Webhook API Reference

Complete REST API reference for managing event relay webhook subscriptions to VECU platform events.

Base URL: https://{cip_vecu_config_url}

Authentication

All endpoints require an OAuth2 Bearer token. See Authentication for how to obtain a token.

Include the token in all requests:

Authorization: Bearer YOUR_ACCESS_TOKEN

POST /event-relay/subscriptions

Register a new webhook subscription.

Request Body

urlstringrequired

HTTPS endpoint URL. Must be publicly accessible and pass SSRF validation (no private IPs, no localhost).

authConfigobjectrequired

Authentication configuration. Uses a discriminated union on the type field. See Auth Configurations below.

eventFiltersobject

Event filtering configuration. Defaults to catch-all (deliver everything) if omitted. See Event Filters.

Auth Configurations

HMAC_SHA256 (recommended):

The HMAC secret is auto-generated server-side (256-bit, hex-encoded). You do not provide a secret — the platform generates one and returns it once in the creation response. Store it immediately.

{
  "url": "https://your-app.com/webhooks/vecu",
  "authConfig": {
    "type": "HMAC_SHA256"
  }
}

OAUTH2:

{
  "url": "https://your-app.com/webhooks/vecu",
  "authConfig": {
    "type": "OAUTH2",
    "tokenUrl": "https://auth.your-app.com/oauth/token",
    "clientId": "vecu-relay-client",
    "clientSecret": "client-secret-abc123",
    "scopes": ["webhook.receive"],
    "grantType": "client_credentials"
  }
}
tokenUrlstringrequired

OAuth2 token endpoint. Must use HTTPS.

clientIdstringrequired

OAuth2 client ID.

clientSecretstringrequired

OAuth2 client secret.

scopesstring[]

OAuth2 scopes to request. Defaults to empty.

grantTypestringDefault: client_credentials

OAuth2 grant type.

BEARER:

{
  "authConfig": {
    "type": "BEARER",
    "token": "your-static-bearer-token"
  }
}

BASIC:

{
  "authConfig": {
    "type": "BASIC",
    "username": "webhook_user",
    "password": "secure_password_123"
  }
}

NONE:

Using type: "NONE" means the relay will not authenticate when delivering events to your endpoint. Your endpoint will have no way to verify that requests originate from the VECU platform. This is strongly discouraged for production use -- prefer HMAC_SHA256 or OAUTH2.

{
  "authConfig": {
    "type": "NONE"
  }
}

Response

201 Created

{
  "subscriptionId": "aBcDeFgHiJkLmNoPqRsT",
  "url": "https://your-app.com/webhooks/vecu",
  "authType": "HMAC_SHA256",
  "authConfig": {
    "type": "HMAC_SHA256",
    "secret": "a1b2c3d4e5f6...64-hex-chars"
  },
  "eventFilters": {
    "include": [],
    "exclude": [],
    "patterns": [],
    "productGroups": []
  },
  "status": "active",
  "createdAt": "2026-03-16T14:30:00Z",
  "updatedAt": "2026-03-16T14:30:00Z"
}

For HMAC_SHA256 subscriptions, the authConfig.secret is only returned in plaintext on creation. All subsequent API responses redact the secret. Store it immediately.


GET /event-relay/subscriptions

List all webhook subscriptions for the authenticated client.

Query Parameters

nextTokenstring

Cursor token for pagination. Only present in the response when more results are available. Returns up to 25 subscriptions per page.

Response

200 OK

{
  "items": [
    {
      "subscriptionId": "aBcDeFgHiJkLmNoPqRsT",
      "url": "https://your-app.com/webhooks/vecu",
      "authType": "HMAC_SHA256",
      "authConfig": {
        "type": "HMAC_SHA256"
      },
      "eventFilters": {
        "include": ["custody.*"],
        "exclude": [],
        "patterns": [],
        "productGroups": []
      },
      "status": "active",
      "createdAt": "2026-03-16T14:30:00Z",
      "updatedAt": "2026-03-16T14:30:00Z"
    }
  ],
  "nextToken": "eyJQSyI6..."
}

