KDPika Licensing Sign inStart free
API v1
Show all languages
Browse documentation

Choose a page in the navigation drawer.

KDPika Licensing · API v1 Intermediate

Idempotency and uncertain outcomes

Choose stable creation keys, understand actual 24-hour replay limits, and avoid repeating uncertain license mutations.

On this page
Updated 2026-10-17 UTCDownload Markdown

Deduplicate your business events durably; the current API creation key is useful but does not guarantee exactly-once fulfillment.

What you will learn

  • Choose stable keys and identical retry bodies.
  • Understand expiry, concurrency and duplicate-work defects.
  • Handle store fulfillment and renewal uncertainty without guessing.

Prerequisites

Creation key contract

POST /api/v1/licenses requires an Idempotency-Key header with 8–190 trimmed characters. The key is scoped to the whole organization. Include a stable product/store/event identity so unrelated operations cannot collide. Store event IDs are input to your own mapping; KDPika does not verify an external store event here.

The retained response lasts 24 hours. Reusing the unexpired key and identical decoded-body hash returns the original 201 body, including the original request_id and plaintext newly issued license key, plus Idempotent-Replay:true. X-Request-ID identifies the current request. A different hash returns 409 IDEMPOTENCY_CONFLICT.

The server hashes PHP JSON encoding of the decoded body. JSON whitespace is decoded away, but object member order is retained and can change the hash. Unknown fields also affect the hash even if creation ignores them. Serialize one stable request and retain its exact business meaning; do not regenerate/reorder customer fields between retries.

Known limitations: not exactly once

An expired row before cleanup can be missed by the lookup and then collide with the unique insert after a new license commits. The caller receives 500 and a duplicate license can exist. Simultaneous same-key requests can both pass the lookup and commit separate licenses; one response then fails storing the idempotency record. Both issues are reproduced in isolated Sandbox tests and remain unchanged.

Do not reissue with a fresh key simply because a request timed out or returned 500. Use your durable fulfillment mapping and support to reconcile uncertain creation. No public license-list/customer-search endpoint exists to reconstruct that mapping automatically. A management GET can reconcile only when you already retained the license ID. These limitations make unattended exactly-once payment fulfillment unsupported without an approved product fix.

Retry safety by operation

OperationIdempotency-Key behaviorClient decision
GET /api/v1/public-keyIgnored / no replaySafe bounded read retry
POST /api/v1/licensesRequired; retained response with known defectsReconcile uncertain result before another write
POST /api/v1/licenses/activateIgnored / no replayReconcile uncertain result before another write
POST /api/v1/licenses/validateIgnored / no replayToken/last-seen refresh; coordinate retries
POST /api/v1/licenses/deactivateIgnored / no replayReconcile uncertain result before another write
GET /api/v1/licenses/{license}Ignored / no replaySafe bounded read retry
POST /api/v1/licenses/{license}/revokeIgnored / no replayReconcile uncertain result before another write
POST /api/v1/licenses/{license}/suspendIgnored / no replayReconcile uncertain result before another write
POST /api/v1/licenses/{license}/restoreIgnored / no replayReconcile uncertain result before another write
POST /api/v1/licenses/{license}/renewIgnored / no replayReconcile uncertain result before another write
POST /api/v1/licenses/{license}/reset-devicesIgnored / no replayReconcile uncertain result before another write

Activation rotates tokens even on an existing ACTIVE installation. Renewal extends time on every accepted call. Deactivation repeats401; repeated status/reset actions can repeat events. Database row locks serialize updates but do not identify a repeated external business event.

Durable fulfillment example

For a verified event such as YOUR_STORE_EVENT_ID, persist a fulfillment row under a unique key of store/account/product/event. Save the normalized request, intended action and state before calling the API. Serialize workers on that row; do not use process-local locks as durable deduplication.

  1. Verify the store webhook or server-side purchase with your own provider integration. Expected: authenticated event, not a success-page query string.
  2. Acquire the unique durable fulfillment row. Expected: only one worker owns this event; an already completed row returns its saved license mapping without another API call.
  3. Use a stable creation key such as store:YOUR_STORE_ACCOUNT:YOUR_PRODUCT:YOUR_STORE_EVENT_ID. Expected: an 8–190 character key with no buyer email or card data.
  4. Send the saved normalized JSON to the create operation. Expected: a documented201 with a new license ID/key, or an explicit error.
  5. Persist the license mapping and secret-delivery state atomically in your system. Expected: subsequent deliveries reuse the durable record, not another API creation.
  6. Mark any timeout/500 as uncertain and reconcile before releasing another write. Expected: no automatic duplicate issuance or renewal. Do not claim a provider charged the buyer unless your provider data confirms it.

A stable illustrative request key is YOUR_STORE_EVENT_ID, not a new random value on every retry. Use your provider account in the dedupe namespace when event IDs are not globally unique. This is a workflow specification, not a new provider integration or a fake payment example. Store-specific tested integration code belongs to the separate integration guides.

Renewal requires its own deduplication

Persist each verified renewal event and expected old/new expiration before calling renew. Renew has no replay key. If a response is lost, compare a known license summary and your durable record; do not add the same days automatically a second time. Concurrent unrelated renewals need deliberate business serialization, because merely reading then writing is not compare-and-swap.

Retention and secrecy

The server currently stores the complete creation response, including plaintext license_key, in its idempotency record for 24 hours; cleanup depends on a functioning scheduler. Treat database access/backups as sensitive. Your own customer-key delivery must be authorized and confidential. The API does not automatically email the key to the buyer.

Expected result

A replayed business event does not trigger an intentional second write from your worker, and uncertain outcomes are surfaced for reconciliation.

Common mistakes

  • Choosing a new random header for every attempt of the same event.
  • Assuming renew supports the creation replay mechanism.
  • Advertising exactly-once fulfillment despite the current expiry/concurrency defects.

Security notes

Verify purchases on your backend. Never put provider secrets or developer API keys in buyer applications. Keep replay bodies and fulfillment records private.

Troubleshooting

SymptomCauseAction
409 IDEMPOTENCY_CONFLICTDifferent decoded request hash/member orderUse the saved original request; do not hide the conflict with a new key
500 after createUncertain work, including documented replay defectsReconcile; retain current/original request IDs
Expiry extended twiceSame renewal event repeated without durable dedupeInvestigate the event mapping; do not automate further extensions

Next steps

Review the endpoint reference and signature verification.

Was this page helpful?

Choose an answer

Do not include personal data, license keys or credentials. Retained for up to 30 days. This is not a support inbox.

Search documentation

Arrow keys to move, Enter to open, Escape to close. Search stays in your browser.

Cookie settings