Webhooks
Receive real-time payment status notifications
Webhooks allow Cost+ to notify your server in real time whenever an order's status changes. Instead of polling the API, you provide a URL and Cost+ sends an HTTP POST request to it whenever there is an update.
How Webhooks Work
- You specify a
webhook_urlwhen creating an order, or configure a default webhook URL at the project level. - When the order status changes (e.g., from
newtocompleted), Cost+ sends a POST request to your webhook URL. - Your server receives the webhook, then calls the Cost+ API to retrieve the full order details.
- You update your system based on the verified order status.
[!WARNING] Never trust the webhook payload alone to fulfill an order. Always verify the order status by making a GET /v1/orders/{id}/ request after receiving a webhook. The webhook is a notification mechanism, not a source of truth.
Webhook Payload
The webhook body is a JSON object containing the event type and the order ID:
{
"event": "status_changed",
"order_id": "b9ae6...",
"project_id": "proj_abc123"
}| Field | Description |
|---|---|
event | The type of event. Currently status_changed for order updates. |
order_id | The unique identifier of the order whose status changed. |
project_id | The project that the order belongs to. |
Setting the Webhook URL
You can set the webhook URL in two ways:
Per-Order
Include the webhook_url field when creating an order:
{
"currency": "EUR",
"amount": 1295,
"webhook_url": "https://www.example.com/webhook"
}Project Default
Configure a default webhook URL in your Cost+ dashboard under project settings. This URL will be used for all orders that do not specify their own webhook_url.
[!TIP] Even if you have a project-level default, you can override it on a per-order basis by including
webhook_urlin the order creation request.
Retry Logic
If your server does not respond with a 2xx status code, Cost+ retries the webhook delivery:
- Maximum retries: 10 attempts
- Retry interval: 2 minutes between each attempt
- First attempt timeout: 4 seconds
- Subsequent attempt timeout: 10 seconds
If all 10 retry attempts fail, the webhook is marked as failed. You can still retrieve the order status at any time by polling the API.
[!NOTE] Make sure your webhook endpoint responds quickly (within 4 seconds for the first attempt). Perform any long-running processing asynchronously after returning a
200 OKresponse.
Best Practices
- Always verify via API. Upon receiving a webhook, call
GET /v1/orders/\{order_id\}/to confirm the current status before taking action such as shipping goods or granting access. - Return 200 quickly. Acknowledge the webhook with a
200response immediately and process the order asynchronously to avoid timeouts. - Handle duplicates. Your webhook endpoint may receive the same event more than once. Ensure your processing logic is idempotent.
- Use HTTPS. Always use an HTTPS URL for your webhook endpoint to ensure the payload is transmitted securely.
- Log webhook payloads. Store incoming webhook data for debugging and audit purposes.