LoyumiDeveloper docsOpen Sandbox
GRAPHQL API · BETA

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.

Account-free guide · scoped credential required to callPOST + JSON over HTTPSBeta · selected API operations

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.

GraphQL member query
query MemberBalance($externalCustomerId: String!) {
  member(externalCustomerId: $externalCustomerId) {
    requestId
    member {
      id
      displayName
      status
      consentStatus
    }
    programs {
      programId
      tier
      balances {
        accountType
        available
        pending
        reserved
      }
    }
  }
}
Copy-paste HTTPS request
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.

GraphQL quote mutation
mutation QuoteReward($input: RedemptionQuoteInput!) {
  quoteRedemption(input: $input) {
    requestId
    idempotent
    quote {
      id
      state
      points
      availableBalance
      expiresAt
      terms
    }
  }
}
Variables
{
  "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/graphql
AuthorizationRequiredBearer <server-key>; each selected field checks its existing API scope
X-EnvironmentRequiredThe environment that owns the credential; tenant and Sandbox/Production isolation are unchanged
Content-TypeRequiredapplication/json
AcceptRecommendedapplication/graphql-response+json
X-Request-IDOptionalYour trace ID is delegated to the underlying API operation

Send 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.

member

members:read. Read identity status, consent, programs, tier, and available, pending, and reserved balances by external customer ID.

transaction · transactions

transactions:read. Inspect one balanced transaction or search a cursor-paged, filterable transaction page.

ledgerSummary · ledgerClose

analytics:read. Read bounded descriptive totals or generate exact close evidence with the same assurance boundaries as the Public API.

purchaseEarn · recordReturn

events: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 · reserveRedemption

redemptions:write. Quote first, then create the separate point reservation from the returned quote ID.

commitRedemption · releaseRedemption

redemptions:write. Commit a valid reservation after fulfillment authorization, or release an unused hold.

reverseRedemption

redemptions:reverse. Reverse a committed redemption with a reason and cancellation evidence where required.

requestAdjustment

adjustments:write. Request a governed credit or debit with reason and evidence; it does not self-approve.

approveAdjustment · rejectAdjustment · reverseAdjustment

adjustments:approve. Execute the separate decision step through the existing two-person governance path.

Predictable limits before a resolver runs.

64 KiB request

The encoded JSON body must fit within 65,536 bytes.

3,000 lexical tokens

The parsed GraphQL document has a bounded token budget before validation or execution.

Depth 12

The selected operation, including expanded fragments, may be at most twelve fields deep.

250 selections

Repeated fragment use consumes the same selection budget as writing the fields inline.

40 aliases

An operation cannot multiply resolver work through unlimited aliases.

Five query fields

A query may select at most five top-level fields; each still enforces its own scope and rate limit.

One mutation field

A mutation operation must contain exactly one top-level value command.

No subscriptions

Use signed lifecycle webhooks for asynchronous change delivery.

Read both the transport status and GraphQL errors.

Delegated business error
{
  "data": null,
  "errors": [{
    "message": "The reward cannot be reserved in its current state",
    "path": ["reserveRedemption"],
    "extensions": {
      "code": "invalid_redemption_state",
      "httpStatus": 409,
      "requestId": "req_…"
    }
  }]
}
400
Fix the GraphQL document

Invalid JSON shape, parse, validation, operation selection, or execution-budget failure.

401 / 403
Fix credentials or scope

The delegated field preserves the API operation’s environment and least-privilege checks.

405
Use POST

The Beta endpoint does not execute GraphQL through GET.

413 / 415
Fix the envelope

Keep the JSON body within 64 KiB and use application/json.

200 + errors
Resolve the field failure

A delegated business conflict can appear in GraphQL errors with its original httpStatus and requestId.

5xx
Keep the safe support reference

Server 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.