SyncGuard Docs

Quick Start

From zero to your first incident alert in under 5 minutes. No SDK required — SyncGuard is a plain REST API.

1. Create a workspace

bash
curl -X POST https://api.syncguard.io/api/v1/workspaces \
  -H "Authorization: Bearer <your_jwt>" \
  -H "Content-Type: application/json" \
  -d '{"name": "My Team"}'
json
{
  "isSuccess": true,
  "data": {
    "workspace": {
      "id": "3fa1c2d4-...",
      "name": "My Team",
      "apiKeyPrefix": "sg_a3f9d2c",
      "isActive": true
    },
    // Store this — it will not be shown again
    "apiKey": "sg_a3f9d2c814e77b9f5a6d3e2c0b1f8e4d7a9c5b3"
  }
}

2. Send your first event

bash
curl -X POST https://api.syncguard.io/api/v1/events \
  -H "X-Api-Key: sg_a3f9d2c814e77b9f5a6d3e2c0b1f8e4d7a9c5b3" \
  -H "Content-Type: application/json" \
  -d '{
    "integrationKey": "payments-service",
    "eventType": "token_refresh_failed",
    "errorCode": "401",
    "tenantId": "acme-corp"
  }'
json
{
  "isSuccess": true,
  "data": {
    "eventId": "b2e3a1f4-...",
    "incidentId": "inc_8f2a1c9d-...",
    "incidentStatus": "Open",
    "patternId": "auth_failure",
    "confidence": "High",
    "isNewIncident": true
  }
}
That's it. SyncGuard matched the event to the auth_failure pattern, opened an incident, and will alert your configured channels automatically.

Authentication

All client API calls are authenticated with an API key. You get your key when you create a workspace — it is shown only once, so store it securely.

API Key

Pass the key in the X-Api-Key header on every request. Keys always start with sg_ followed by 48 hex characters.

bash
curl -X POST https://api.syncguard.io/api/v1/events \
  -H "X-Api-Key: sg_a3f9d2c814e77b9f5a6d3e2c0b1f8e4d7a9c5b3" \
  -H "Content-Type: application/json" \
  -d '{ ... }'

Rotate your key

If a key is compromised, rotate it immediately. The old key stops working the instant the new one is issued.

bash
curl -X POST https://api.syncguard.io/api/v1/workspaces/rotate-key \
  -H "X-Api-Key: sg_a3f9d2c814e77b9f5a6d3e2c0b1f8e4d7a9c5b3"
json
{
  "isSuccess": true,
  "data": {
    "workspace": { "id": "3fa1c2d4-...", "name": "My Team", "apiKeyPrefix": "sg_b9e1f3a" },
    // New key — shown once, store it now
    "apiKey": "sg_b9e1f3a0c2d4e6f8a0b2c4d6e8f0a2b4c6d8e0f2"
  }
}
Never commit API keys to source control. Use environment variables: SYNCGUARD_API_KEY=sg_...

Send Events

POST /api/v1/events is the core endpoint. It runs the 3-stage pipeline: resolve tenant → classify pattern → open or update incident.

Request body

json
{
  // Required
  "integrationKey": "payments-service",   // groups related events into incidents
  "eventType": "webhook_failed",          // matched against pattern triggers
  "tenantId": "acme-corp",               // your customer's external ID

  // Optional — improves confidence scoring
  "errorCode": "503",
  "rawPayload": {                         // any additional context (stored as JSONB)
    "endpoint": "/v2/webhooks/deliver",
    "durationMs": 12043,
    "attemptNumber": 3
  }
}

Successful response — new incident opened

json
{
  "isSuccess": true,
  "data": {
    "eventId": "b2e3a1f4-7c8d-4e9f-a1b2-c3d4e5f6a7b8",
    "incidentId": "9d8c7b6a-5e4f-3d2c-1b0a-f9e8d7c6b5a4",
    "incidentStatus": "Open",
    "patternId": "webhook_failure_spike",
    "confidence": "High",
    "isNewIncident": true,
    "affectedTenants": ["acme-corp"]
  }
}

Event grouped into existing incident

json
{
  "isSuccess": true,
  "data": {
    "eventId": "a1b2c3d4-...",
    "incidentId": "9d8c7b6a-...",  // same incident
    "incidentStatus": "Open",
    "patternId": "webhook_failure_spike",
    "confidence": "High",
    "isNewIncident": false,         // grouped, not opened again
    "affectedTenants": ["acme-corp", "beta-ltd"]  // now 2 tenants
  }
}

