CEEJAYDocs

Complete a shop delivery

Tell CEEJAY that a shop item your server was delivering has been delivered, or that delivery failed.

POST /v1/shop/purchases/{id}/complete · requires shop:fulfil

Use it when a shop item set to Delivered by your API is awaiting confirmation from your server: your server responded to the delivery request with 202, or with { "status": "pending" }, and you now know the result. Deliver shop items from your own platform explains the whole flow, and List shop purchases lists the purchases that await your confirmation.

Path parameters

Prop

Type

Body parameters

Prop

Type

Returns

Prop

Type

These fields are inside data. Alongside success, the response also includes the original fields, which remain for as long as version 1 exists: purchaseId, status, alreadyDone (only when it is true) and refunded (only on the call that makes the refund).

Example

Request
curl -X POST https://ceejay.communitystudios.xyz/api/v1/shop/purchases/4242/complete \
  -H "Authorization: Bearer $CEEJAY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "delivered"
  }'

The TypeScript example uses ceejay.shop.completePurchase from the TypeScript SDK. It returns the full response below.

200 OK, delivered
{
  "success": true,
  "purchaseId": 4242,
  "status": "fulfilled",
  "data": {
    "purchaseId": 4242,
    "status": "fulfilled",
    "alreadyDone": false,
    "refunded": null,
    "duplicate": false
  }
}
200 OK, failed
{
  "success": true,
  "purchaseId": 4242,
  "status": "refunded",
  "refunded": 500,
  "data": {
    "purchaseId": 4242,
    "status": "refunded",
    "alreadyDone": false,
    "refunded": 500,
    "duplicate": false
  }
}
200 OK, the same request retried
{
  "success": true,
  "purchaseId": 4242,
  "status": "fulfilled",
  "alreadyDone": true,
  "data": {
    "purchaseId": 4242,
    "status": "fulfilled",
    "alreadyDone": true,
    "refunded": null,
    "duplicate": false
  }
}

Which purchases it applies to

A purchase of a Delivered by your API item of your own community that is awaiting an outcome: shown as Being delivered in Commerce → Shop → Redemptions, or under Failed delivery because an earlier attempt could not reach your server. Sending the same request again is safe: it returns alreadyDone.

A purchase that is already delivered or refunded returns 409 with the code wrong_status. Once a purchase is delivered you cannot mark it failed, and once it is refunded you cannot mark it delivered.

An earned reward, such as one for reaching a level, that is set to be delivered by your API takes the same call. delivered completes it. failed marks it failed with your message: no payment was taken, so nothing is refunded.

What it does

  • delivered marks the purchase fulfilled. It moves to Done in Redemptions.
  • failed refunds the member the full price, puts a limited item back in stock and notifies your team in CEEJAY that the delivery failed on your side. Your message is the reason.
  • Shop & Economy pages that are open refresh automatically.

Retrying safely

Send an idempotencyKey with every call you might need to retry, such as after a timeout. It is a string of 1 to 128 characters that you choose, sent in the JSON body: an Idempotency-Key header is not read.

  • Retrying with the same key returns the original response. When the same request is sent again with its key, CEEJAY returns the original response, with duplicate: true and the header Idempotent-Replayed: true.
  • Each key is tied to one request payload. The same request means the same purchase, status and message. Two requests for one event need two keys, for example match-9:coins and match-9:xp. A key that was used for a different request, here or on any other request of the API, returns 409 with the code idempotency_key_reused, and nothing is changed.
  • A rejected request does not use up the key. A call that was rejected can be retried with the same key once the cause is fixed.
  • A key belongs to the API key that sent it. Another API key of your community can send the same text, and it is a different key.
  • Keys are retained for 30 days. Use a value you can regenerate after a crash, such as an order ID or a match ID.
  • On an instance that does not support idempotency keys yet, a call that sends one returns 503 with the code idempotency_unavailable, and nothing is changed. Community details reports whether keys are supported, under features.retryKeys. idempotency_key is not accepted on this endpoint; use idempotencyKey.
  • Without a key, a retried call is a new call.

Completing a purchase twice has the same effect as completing it once, so when a first request was started more than a minute ago and never finished, a retry with the same key is processed again and returns normally. After a 502 or a 504, retry the same request: it is safe to repeat, with or without a key.

Errors

StatuscodeerrorWhen
400bad_requestA numeric purchase id is requiredThe purchase ID in the path is not a whole number, or has a leading zero
400bad_requestThe purchase id cannot exceed 2147483647The purchase ID is above 2,147,483,647
400bad_requeststatus must be 'delivered' or 'failed'status is missing or is neither delivered nor failed. A body that is not a JSON object returns this too
400bad_requestmessage must be textmessage was sent and is not text
400bad_requestmessage must be 500 characters or fewermessage is longer than 500 characters
400bad_requestmessage cannot contain a null charactermessage contains a null character (U+0000), which cannot be stored
400bad_requestmessage must be valid Unicode textmessage contains an unpaired surrogate, such as the JSON "\ud800"
400bad_requestidempotencyKey must be a string of 1-128 charactersThe key is empty, longer than 128 characters or not text, or contains an unpaired surrogate, such as the JSON "\ud800"
400bad_requestidempotencyKey cannot contain a null characterThe key contains a null character (U+0000)
400bad_requestThe request was not validCEEJAY's bot, which finishes the purchase, rejected the request as invalid
404purchase_not_foundPurchase not foundNo purchase with this ID on your server whose item is delivered by your API
404purchase_not_foundThis purchase no longer exists on this serverThe purchase was removed while it was being updated
404not_availableThis is not available on this instance yet.This feature is not available on this instance yet. Community details reports the same under features. The body includes feature
409wrong_statusThis purchase is refunded and can no longer be marked deliveredThe purchase has already reached a final status. status is its current status
409wrong_statusThis reward's status has already changedThe purchase changed status while it was being updated. status can be null here
409idempotency_key_reusedThis idempotencyKey was already used for a different requestYour API key already used this idempotencyKey for a different request: a request of another kind, or this one with other values. Nothing was changed
409idempotency_in_progressThe first request with this idempotencyKey is still running. Try again in a few seconds.The first request with this key is still being processed. Wait retryAfter seconds and retry
502bot_unavailableThe delivery could not be finished. Try againCEEJAY's bot could not be reached or could not finish. Retry the same request: it is safe to repeat
503idempotency_unavailableidempotencyKey cannot be used on this community yet, so nothing was changedYou sent a key, and this instance does not support idempotency keys yet. Nothing was changed. Community details reports it as features.retryKeys
504bot_timeoutThe bot did not answer in time. Send the same request again: it is safe to repeatCEEJAY's bot did not respond in time. Retry the same request: it is safe to repeat

Every error body also includes requestId, and a 400 with the code bad_request identifies the invalid field in field. Match on code; message text can change.

The errors every request shares (401, 403, 405, 429, 500) are on the Errors page.

On this page

Community StudiosPrivacyTerms