GET /event-relay/subscriptions/{subscriptionId}

Retrieve details of a specific subscription.

Response

200 OK

{
  "subscriptionId": "aBcDeFgHiJkLmNoPqRsT",
  "url": "https://your-app.com/webhooks/vecu",
  "authType": "HMAC_SHA256",
  "authConfig": {
    "type": "HMAC_SHA256"
  },
  "eventFilters": {
    "include": ["custody.*"],
    "exclude": [],
    "patterns": [],
    "productGroups": []
  },
  "status": "active",
  "createdAt": "2026-03-16T14:30:00Z",
  "updatedAt": "2026-03-16T14:30:00Z"
}

404 Not Found

{
  "code": "404",
  "message": "Subscription not found"
}

PATCH /event-relay/subscriptions/{subscriptionId}

Update an existing subscription. Only include fields you want to change.

Updatable Fields

urlstring

Webhook endpoint URL (re-validated for SSRF and duplicate check).

authConfigobject

Authentication configuration. Credentials are re-encrypted on update. For HMAC_SHA256, a new secret is generated and returned once.

eventFiltersobject

Event subscription filters.

statusstring

active or paused.

Example

curl -X PATCH https://{cip_vecu_config_url}/event-relay/subscriptions/aBcDeFgHiJkLmNoPqRsT \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"status": "paused"}'

Response

200 OK -- Returns the full updated subscription object.


DELETE /event-relay/subscriptions/{subscriptionId}

Delete a subscription. Credentials are deleted with the subscription record.

Response

204 No Content -- Empty body.

404 Not Found -- Subscription does not exist.


Event Filters

Control which events are delivered to your subscription.

Filter Options

{
  "eventFilters": {
    "include": ["custody.vehicle.released", "credential.revoked"],
    "exclude": ["credential.expired"],
    "patterns": ["custody.*"],
    "productGroups": ["CUSTODY_SDK"]
  }
}
includestring[]

Exact event type names to receive.

excludestring[]

Event types to skip (evaluated first, highest priority).

patternsstring[]

Wildcard patterns using * (e.g., custody.*, verification.*).

productGroupsstring[]

Product group names: CUSTODY_SDK or IDV_SDK. Expands to all namespaces in the group.

Evaluation order (short-circuit):

  1. exclude -- if matched, skip
  2. include -- exact match delivers
  3. patterns -- wildcard match delivers
  4. productGroups -- expanded namespace match delivers
  5. All lists empty -- catch-all, delivers everything
  6. No match -- skip

Constraints:

  • Maximum 50 items per list
  • Wildcard only at the end of a segment (custody.* is valid, *.credential.* is not)
  • Empty filter config = catch-all (delivers everything)

Error Responses

HTTP StatusDescription
400Invalid request body or parameters
401Missing or invalid access token
403Access denied (subscription belongs to another client)
404Subscription not found
409URL already registered for this client
500Internal server error

Delivery Behavior

Retry Policy

When your webhook endpoint is unavailable or returns an error, the relay retries delivery automatically:

  • 6 attempts total with exponential backoff
  • Retried: HTTP 5xx responses, HTTP 429 responses, connection timeouts
  • Not retried: HTTP 4xx responses (except 429) — these indicate a client-side rejection
  • Events that exhaust all retries are moved to a dead letter queue (DLQ)

The X-VECU-Retry-Count request header on each delivery indicates how many previous attempts were made (0 for first attempt).

At-Least-Once Delivery

The relay provides at-least-once delivery semantics. In rare cases (network retries, regional failover), your endpoint may receive the same event more than once. Use the CloudEvents id field (also available as X-VECU-Event-ID header) for deduplication.

Delivery Timeout

Your endpoint must respond within 30 seconds. Requests that do not receive a response within this window are treated as failures and trigger a retry.