Request idempotency
Send anIdempotency-Key with every POST request:
OAuth REST-hook creation has a resource-lifecycle exception. For
POST /webhooks, the idempotency key remains bound to the live subscription until
that row is deleted, and a retry returns its signing secret. The event set
must stay the same; apply a current callback URL, card, live/test mode, or
active state with PATCH /webhooks/:id. Deleting the subscription releases
the key immediately.Permanent transaction deduplication
POS and commerce integrations should also sendtransaction.external_transaction_id to /marketplace/accrue.
idempotent_replay: true.
Use an upstream ID that is:
- stable across webhook retries;
- unique to one loyalty operation;
- available again when a refund must reverse the operation; and
- namespaced when several stores can produce the same numeric order ID.
odoo:shop_12:pos_order:94721
Risky: 94721
Keep test and live references in separate namespaces, for example
test:odoo:shop_12:pos_order:94721 and
live:odoo:shop_12:pos_order:94721. Perkstar rejects a permanent transaction
reference that already belongs to the other environment instead of silently
replaying it.
Retry policy
A practical schedule is 1 second, 2 seconds, 4 seconds, then a background retry
queue. Cap attempts and surface terminal failures for an operator to inspect.
Reversals
Reverse a transaction by Perkstar ID or by its originalexternal_transaction_id. Give the reversal its own idempotency key. Test and
live transactions cannot be reversed across environments. Use an identifier
namespace owned by your integration; provider-managed prefixes such as
sq_payment_ are reserved.
