Cost+ Docs

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

  1. You specify a webhook_url when creating an order, or configure a default webhook URL at the project level.
  2. When the order status changes (e.g., from new to completed), Cost+ sends a POST request to your webhook URL.
  3. Your server receives the webhook, then calls the Cost+ API to retrieve the full order details.
  4. 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"
}
FieldDescription
eventThe type of event. Currently status_changed for order updates.
order_idThe unique identifier of the order whose status changed.
project_idThe 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_url in 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 OK response.

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 200 response 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.

On this page