Skip to main content

Entitlements & refunds

A download link says how bytes are handed over. An entitlement says what the customer owns. Traide keeps the two separate: DigitalContentUrl is a replaceable delivery credential, while Entitlement is the durable, account-bound record of the customer's claim — with a lifecycle, an audit trail of uses, and revocation wired to refunds. Integrators should treat the entitlement as the source of truth for access decisions.

note

Entitlement, RedemptionEvent, and the related queries are not yet in the generated API reference; they will appear with the next schema regeneration. Until then, the SDL excerpts on this page are the authoritative shape.

The entitlement ledger​

An entitlement is granted automatically whenever a digital line is delivered — on automatic fulfillment at payment, and on manual fulfillment. Granularity depends on the kind: DIGITAL_FILE lines grant one entitlement per line; the per-unit kinds (LICENSE_KEY/CODE/GIFT_CARD) grant one entitlement per unit — a quantity-3 key line produces three rows of quantity: 1, each bound to its own key. Its key fields:

FieldMeaning
customerEmailIdentity the claim is bound to. Always present, including guest checkouts
quantityUnits covered by the claim
productName / variantName / productSkuSnapshotted at purchase — they survive later catalog changes
kindThe fulfillment kind, snapshotted at grant time
licenseKeyFor per-unit kinds: the secret credential this claim was issued against — see License keys, codes & gift cards
statusLifecycle state (below)
revokedReasonWhy the claim was withdrawn, if it was
isUsableWhether redemption is permitted right now — combines status with the expiry clock
contentUrlsDownload credentials issued against this entitlement
redemptionsUses of the entitlement, most recent first

The lifecycle is expressed as states, not booleans — "revoked because refunded" and "expired because the term ended" are different facts, and only ACTIVE permits redemption:

enum EntitlementStatus {
PENDING
ACTIVE
SUSPENDED
EXPIRED
REVOKED
TRANSFERRED
}

enum EntitlementRevokedReason {
REFUND
CHARGEBACK
FRAUD
OPERATOR
SELLER
}

The customer library​

Signed-in customers read their own library with me { entitlements }. It is owner-scoped — only ever the requesting user's entitlements — and includes items whose download links have since expired, which is what makes "re-download without email archaeology" possible on a storefront:

query {
me {
entitlements(first: 20) {
edges {
node {
productName
variantName
status
isUsable
grantedAt
contentUrls {
url
downloadNum
}
}
}
}
}
}
Show more ↓

Guest purchases carry the checkout email as their identity (customerEmail). A guest's entitlements become visible in me { entitlements } once the entitlement is associated with their customer account — until then the claim exists but is not exposed through the library.

Operator and seller views​

  • entitlements(first: …) — requires MANAGE_ORDERS. Marketplace operators see every entitlement; a seller sees only claims against their own goods.
  • entitlementRevoke(id, reason) — withdraw a customer's entitlement, invalidating any download links issued against it. Requires MANAGE_MARKETPLACE. The reason defaults to OPERATOR; pass FRAUD or SELLER when that is the real cause, since the reason drives downstream trust policy.
mutation {
entitlementRevoke(id: "RW50aXRsZW1lbnQ6MQ==", reason: FRAUD) {
entitlement {
id
status
revokedReason
}
entitlementErrors {
field
code
message
}
}
}

Refunds revoke access​

With revokeEntitlementsOnRefund enabled on the marketplace configuration (it is on by default), a refund that completes — reaching the PAID refund status — revokes the entitlements covered by that refund with revokedReason: REFUND, and the associated download links stop validating. A refunded buyer does not keep a working download link.

This holds regardless of how the refund reached PAID: dashboard-driven refunds, automatic gateway processing, and gateway webhook confirmations all trigger revocation. Refund scope fans out — a whole-order or whole-seller-order refund revokes the digital lines it covers, not just refunds issued line-by-line.

To keep links alive for refunded buyers as a policy choice, disable the flag:

mutation {
marketplaceConfigurationUpdate(input: { revokeEntitlementsOnRefund: false }) {
marketplaceConfiguration {
revokeEntitlementsOnRefund
}
}
}

Redemption events​

Every use of an entitlement is recorded as a RedemptionEvent:

type RedemptionEvent implements Node {
id: ID!
occurredAt: DateTime!
eventType: RedemptionEventType!
idempotencyKey: String
}

Three event types are live: DOWNLOAD (a file download — no idempotency key, every download is a distinct use), REVEAL (the first time a buyer reveals a key's secret — exactly one per key), and ACTIVATION (a use counted through the verification API, idempotent when the caller supplies an idempotency key). SCAN and CHECK_IN remain reserved for tickets and bookings, which will redeem against this same ledger.

Alongside the event exposed in the API, the download endpoint records request forensics (IP address and user agent) server-side with each download redemption. That row — not just the counter — is the evidence a chargeback dispute is argued from, and it covers guest downloads too.

Webhooks​

Seven webhook events cover the digital lifecycle for integrators:

EventFires whenPayload
ENTITLEMENT_GRANTEDA customer's claim is created at deliveryThe serialized entitlement
ENTITLEMENT_REVOKEDA claim is withdrawn (refund, operator, fraud…)The serialized entitlement
DIGITAL_CONTENT_URL_CREATEDA download link is mintedThe serialized link
DIGITAL_CONTENT_URL_REVOKEDA link is invalidatedThe serialized link
LICENSE_KEY_ISSUEDA sold key binds to its entitlement at paymentThe serialized key (secretLast4 only — never the secret)
LICENSE_KEY_REVEALEDA key's first revealThe serialized key
LICENSE_KEY_VOIDEDA key is withdrawn (inventory void, or revocation on refund)The serialized key

Payloads mirror the corresponding GraphQL type's shape. Subscribe to them like any other event — see Subscribing to webhooks; the entitlement events and the three license-key events require the subscribing app to hold MANAGE_ORDERS.

Separately from webhooks, each download also records a DIGITAL_LINK_DOWNLOADED customer analytics event on the buyer's timeline.

Was this page helpful?