Avrix never moves money at your payment processor. Refund the buyer at your PSP first, then call Avrix to quarantine the keys and adjust finance. POST /orders/cancel only cancels pre-order reservations — fulfilled orders use POST /refunds or POST /keys/return.
Refund and key return flow#
Status reads#
GET /api/seller/v1/refunds and GET /api/seller/v1/refunds/{refundId} return adjustment status:
adjustmentStatus | Meaning |
|---|---|
pending | Quarantine / adjustment accepted, not yet final |
completed | Adjustment finalised |
chargeback_open | Chargeback opened at your PSP / declared to Avrix |
chargeback_lost | Chargeback lost |
chargeback_won | Chargeback won |
Accepted scopes (any one): seller:refunds:read, seller:refunds:write, or seller:finance:read (legacy keys with seller:keys:pull may still work for writes/list where configured).
Scope#
- In scope: Keys delivered through the Seller API — inventory quarantine, finance adjustment status, and related webhooks.
- Out of scope: Payment processing, PSP chargeback mechanics, fraud, regional law, and vendor-specific refund windows — those remain store and vendor responsibilities.
Eligibility#
Technical rules enforced by the API (there is no published calendar time window such as “N days after fulfilment”):
- Ownership: Each
keyIdmust belong to a pull by the authenticated seller company. - State: Each key must still be in status
revealed— already quarantined (returned) orredeemedkeys are rejected (Key is not in returnable state). - Volume: 1–100 distinct key UUIDs per request.
Successful returns quarantine keys (returned) — they do not re-enter the available pool
automatically. Vendor commercial policies (store refund windows, proof requirements) are separate
from this technical gate.
keyIds must come from the original POST /orders response (persist them — authoritative).
OpenAPI may list keyIds on order.fulfilled, but do not treat webhooks as the source of truth.
GET /orders never returns key material.
Behavior#
- Atomic: Returns run as a single operation — quarantine keys, adjust pulled quantities where the business model requires, and record an audit trail. Returned keys are not recycled into the available pool without operator review.
- Finance clawback: When adjustment metadata is supplied, matching sale rows are stamped with an adjustment status and excluded from monthly aggregation / payout statements.
- Webhooks: On a successful return, both
order.keys_returned(carrieskeyIds) andrefund.completed(optionaladjustmentType) may fire.allocation.updatedmay also fire. - Idempotency: Send
Idempotency-Keyon every return / refund write; retries replay the stored response within 24 hours.
Resolving a chargeback#
A chargeback declared via POST /refunds with type: "chargeback" opens a dispute
(adjustmentStatus: "chargeback_open") at your payment processor. You own that dispute, so you
report its outcome with POST /api/seller/v1/chargebacks/resolve:
| Field | Type | Notes |
|---|---|---|
chargebackReference | string, required | The same reference passed as chargebackReference on the original POST /refunds call |
outcome | "won" | "lost", required | Won: you kept the buyer's money. Lost: the chargeback stands |
occurredAt | ISO 8601 datetime, optional | When the dispute was decided at your PSP |
The resolution applies to the whole group of sale transactions sharing that
chargebackReference in one atomic update, since a PSP dispute covers the whole order group
that was declared. On success the response reports resolved, the count of transactions moved
to chargeback_won or chargeback_lost, and Avrix emits the chargeback.resolved webhook.
Send Idempotency-Key, same as any other write; retries replay the stored response.
Error semantics:
404whenchargebackReferencedoes not match a chargeback owned by your company.409when the chargeback is not currentlychargeback_open(already resolved as won or lost). The message includes the current state. This is terminal: a resolved chargeback cannot be resolved again.422for a malformed body (missingchargebackReferenceoroutcome, or an unrecognisedoutcomevalue).
A won outcome restores the Content Owner's revenue share and the platform commission on a later settlement, rather than editing an already-approved report.
Why quarantine, not recycle?#
Digital game keys cannot be reliably proven unused once delivered. Quarantining defaults to safe behaviour: an operator decides whether to write off the unit, re-issue after confirming with the vendor, or close the case.
Operational notes#
- Vendors may impose stricter commercial rules (for example no returns after redemption). The API enforces technical returnability; commercial policy is layered in contracts and store terms.
- Pre-order cancels: Use POST /orders/cancel for active reservations — emits
order.returned, notorder.keys_returned. - External refunds and chargebacks: Use
POST /api/seller/v1/refundswithtype,keyIds, and the matchingrefundReferenceorchargebackReference.
Refund read model#
curl -s -X POST "https://api.avrix.io/api/seller/v1/keys/return" \
-H "Authorization: Bearer $AVRIX_API_KEY" \
-H "Idempotency-Key: return-store-10432" \
-H "Content-Type: application/json" \
-d '{
"orderReference": "store-order-10432",
"keyIds": [
"key_replace_me"
],
"reason": "customer_refund"
}'Each row includes type (refund | chargeback), adjustmentStatus, keyId, skuId, orderReference, money fields with currencyExponent, and timestamps.
Finance ledger export (when scoped):
curl -s "https://api.avrix.io/api/seller/v1/finance/api-sales?format=csv" \
-H "Authorization: Bearer avrix_sk_sbx_your_key_here"