Aller au contenu principal

Webhooks

STOA Platform can notify external systems when subscription lifecycle events occur. Webhooks deliver HTTP POST requests to your endpoints with signed payloads.

Event Types

EventTriggerPayload Includes
subscription.createdNew subscription requestSubscription ID, API, consumer, plan
subscription.approvedSubscription approved by adminSubscription ID, API key (if generated)
subscription.revokedSubscription revokedSubscription ID, reason
subscription.key_rotatedAPI key rotatedSubscription ID, new key prefix
subscription.expiredSubscription TTL expiredSubscription ID, expiry date

Use ["*"] to subscribe to all event types.

Creating a Webhook

Via API

Configure your environment

The examples below use environment variables. Set them for your STOA instance:

export STOA_API_URL="https://api.gostoa.dev"       # Replace with your domain
export STOA_AUTH_URL="https://auth.gostoa.dev" # Keycloak OIDC provider
export STOA_GATEWAY_URL="https://mcp.gostoa.dev" # MCP Gateway endpoint

Self-hosted? Replace gostoa.dev with your domain.

curl -X POST "${STOA_API_URL}/v1/tenants/{tenant_id}/webhooks" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-system.example.com/stoa-events",
"events": ["subscription.created", "subscription.approved"],
"secret": "your-hmac-secret-min-32-chars-long",
"enabled": true,
"custom_headers": {
"X-Source": "stoa-platform"
}
}'

Via Portal

  1. Navigate to Webhooks in the Portal sidebar
  2. Click Create Webhook
  3. Enter the target URL and select event types
  4. Set a signing secret (min 32 characters)
  5. Optionally add custom headers
  6. Click Save

Payload Format

Every webhook delivery sends a JSON payload:

{
"event": "subscription.approved",
"timestamp": "2026-02-13T10:30:00Z",
"webhook_id": "wh_abc123",
"data": {
"subscription_id": "sub_xyz789",
"api_id": "api_456",
"api_name": "Payment API",
"consumer_id": "consumer_012",
"plan": "standard",
"status": "approved"
}
}

HMAC-SHA256 Signature Verification

Every delivery includes a signature header for payload verification:

X-STOA-Signature: sha256=<hex-encoded-hmac>

Verification Example (Python)

import hmac
import hashlib

def verify_signature(payload: bytes, secret: str, signature_header: str) -> bool:
expected = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
received = signature_header.removeprefix("sha256=")
return hmac.compare_digest(expected, received)

Verification Example (Node.js)

const crypto = require('crypto');

function verifySignature(payload, secret, signatureHeader) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
const received = signatureHeader.replace('sha256=', '');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(received)
);
}

Always use timing-safe comparison to prevent timing attacks.

Retry Policy

Failed deliveries (non-2xx response or timeout) are retried with exponential backoff:

AttemptDelayCumulative Wait
1Immediate0
21 minute1 min
35 minutes6 min
415 minutes21 min
51 hour1h 21min

After 5 failed attempts, the delivery is marked as failed. No further retries are attempted automatically.

Delivery Tracking

View Delivery History

curl "${STOA_API_URL}/v1/tenants/{tenant_id}/webhooks/{webhook_id}/deliveries" \
-H "Authorization: Bearer $TOKEN"

Each delivery record includes:

FieldDescription
statussuccess, failed, pending
status_codeHTTP response code from your endpoint
response_bodyFirst 1KB of response (for debugging)
attemptAttempt number (1-5)
created_atDelivery timestamp

Retry a Failed Delivery

curl -X POST "${STOA_API_URL}/v1/tenants/{tenant_id}/webhooks/{webhook_id}/deliveries/{delivery_id}/retry" \
-H "Authorization: Bearer $TOKEN"

Testing Webhooks

Send a test event to verify your endpoint before going live:

curl -X POST "${STOA_API_URL}/v1/tenants/{tenant_id}/webhooks/{webhook_id}/test" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"event_type": "subscription.created"}'

The test delivery uses synthetic data and is marked as test: true in the payload.

Managing Webhooks

List Webhooks

curl "${STOA_API_URL}/v1/tenants/{tenant_id}/webhooks" \
-H "Authorization: Bearer $TOKEN"

Disable a Webhook

curl -X PATCH "${STOA_API_URL}/v1/tenants/{tenant_id}/webhooks/{webhook_id}" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled": false}'

Delete a Webhook

curl -X DELETE "${STOA_API_URL}/v1/tenants/{tenant_id}/webhooks/{webhook_id}" \
-H "Authorization: Bearer $TOKEN"

Best Practices

  1. Always verify signatures — reject unsigned or incorrectly signed payloads
  2. Respond quickly — return 200 within 5 seconds; process asynchronously
  3. Handle duplicates — use webhook_id + timestamp for idempotency
  4. Use HTTPS — webhook URLs must use TLS in production
  5. Rotate secrets — update the webhook secret periodically via PATCH
  6. Monitor deliveries — check the Portal delivery history for failures