Rate limit exceeded

json
{
  "isSuccess": false,
  "statusCode": 429,
  "message": "Rate limit exceeded. Try again in 43 seconds."
  // Retry-After header is also set
}

Patterns

Twelve built-in patterns cover the most common integration failure modes. Evaluated in priority order — first match wins. You enable/disable per workspace and optionally set custom alert thresholds.

Pattern IDPriorityTriggers on
auth_failure1token_refresh_failed · auth_failed · errorCode 401/403/invalid_grant/token_expired
webhook_failure_spike2webhook_failed · webhook_timeout · webhook_undeliverable · ≥10 events / 5 min
rate_limit_exceeded3rate_limit_exceeded · throttled · errorCode 429/rate_limit/too_many_requests
timeout_spike4request_timeout · connection_timeout · gateway_timeout · ≥5 events / 3 min
task_canceled_spike5task_canceled · operation_canceled · request_canceled · ≥5 events / 3 min
validation_failure_spike6validation_failed · schema_validation_failed · payload_invalid · errorCode 400/422
server_error_spike7server_error · bad_gateway · service_unavailable · errorCode 500/502/503/504
connection_failure8connection_failed · connection_refused · connection_reset · host_unreachable · errorCode econnrefused/econnreset · ≥3 events / 2 min
service_unavailable9service_unavailable · dependency_failed · circuit_open · upstream_unavailable · errorCode 503/circuit_open
data_sync_failure10sync_failed · sync_error · data_sync_failed · record_sync_failed · batch_sync_failed · errorCode sync_error/data_mismatch/mapping_error/duplicate_record
ssl_certificate_error11ssl_error · tls_error · certificate_error · tls_handshake_failed · certificate_expired · errorCode ssl_error/certificate_expired/hostname_mismatch
quota_exceeded12quota_exceeded · limit_reached · storage_full · seats_exhausted · resource_exhausted · errorCode quota_exceeded/storage_full/over_quota/account_limit

Confidence scoring

json
// High   — both eventType AND errorCode match
// Medium — only one of the two matches
// (Spike patterns are always High confidence)

{
  "eventType": "auth_failed",   // ✓ matches auth_failure
  "errorCode": "401"            // ✓ matches auth_failure
  // → confidence: "High"
}

{
  "eventType": "auth_failed",   // ✓ matches auth_failure
  "errorCode": "500"            // ✗ not an auth error code
  // → confidence: "Medium"
}

Set a custom alert threshold

bash
curl -X PATCH https://api.syncguard.io/api/v1/patterns/webhook_failure_spike \
  -H "X-Api-Key: sg_..." \
  -H "Content-Type: application/json" \
  -d '{
    "isEnabled": true,
    "thresholdCount": 20,
    "thresholdWindowSeconds": 300
  }'

With a threshold set, the incident opens silently. The alert fires only once the event count inside the window reaches thresholdCount.

Incidents

Incidents are opened automatically by the pipeline. They follow a strict lifecycle managed by background timers — no manual state flipping required.

Lifecycle

json
// Open        → new event matched a pattern, threshold met
// Recovering  → no new events for RecoveryWindow (default 5 min)
// Closed      → stable during CloseWindow (default 10 min)

// Reopened    → new event arrives within CooldownWindow (15 min) after Close
//               → same incident is reused, ReopenCount++

// Manually resolved at any time via POST /incidents/{id}/resolve

Full incident object

json
{
  "id": "9d8c7b6a-5e4f-3d2c-1b0a-f9e8d7c6b5a4",
  "workspaceId": "3fa1c2d4-...",
  "integrationKey": "payments-service",
  "patternId": "auth_failure",
  "patternName": "Auth Failure",
  "status": "Open",             // Open | Recovering | Closed
  "confidence": "High",
  "openedAt": "2025-03-26T08:14:22Z",
  "recoveringAt": null,
  "closedAt": null,
  "reopenedAt": null,
  "reopenCount": 0,
  "eventCount": 14,
  "tenantCount": 3,
  "isChronic": false,           // true when reopenCount >= 3
  "affectedTenants": [
    { "tenantId": "...", "tenantName": "acme-corp",  "eventCount": 9, "firstSeenAt": "...", "lastSeenAt": "..." },
    { "tenantId": "...", "tenantName": "beta-ltd",   "eventCount": 4, "firstSeenAt": "...", "lastSeenAt": "..." },
    { "tenantId": "...", "tenantName": "gamma-inc",  "eventCount": 1, "firstSeenAt": "...", "lastSeenAt": "..." }
  ]
}

