Developers For developers · Updated May 27, 2026

Webhooks: setup, events and troubleshooting

Webhooks let Arca notify your server in real time when something happens — a payment succeeds, an invoice fails, a subscription is canceled. This guide covers registering a URL, the events you can receive, and how to handle delivery reliably.

Registering a webhook URL

Send a request to the webhook-URLs endpoint with your API token and tenant header:

FieldValue
EndpointPOST /webhook-urls
HeadersAuthorization: Bearer <token> and tenant: <your tenant id>
Body{ "url": "https://your-server.com/webhook", "isActive": true }

The event payload

Each event is delivered as a JSON POST:

FieldDescription
eventNameWhich event fired, e.g. subscriptions.payment_failed
objectThe full record the event is about (transaction, invoice, subscription, etc.)
tenantId / googleTenantIdYour account identifiers — use these to verify the event (see below)

Respond with HTTP 200 (any 2xx) to acknowledge receipt.

Verifying events: Arca does not sign webhooks. The only origin check is the tenant identifier in the payload — your handler should confirm tenantId (or googleTenantId) matches your account and reject anything that doesn't. Always use an HTTPS endpoint, and a hard-to-guess URL path adds protection.

Event types

The most useful events, by area (this is a subset — the full set also covers products, prices, coupons, credit notes, and partners):

AreaEvents
Payments & transactionstransactions.succeeded, transactions.failed, transactions.pending, transactions.refunded, transactions.partial_refund, transactions.voided, transactions.disputed
Invoicesinvoices.paid, invoices.payment_succeeded, invoices.payment_failed, invoices.finalized, invoices.voided, invoices.refunded, invoices.created_from_subscription
Subscriptionssubscriptions.created, subscriptions.updated, subscriptions.canceled, subscriptions.paused, subscriptions.payment_succeeded, subscriptions.payment_failed, subscriptions.payment_collection_paused, subscriptions.payment_collection_resumed
Ordersorders.paid, orders.canceled, orders.voided, orders.refunded, orders.payment_failed
Payment linkspayment_links.created, payment_links.activated, payment_links.deactivated, payment_links.order_created
Customerscustomers.created, customers.updated, customer_cards.created, customer_cards.updated

Delivery and retries

Common problems

1

Webhook never arrives

Cause

The URL is inactive, was registered under the wrong tenant, or your endpoint isn't reachable from the public internet.

Solution

Call GET /webhook-urls to confirm the URL exists, is active, and is under the right tenant; make sure the endpoint is a public HTTPS address.

2

Events still go to an old URL after it changed

Cause

There's no automatic re-sync — a registered URL stays until you change it.

Solution

PATCH /webhook-urls/:id with the new URL, or delete the old one and register the new one. Re-registering the same URL returns a 409 (already exists).

3

Receiving duplicate deliveries

Cause

Delivery is at-least-once, so retries or a slow-but-successful response can cause the same event to arrive twice.

Solution

Make the handler idempotent — de-duplicate on the object id plus eventName — and acknowledge quickly (well under 30 seconds).

4

Your server rejects events (tenant mismatch)

Cause

Your verification expects a different tenant id, or you're mixing sandbox and production.

Solution

Confirm the tenant id your handler checks exactly matches the account that registered the URL; accept both tenantId and googleTenantId.

5

Events stop after your endpoint returned an error

Cause

A 4xx response is permanent (no retry); 5xx and timeouts retry up to 3 times, then stop.

Solution

Return 2xx as soon as you accept an event. Return 5xx only when you actually want a retry; never return 4xx for a temporary problem.

Error reference (registration)

CodeMeaningWhat to do
401 UnauthorizedMissing or invalid API tokenSend a valid Authorization: Bearer token
403 ForbiddenNo permission, or tenant check failedUse a key with webhook permission and the correct tenant
400 Bad RequestMissing/invalid tenant header or invalid URLInclude the tenant header; use a valid HTTPS URL ≤200 chars
409 ConflictThat URL is already registeredUpdate the existing one instead of re-adding
404 Not FoundThe webhook URL id doesn't existCheck the id from GET /webhook-urls

Still having trouble?

Contact Arca support and include: