# Synctera Webhooks

## When to Use This Skill

* How do I receive Synctera webhooks?
* How do I verify Synctera webhook signatures (`Synctera-Signature`)?
* How do I handle `ACCOUNT.UPDATED` or `TRANSACTIONS.POSTED.CREATED` events?
* Why is my Synctera webhook signature verification failing?
* How do I generate a Synctera webhook signing secret?

## Verification (core)

Synctera uses a custom HMAC scheme (not Standard Webhooks). Each delivery has two headers:

* `Synctera-Signature` — the hex-encoded signature (two `.`-delimited signatures during secret rotation)
* `Request-Timestamp` — POSIX seconds used in the signed string

The signed string is ``${Request-Timestamp}.${raw_body}`` (the `.` is a literal separator). Compute `HMAC-SHA256(secret, signed_string)` and hex-encode. The secret is not your API key — generate it with `POST /v0/webhook_secrets` (empty body) and store it. Verify against the raw body; don't `JSON.parse` first.

```javascript
const crypto = require('crypto');

// secret comes from POST /v0/webhook_secrets (NOT your API key)
function verifySynctera(rawBody, signatureHeader, timestamp, secret, toleranceSec = 300) {
  if (!signatureHeader || !/^\d+$/.test(String(timestamp))) return false;

  // Replay protection: Request-Timestamp must be within 5 minutes of now
  const now = Math.floor(Date.now() / 1000);
  if (Math.abs(now - Number(timestamp)) > toleranceSec) return false;

  // HMAC over `${timestamp}.${rawBody}` — the "." is a literal separator
  const expected = crypto.createHmac('sha256', secret)
    .update(`${timestamp}.${rawBody}`).digest('hex');

  // During a rolling secret, the header holds two "."-delimited signatures
  return signatureHeader.split('.').some((sig) => {
    try { return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)); }
    catch { return false; }
  });
}

```

> For complete handlers with route wiring, event dispatch, and tests, see:
> 
> * [examples/express/](https://github.com/hookdeck/webhook-skills/tree/main/skills/synctera-webhooks/examples/express/)
> * [examples/nextjs/](https://github.com/hookdeck/webhook-skills/tree/main/skills/synctera-webhooks/examples/nextjs/)
> * [examples/fastapi/](https://github.com/hookdeck/webhook-skills/tree/main/skills/synctera-webhooks/examples/fastapi/)

## Common Event Types

Event names use the format `<resource>.[<sub-resource>.]<action>`. Wildcards like `CUSTOMER.*` auto-subscribe to all current and future events under a resource. The three-segment `TRANSACTIONS.POSTED.CREATED` shows the optional sub-resource case.

> Only `ACCOUNT.UPDATED` and `TRANSACTIONS.POSTED.CREATED` are verified names. The others below are illustrative of the format only — confirm the exact spelling against Synctera's docs or your own webhook config before subscribing or switching on them. Do not treat this as an authoritative catalog.

| Event | Verified? | Triggered When |
| --- | --- | --- |
| `ACCOUNT.UPDATED` | ✅ verified | An account changed (status, balance limits, etc.) |
| `TRANSACTIONS.POSTED.CREATED` | ✅ verified | A posted transaction was recorded (note plural `TRANSACTIONS`, three segments) |
| `CARD.CREATED` | illustrative | A card was issued (confirm name) |
| `CARD.UPDATED` | illustrative | A card changed — status, activation (confirm name) |
| `DISPUTE.CREATED` | illustrative | A dispute was opened (confirm name) |
| `CUSTOMER.*` | illustrative | Any customer event (wildcard form) |

> For the full event reference, see [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/synctera-webhooks/references/overview.md) and Synctera's [Webhooks guide](https://docs.synctera.com/docs/webhooks-guide).

## Environment Variables

```bash
# Signing secret from POST /v0/webhook_secrets (NOT your API key)
SYNCTERA_WEBHOOK_SECRET=your_signature_secret_here

```

## Local Development

```bash
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 synctera --path /webhooks/synctera

```

## Reference Materials

* [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/synctera-webhooks/references/overview.md) - Synctera webhook concepts and event types
* [references/setup.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/synctera-webhooks/references/setup.md) - Create the secret and register endpoints via the API
* [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/synctera-webhooks/references/verification.md) - Signature verification details and gotchas