List incidents with filters

bash
# Active (Open + Recovering) — default
curl "https://api.syncguard.io/api/v1/incidents" \
  -H "X-Api-Key: sg_..."

# Closed, paginated
curl "https://api.syncguard.io/api/v1/incidents?status=closed&page=1&pageSize=25" \
  -H "X-Api-Key: sg_..."

# Filter by integration key
curl "https://api.syncguard.io/api/v1/incidents?integrationKey=payments-service" \
  -H "X-Api-Key: sg_..."

# Chronic incidents only (reopened 3+ times)
curl "https://api.syncguard.io/api/v1/incidents?chronic=true" \
  -H "X-Api-Key: sg_..."

Incident timeline

json
// GET /incidents/{id}/timeline
[
  { "fromStatus": null,         "toStatus": "Open",       "reason": "Pattern matched: auth_failure", "occurredAt": "2025-03-26T08:14:22Z" },
  { "fromStatus": "Open",       "toStatus": "Recovering", "reason": "No events for 5 min",          "occurredAt": "2025-03-26T08:19:22Z" },
  { "fromStatus": "Recovering", "toStatus": "Open",       "reason": "New event during recovery",    "occurredAt": "2025-03-26T08:21:05Z" },
  { "fromStatus": "Open",       "toStatus": "Recovering", "reason": "No events for 5 min",          "occurredAt": "2025-03-26T08:26:05Z" },
  { "fromStatus": "Recovering", "toStatus": "Closed",     "reason": "Stable for 10 min",            "occurredAt": "2025-03-26T08:36:05Z" }
]

Alerts

SyncGuard fires alerts automatically at each lifecycle transition. Configure channels once per workspace — no per-incident wiring needed.

Configure Slack

bash
curl -X PUT https://api.syncguard.io/api/v1/workspaces/me/channels/slack \
  -H "X-Api-Key: sg_..." \
  -H "Content-Type: application/json" \
  -d '{
    "config": { "webhookUrl": "https://hooks.slack.com/services/T.../B.../..." },
    "isEnabled": true
  }'

Configure PagerDuty

bash
curl -X PUT https://api.syncguard.io/api/v1/workspaces/me/channels/pagerduty \
  -H "X-Api-Key: sg_..." \
  -H "Content-Type: application/json" \
  -d '{
    "config": { "routingKey": "R01ABCDEF1234567890ABCDEF12345678" },
    "isEnabled": true
  }'

Configure OpsGenie

bash
curl -X PUT https://api.syncguard.io/api/v1/workspaces/me/channels/opsgenie \
  -H "X-Api-Key: sg_..." \
  -H "Content-Type: application/json" \
  -d '{
    "config": { "apiKey": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" },
    "isEnabled": true
  }'
Alert events fired
Incident opened

First time a pattern threshold is met

Incident reopened

New event during Recovering state

Incident resolved

Closed after stable CloseWindow

Blast radius expanded

A new tenant is affected in the current incident cycle

API Reference

All endpoints share the base URL https://api.syncguard.io/api/v1. Responses use OperationResult<T> — always check isSuccess.

MethodPath
POST/auth/register
POST/auth/login
POST/auth/token
POST/workspaces
GET/workspaces/me
PATCH/workspaces/me
POST/workspaces/rotate-key
GET/workspaces/stats
GET/workspaces/trends
PUT/workspaces/me/channels/{provider}
DELETE/workspaces/me/channels/{provider}
POST/events
GET/events
GET/incidents
GET/incidents/{id}
POST/incidents/{id}/resolve
GET/incidents/{id}/timeline
GET/patterns
PATCH/patterns/{id}
GET/tenants
POST/tenants
DELETE/tenants/{id}
POST/tenants/{id}/activate

Response envelope

json
{
  "isSuccess": true,
  "errorCode": 0,           // 0 = Success
  "message": "...",
  "data": { ... }           // present on success responses
}

// Error example
{
  "isSuccess": false,
  "errorCode": 4,           // ValidationError
  "message": "integrationKey is required."
}