Webhooks
District Seal receives webhook events from Dodo Payments to keep subscription state synchronized. This page documents the endpoint, the signature verification scheme, and the events that are processed.
Endpoint
POST https://districtseal.com/api/webhooks/dodo
This endpoint is only called by Dodo Payments. It is not designed for direct use by customers or third-party integrations.
Signature verification
Dodo Payments delivers webhooks using the Svix signature scheme. Every incoming request carries three headers:
| Header | Purpose |
|---|---|
webhook-id | Unique message identifier |
webhook-timestamp | Unix epoch of the delivery attempt |
webhook-signature | HMAC-SHA256 signature, prefixed with v1, |
District Seal verifies the signature on every request as follows:
- Read the signing secret from the environment.
- Strip the
whsec_prefix and base64-decode the secret. - Construct the signed payload as
{msg_id}.{timestamp}.{body}. - Compute an HMAC-SHA256 over that payload using the decoded secret.
- Base64-encode the result and compare it to the value after
v1,in the header. - If the signature does not match, reject with HTTP
401and do not process the event.
401 Unauthorized and are discarded.
Events processed
| Event type | Action taken |
|---|---|
payment.succeeded | For PAYG products, increments the user's signature_credits by the amount purchased. For subscription products, upgrades the plan. |
subscription.active | Sets the user's plan to the corresponding tier (Pro, Firm). |
subscription.renewed | No-op if the plan is unchanged. |
subscription.cancelled | Downgrades the user to the Free plan at the end of the current billing period. |
subscription.expired | Downgrades immediately. |
subscription.failed | Flags the account as past due. A grace period applies before downgrade. |
Metadata conventions
Every subscription and one-time payment created by District Seal includes a metadata object:
{
"metadata": {
"user_id": "41",
"plan": "pro"
}
}
The plan field is pro, firm, or payg. When the webhook fires, the handler looks up the user by the email in the event, then applies the plan or credit change.
Retries and idempotency
Dodo Payments retries failed webhooks with exponential backoff. Because retries may occur, the handler is written to be idempotent: applying the same event twice does not double-credit an account. If you are building an integration that consumes District Seal webhooks, follow the same rule — treat the webhook-id as an idempotency key.
Testing
Dodo Payments provides a webhook replay feature in their dashboard for both test mode and live mode. When testing, use the replay feature rather than crafting your own requests — the signature scheme uses a shared secret and manual requests will fail verification.
District Seal is a product of NEXSIM LLC, Montana, United States.
API support: support@districtseal.com