The encoded JSON body must fit within 65,536 bytes.
Query loyalty without bypassing its controls.
Use a typed GraphQL surface for selected member, ledger, earn, return, redemption, and adjustment operations while Loyumi’s existing scopes and value state machines remain authoritative.
Read one member, then quote value without spending it.
The guide is public and needs no account. Calling the endpoint requires a scoped Sandbox server credential and environment ID. Start with a read, then use one stable idempotency key for one mutation step.
query MemberBalance($externalCustomerId: String!) {
member(externalCustomerId: $externalCustomerId) {
requestId
member {
id
displayName
status
consentStatus
}
programs {
programId
tier
balances {
accountType
available
pending
reserved
}
}
}
}curl --request POST "https://app.loyumi.com/api/graphql" \
--header "Authorization: Bearer <sandbox-key>" \
--header "X-Environment: <sandbox-environment-id>" \
--header "Content-Type: application/json" \
--header "Accept: application/graphql-response+json" \
--data '{
"query": "query MemberBalance($externalCustomerId: String!) { member(externalCustomerId: $externalCustomerId) { requestId member { id displayName status consentStatus } programs { programId tier balances { accountType available pending reserved } } } }",
"variables": { "externalCustomerId": "<sandbox-customer-id>" }
}'Next: quote a reward
A quote validates the current reward, balance, program, and expiry terms. It does not reserve or spend points. Save its ID before moving to the separate reserve mutation.
mutation QuoteReward($input: RedemptionQuoteInput!) {
quoteRedemption(input: $input) {
requestId
idempotent
quote {
id
state
points
availableBalance
expiresAt
terms
}
}
}{
"input": {
"idempotencyKey": "quote:customer-42:reward-7:attempt-1",
"programId": "<program-id>",
"externalCustomerId": "<sandbox-customer-id>",
"sourceReference": "cart-9001",
"rewardId": "<reward-id>",
"ttlSeconds": 300
}
}One POST-only JSON endpoint over HTTPS.
EndpointRequiredPOST https://app.loyumi.com/api/graphqlAuthorizationRequiredBearer <server-key>; each selected field checks its existing API scopeX-EnvironmentRequiredThe environment that owns the credential; tenant and Sandbox/Production isolation are unchangedContent-TypeRequiredapplication/jsonAcceptRecommendedapplication/graphql-response+jsonX-Request-IDOptionalYour trace ID is delegated to the underlying API operationSend one JSON object with a nonempty query string plus optional operationName and object-valued variables. JSON-array batching is rejected. GET returns 405; subscriptions are not supported. Responses use application/graphql-response+json and Cache-Control: no-store.
Five reads and eleven governed mutations.
Create the narrowest credential that covers only the fields an integration actually selects. A document can contain reusable fragments, but scopes are enforced when each field executes.
membermembers:read. Read identity status, consent, programs, tier, and available, pending, and reserved balances by external customer ID.
transaction · transactionstransactions:read. Inspect one balanced transaction or search a cursor-paged, filterable transaction page.
ledgerSummary · ledgerCloseanalytics:read. Read bounded descriptive totals or generate exact close evidence with the same assurance boundaries as the Public API.
purchaseEarn · recordReturnevents:write. Post a completed purchase or exact/amount-based return through the existing earn and clawback rules. Always read id, status, requestId, and idempotent; detailed earn or return fields are present on a fresh commit and may be null on an intentionally minimal replay receipt.
quoteRedemption · reserveRedemptionredemptions:write. Quote first, then create the separate point reservation from the returned quote ID.
commitRedemption · releaseRedemptionredemptions:write. Commit a valid reservation after fulfillment authorization, or release an unused hold.
reverseRedemptionredemptions:reverse. Reverse a committed redemption with a reason and cancellation evidence where required.
requestAdjustmentadjustments:write. Request a governed credit or debit with reason and evidence; it does not self-approve.
approveAdjustment · rejectAdjustment · reverseAdjustmentadjustments:approve. Execute the separate decision step through the existing two-person governance path.
Predictable limits before a resolver runs.
The parsed GraphQL document has a bounded token budget before validation or execution.
The selected operation, including expanded fragments, may be at most twelve fields deep.
Repeated fragment use consumes the same selection budget as writing the fields inline.
An operation cannot multiply resolver work through unlimited aliases.
A query may select at most five top-level fields; each still enforces its own scope and rate limit.
A mutation operation must contain exactly one top-level value command.
Use signed lifecycle webhooks for asynchronous change delivery.
Read both the transport status and GraphQL errors.
{
"data": null,
"errors": [{
"message": "The reward cannot be reserved in its current state",
"path": ["reserveRedemption"],
"extensions": {
"code": "invalid_redemption_state",
"httpStatus": 409,
"requestId": "req_…"
}
}]
}400Invalid JSON shape, parse, validation, operation selection, or execution-budget failure.
401 / 403The delegated field preserves the API operation’s environment and least-privilege checks.
405The Beta endpoint does not execute GraphQL through GET.
413 / 415Keep the JSON body within 64 KiB and use application/json.
200 + errorsA delegated business conflict can appear in GraphQL errors with its original httpStatus and requestId.
5xxServer failures use a sanitized public message; internal implementation detail is not reflected.
Never treat HTTP 200 alone as success. Check errors, then inspect extensions.code, extensions.httpStatus, and optional extensions.requestId. Reuse an idempotency key only when repeating the exact same mutation and variables after an uncertain result.
Review the same SDL the endpoint executes.
The downloadable SDL defines every Beta query, mutation, input, and output type. Long accepts JSON safe integers rather than GraphQL's signed 32-bit Int range. JSON appears only where the underlying API intentionally permits merchant-defined structured data.