Shop and Game Services
Operations are invoked through persisted documentId values. Offer, calculation, order, and payment identifiers are opaque: clients retain the received value and never parse it. Authenticated operations use the game server selected in the session, while guest operations accept gameServerId.
Every purchase has a calculation step followed by confirmation. The browser submits the offer, quantity, permitted selections, and recipient, but never submits a price, discount, or delivery contents. Each requestId, orderRequestId, and paymentRequestId is a client-generated UUIDv7 that provides idempotency for its specific operation.
Operations
See Purchase history for purchase list and receipt queries.
Shop
documentId | Authentication | Input | Result |
|---|---|---|---|
shopOffers | Bearer session | first, after, categoryId, accountLogin | ShopOfferConnection! |
shopOffer | Bearer session | offerId, accountLogin | ShopOffer! |
shopCategories | Bearer session | first, after | ShopCategoryConnection! |
guestShopOffers | Public | gameServerId, first, after, categoryId | ShopOfferConnection! |
guestShopOffer | Public | gameServerId, offerId | ShopOffer! |
guestShopCategories | Public | gameServerId, first, after | ShopCategoryConnection! |
prepareShopPurchase | Bearer session | input: PrepareShopPurchaseInput! | ShopQuote! |
purchaseShop | Bearer session | input: PurchaseShopInput! | ShopPurchase! |
prepareGuestShopPurchase | Public | input: PrepareGuestShopPurchaseInput! | ShopQuote! |
confirmFreeGuestShopPurchase | Public | input: ConfirmFreeGuestPurchaseInput! | ShopPurchase! |
prepareGuestShopCheckout | Public | input: PrepareGuestShopCheckoutInput! | StorefrontExternalPaymentPreparation! |
startGuestShopCheckout | Public | input: ExecuteGuestShopCheckoutInput! | StorefrontExternalPaymentExecution! |
retryGuestShopCheckout | Public | input: ExecuteGuestShopCheckoutInput! | StorefrontExternalPaymentExecution! |
Game services
documentId | Authentication | Input | Result |
|---|---|---|---|
gameServiceOffers | Bearer session | first, after, categoryCode | GameServiceOfferConnection! |
gameServiceOffer | Bearer session | offerId | GameServiceOffer! |
gameServiceCategories | Bearer session | first, after | GameServiceCategoryConnection! |
prepareGameServicePurchase | Bearer session | input: PrepareGameServicePurchaseInput! | GameServiceQuote! |
purchaseGameService | Bearer session | input: PurchaseGameServiceInput! | GameServicePurchase! |
When the total is zero, purchaseShop and purchaseGameService confirm the order without a debit. The result has paymentId: null and paymentStatus: NOT_REQUIRED. Their paymentRequestId identifies the confirmation.
Shop catalog
shopOffers
Description
Returns offers available to the player on the current server. Prices already include applicable promotions, referral discounts, and VIP benefits. availability contains the state and purchase-limit progress. Continue pagination with pageInfo.endCursor.
Input
| Field | Type | Required | Description |
|---|---|---|---|
first | Int! | yes | Page size. |
after | ID | no | Cursor from the previous page. |
categoryId | ID | no | Opaque category ID. |
accountLogin | String | no | An owned game account for account-limit calculation. |
Exchange example
{
"documentId": "shopOffers",
"variables": {
"first": 24,
"after": null,
"categoryId": null,
"accountLogin": "eternal_main"
}
}
{
"data": {
"shopOffers": {
"items": [
{
"id": "019bf3dd-b08b-7000-8000-000000000205",
"sku": "STARTER_CHOICE",
"name": "Starter selection",
"description": "Choose one reward.",
"imageReference": "/styles/default/cabinet/images/items/soulshot-ticket.png",
"categoryId": "019bf3dd-b08b-7000-8000-000000000206",
"pricingMode": "SELECTION",
"deliveryModes": [
"ACCOUNT_CHARACTER",
"WAREHOUSE"
],
"selectionLimitCount": 1,
"items": [
{
"assetReference": "57",
"quantity": 250000,
"enchantLevel": 0,
"selectionKey": "adena",
"quantitySelectable": true,
"maximumQuantityMultiplier": 4
}
],
"price": {
"base": {
"units": "400",
"decimal": "4.00",
"currencyCode": "USD",
"currencyScale": 2
},
"effective": {
"units": "288",
"decimal": "2.88",
"currencyCode": "USD",
"currencyScale": 2
},
"adjustments": [
{
"code": "launch-sale",
"source": "SALE",
"percentage": 20,
"amount": {
"units": "80",
"decimal": "0.80",
"currencyCode": "USD",
"currencyScale": 2
}
}
],
"fromPrice": true,
"hasSavings": true
},
"selectionPrices": [],
"availability": {
"status": "AVAILABLE",
"available": true,
"startsAt": "2026-09-01T00:00:00Z",
"endsAt": "2026-10-01T00:00:00Z",
"globalLimit": {
"windowSeconds": 86400,
"maximumPurchases": 100,
"currentPurchases": 2,
"remainingPurchases": 98,
"evaluated": true,
"nextAvailableAt": null
},
"customerLimit": null,
"gameAccountLimit": null,
"gameAccountSelectionRequired": false
},
"sortOrder": 10
}
],
"pageInfo": {
"endCursor": null,
"hasNextPage": false
}
}
}
}
Use shopOffer with offerId for one card. shopCategories returns id, localized name, sortOrder, and a cursor. Public guestShopOffers, guestShopOffer, and guestShopCategories return the same projections, additionally require gameServerId, and do not accept accountLogin.
Related types
Wallet purchase
prepareShopPurchase
Description
Validates the offer, recipient, selected entries, and limits, then creates a short-lived calculation. ACCOUNT_CHARACTER requires an owned account and character, DIRECT_CHARACTER requires a character, and WAREHOUSE requires no recipient.
Input
| Field | Type | Required | Description |
|---|---|---|---|
input.requestId | ID! | yes | New calculation UUIDv7. |
input.offerId | ID! | yes | Opaque offer ID. |
input.quantity | Int! | yes | Number of offer units. |
input.deliveryMode | PlayerShopDeliveryMode! | yes | ACCOUNT_CHARACTER, DIRECT_CHARACTER, or WAREHOUSE. |
input.accountLogin | String | conditional | Owned account for ACCOUNT_CHARACTER. |
input.characterName | String | conditional | Character for in-game delivery. |
input.selectedItems | [ShopPurchaseSelectionInput!]! | yes | Permitted selection; empty for a bundle. |
Exchange example
{
"documentId": "prepareShopPurchase",
"variables": {
"input": {
"requestId": "019bf3dd-b08b-7000-8000-000000000201",
"offerId": "019bf3dd-b08b-7000-8000-000000000205",
"quantity": 2,
"deliveryMode": "ACCOUNT_CHARACTER",
"accountLogin": "eternal_main",
"characterName": "Hero",
"selectedItems": [
{
"selectionKey": "adena",
"quantityMultiplier": 2
}
]
}
}
}
{
"data": {
"prepareShopPurchase": {
"id": "019bf3dd-b08b-7000-8000-000000000207",
"offer": {
"id": "019bf3dd-b08b-7000-8000-000000000205",
"name": "Starter selection",
"pricingMode": "SELECTION"
},
"quantity": 2,
"selectedItems": [
{
"selectionKey": "adena",
"quantityMultiplier": 2
}
],
"deliveryItems": [
{
"assetReference": "57",
"quantity": 1000000,
"enchantLevel": 0
}
],
"unitAmount": {
"units": "1200",
"decimal": "12.00",
"currencyCode": "USD",
"currencyScale": 2
},
"subtotal": {
"units": "2400",
"decimal": "24.00",
"currencyCode": "USD",
"currencyScale": 2
},
"adjustments": [
{
"code": "vip-rank",
"kind": "DISCOUNT",
"source": "VIP",
"amount": {
"units": "480",
"decimal": "4.80",
"currencyCode": "USD",
"currencyScale": 2
}
}
],
"total": {
"units": "1920",
"decimal": "19.20",
"currencyCode": "USD",
"currencyScale": 2
},
"hasSavings": true,
"delivery": {
"mode": "ACCOUNT_CHARACTER",
"accountLogin": "eternal_main",
"characterName": "Hero"
},
"expiresAt": "2026-09-03T12:15:00Z"
}
}
}
The example shows key fields from nested offer; the persisted document returns its full catalog projection.
purchaseShop
Description
Creates an order from an active calculation and pays it from the player wallet. Repeating the same identifiers returns the same result; changing data under an existing identifier produces a conflict.
Input
| Field | Type | Required | Description |
|---|---|---|---|
input.orderRequestId | ID! | yes | Order UUIDv7. |
input.paymentRequestId | ID! | yes | Separate debit UUIDv7. |
input.quoteId | ID! | yes | Active calculation. |
Exchange example
{
"documentId": "purchaseShop",
"variables": {
"input": {
"orderRequestId": "019bf3dd-b08b-7000-8000-000000000202",
"paymentRequestId": "019bf3dd-b08b-7000-8000-000000000203",
"quoteId": "019bf3dd-b08b-7000-8000-000000000207"
}
}
}
{
"data": {
"purchaseShop": {
"orderId": "019bf3dd-b08b-7000-8000-000000000208",
"quoteId": "019bf3dd-b08b-7000-8000-000000000207",
"orderStatus": "FULFILLED",
"paymentId": "019bf3dd-b08b-7000-8000-000000000209",
"paymentStatus": "PAID",
"total": {
"units": "1920",
"decimal": "19.20",
"currencyCode": "USD",
"currencyScale": 2
},
"createdAt": "2026-09-03T12:01:00Z"
}
}
}
Guest purchase
Guest checkout has three consecutive phases: calculate and verify the character, create the order and discover payment methods, then start the selected method. The client never supplies an arbitrary return URL or price.
prepareGuestShopPurchase
Input
| Field | Type | Required | Description |
|---|---|---|---|
input.gameServerId | Int! | yes | Selected game server. |
input.requestId | ID! | yes | Calculation UUIDv7. |
input.offerId | ID! | yes | Offer with guest delivery. |
input.quantity | Int! | yes | Quantity. |
input.characterName | String! | yes | Verified recipient character. |
input.payerEmail | String! | yes | Payer email address. |
input.selectedItems | [ShopPurchaseSelectionInput!]! | yes | Selected entries or an empty list. |
Exchange example
{
"documentId": "prepareGuestShopPurchase",
"variables": {
"input": {
"gameServerId": 7,
"requestId": "019bf3dd-b08b-7000-8000-000000000201",
"offerId": "019bf3dd-b08b-7000-8000-000000000205",
"quantity": 1,
"characterName": "Hero",
"selectedItems": []
}
}
}
{
"data": {
"prepareGuestShopPurchase": {
"id": "019bf3dd-b08b-7000-8000-000000000207",
"quantity": 1,
"selectedItems": [],
"deliveryItems": [
{
"assetReference": "57",
"quantity": 250000,
"enchantLevel": 0
}
],
"subtotal": {
"units": "1200",
"decimal": "12.00",
"currencyCode": "USD",
"currencyScale": 2
},
"adjustments": [],
"total": {
"units": "1200",
"decimal": "12.00",
"currencyCode": "USD",
"currencyScale": 2
},
"hasSavings": false,
"delivery": {
"mode": "GUEST_CHARACTER",
"accountLogin": null,
"characterName": "Hero"
},
"expiresAt": "2026-09-03T12:15:00Z"
}
}
}
The response also contains full offer and unitAmount fields, matching the authenticated calculation.
prepareGuestShopCheckout
Description
Creates a pending order and returns only methods eligible for the exact amount, each with its own payment calculation.
Input
| Field | Type | Required | Description |
|---|---|---|---|
input.gameServerId | Int! | yes | The same game server. |
input.orderRequestId | ID! | yes | Order UUIDv7. |
input.paymentRequestId | ID! | yes | Payment-intent UUIDv7. |
input.quoteId | ID! | yes | Active Shop calculation. |
input.characterName | String! | yes | The same character. |
input.payerEmail | String! | yes | The same payer email. |
input.payerCountry | String | no | Two-letter country code when known. |
Exchange example
{
"documentId": "prepareGuestShopCheckout",
"variables": {
"input": {
"gameServerId": 7,
"orderRequestId": "019bf3dd-b08b-7000-8000-000000000202",
"paymentRequestId": "019bf3dd-b08b-7000-8000-000000000203",
"quoteId": "019bf3dd-b08b-7000-8000-000000000207",
"characterName": "Hero",
"payerCountry": "DE"
}
}
}
{
"data": {
"prepareGuestShopCheckout": {
"orderId": "019bf3dd-b08b-7000-8000-000000000208",
"quoteId": "019bf3dd-b08b-7000-8000-000000000207",
"orderStatus": "PENDING_PAYMENT",
"intent": {
"id": "019bf3dd-b08b-7000-8000-000000000210",
"status": "OPEN",
"expiresAt": "2026-09-03T12:10:00Z"
},
"methods": [
{
"id": "019bf3dd-b08b-7000-8000-000000000211",
"code": "bank_card",
"name": "Bank card",
"iconAssetId": null,
"paymentQuote": {
"id": "019bf3dd-b08b-7000-8000-000000000212",
"paymentAmount": {
"units": "1700",
"decimal": "17.00",
"currencyCode": "EUR",
"currencyScale": 2
},
"destinationAmount": {
"units": "1920",
"decimal": "19.20",
"currencyCode": "USD",
"currencyScale": 2
},
"payerFee": {
"units": "50",
"decimal": "0.50",
"currencyCode": "EUR",
"currencyScale": 2
},
"expiresAt": "2026-09-03T12:05:00Z"
}
}
]
}
}
}
startGuestShopCheckout
Description
Starts the selected payment method. action.kind determines the one client action: REDIRECT, FORM_POST, QR_CODE, DEEP_LINK, or WAIT. Non-applicable action fields are null.
retryGuestShopCheckout accepts the same input and returns the same result type. A retry uses a new requestId; orderId, quoteId, recipient, and selected payment calculation remain bound to the prepared order.
Input
| Field | Type | Required | Description |
|---|---|---|---|
input.gameServerId | Int! | yes | Order game server. |
input.requestId | ID! | yes | Start or retry UUIDv7. |
input.orderId | ID! | yes | Prepared order. |
input.quoteId | ID! | yes | Bound Shop calculation. |
input.characterName | String! | yes | Verified character. |
input.payerEmail | String! | yes | Payer email. |
input.methodProfileId | ID! | yes | methods[].id. |
input.paymentQuoteId | ID! | yes | methods[].paymentQuote.id. |
Exchange example
{
"documentId": "startGuestShopCheckout",
"variables": {
"input": {
"gameServerId": 7,
"requestId": "019bf3dd-b08b-7000-8000-000000000204",
"orderId": "019bf3dd-b08b-7000-8000-000000000208",
"quoteId": "019bf3dd-b08b-7000-8000-000000000207",
"characterName": "Hero",
"methodProfileId": "019bf3dd-b08b-7000-8000-000000000211",
"paymentQuoteId": "019bf3dd-b08b-7000-8000-000000000212"
}
}
}
{
"data": {
"startGuestShopCheckout": {
"orderId": "019bf3dd-b08b-7000-8000-000000000208",
"quoteId": "019bf3dd-b08b-7000-8000-000000000207",
"orderStatus": "PENDING_PAYMENT",
"intent": {
"id": "019bf3dd-b08b-7000-8000-000000000210",
"status": "PROCESSING",
"expiresAt": "2026-09-03T12:10:00Z"
},
"attempt": {
"id": "019bf3dd-b08b-7000-8000-000000000213",
"status": "REQUIRES_CUSTOMER_ACTION",
"expiresAt": "2026-09-03T12:05:00Z"
},
"action": {
"kind": "FORM_POST",
"expiresAt": "2026-09-03T12:05:00Z",
"redirect": null,
"formPost": {
"url": "https://pay.example/checkout",
"fields": [
{
"name": "invoice",
"value": "checkout-123"
},
{
"name": "signature",
"value": "signed-value"
}
]
},
"qrCode": null,
"deepLink": null,
"wait": null
}
}
}
}
Game services
gameServiceOffers
Description
Returns localized game services for the current server. Fields are typed as TEXT, OPTION, or COLOR; allowed options, text constraints, and option-specific prices are returned by the API.
Input
| Field | Type | Required | Description |
|---|---|---|---|
first | Int! | yes | Page size. |
after | ID | no | Next-page cursor. |
categoryCode | String | no | Category code. |
Exchange example
{
"documentId": "gameServiceOffers",
"variables": {
"first": 24,
"after": null,
"categoryCode": "character"
}
}
{
"data": {
"gameServiceOffers": {
"items": [
{
"id": "019bf3dd-b08b-7000-8000-000000000104",
"name": "Character name change",
"description": "Changes the selected character name.",
"imageReference": "/styles/default/cabinet/images/items/lucky-coin.png",
"category": {
"code": "character",
"name": "Character services",
"description": "Operations for a selected character."
},
"targetKind": "CHARACTER",
"fields": [
{
"code": "newCharacterName",
"kind": "TEXT",
"required": true,
"name": "New name",
"description": "Enter a new character name.",
"textConstraint": {
"policy": "ALPHANUMERIC_NAME",
"minimumLength": 3,
"maximumLength": 16
},
"options": [],
"sortOrder": 10,
"determinesPrice": false
}
],
"price": {
"base": {
"units": "1000",
"decimal": "10.00",
"currencyCode": "USD",
"currencyScale": 2
},
"effective": {
"units": "800",
"decimal": "8.00",
"currencyCode": "USD",
"currencyScale": 2
},
"adjustments": [
{
"code": "vip-rank",
"source": "VIP",
"percentage": 20,
"amount": {
"units": "200",
"decimal": "2.00",
"currencyCode": "USD",
"currencyScale": 2
}
}
],
"fromPrice": false,
"hasSavings": true
},
"availability": {
"status": "AVAILABLE",
"available": true,
"startsAt": "2026-09-01T00:00:00Z",
"endsAt": "2026-10-01T00:00:00Z"
},
"sortOrder": 10
}
],
"pageInfo": {
"endCursor": null,
"hasNextPage": false
}
}
}
}
gameServiceOffer returns one complete offer by offerId. gameServiceCategories returns code, localized name and description, sortOrder, and a cursor.
Related types
prepareGameServicePurchase
Description
Creates a service calculation for the selected recipient and form values. Use it before the specified expiry.
Input
| Field | Type | Required | Description |
|---|---|---|---|
input.requestId | ID! | yes | Calculation UUIDv7. |
input.offerId | ID! | yes | Opaque service ID. |
input.target.accountLogin | String! | yes | Owned game account. |
input.target.characterName | String | conditional | Required for a CHARACTER target. |
input.fields | [GameServiceFieldValueInput!]! | yes | Values matching the published field schema. |
Exchange example
{
"documentId": "prepareGameServicePurchase",
"variables": {
"input": {
"requestId": "019bf3dd-b08b-7000-8000-000000000101",
"offerId": "019bf3dd-b08b-7000-8000-000000000104",
"target": {
"accountLogin": "eternal_main",
"characterName": "Hero"
},
"fields": [
{
"fieldCode": "newCharacterName",
"value": "NewHero"
},
{
"fieldCode": "titleColor",
"value": "blue"
}
]
}
}
}
{
"data": {
"prepareGameServicePurchase": {
"id": "019bf3dd-b08b-7000-8000-000000000105",
"offer": {
"id": "019bf3dd-b08b-7000-8000-000000000104",
"name": "Character name change",
"targetKind": "CHARACTER"
},
"fieldValues": [
{
"fieldCode": "newCharacterName",
"value": "NewHero"
},
{
"fieldCode": "titleColor",
"value": "blue"
}
],
"target": {
"kind": "CHARACTER",
"accountLogin": "eternal_main",
"characterName": "Hero"
},
"unitAmount": {
"units": "1200",
"decimal": "12.00",
"currencyCode": "USD",
"currencyScale": 2
},
"subtotal": {
"units": "1200",
"decimal": "12.00",
"currencyCode": "USD",
"currencyScale": 2
},
"adjustments": [
{
"code": "vip-rank",
"kind": "DISCOUNT",
"source": "VIP",
"amount": {
"units": "240",
"decimal": "2.40",
"currencyCode": "USD",
"currencyScale": 2
}
}
],
"total": {
"units": "960",
"decimal": "9.60",
"currencyCode": "USD",
"currencyScale": 2
},
"hasSavings": true,
"expiresAt": "2026-09-03T12:15:00Z"
}
}
}
The example shows key fields from nested offer; the actual response contains the complete published service schema.
purchaseGameService
Description
Creates an order from an active calculation, debits the player wallet, and executes the game operation. The client does not repeat dynamic fields in this mutation because the calculation already binds them.
Input
| Field | Type | Required | Description |
|---|---|---|---|
input.orderRequestId | ID! | yes | Order UUIDv7. |
input.paymentRequestId | ID! | yes | Separate debit UUIDv7. |
input.quoteId | ID! | yes | Active service calculation. |
Exchange example
{
"documentId": "purchaseGameService",
"variables": {
"input": {
"orderRequestId": "019bf3dd-b08b-7000-8000-000000000102",
"paymentRequestId": "019bf3dd-b08b-7000-8000-000000000103",
"quoteId": "019bf3dd-b08b-7000-8000-000000000105"
}
}
}
{
"data": {
"purchaseGameService": {
"orderId": "019bf3dd-b08b-7000-8000-000000000106",
"quoteId": "019bf3dd-b08b-7000-8000-000000000105",
"orderStatus": "FULFILLED",
"paymentId": "019bf3dd-b08b-7000-8000-000000000107",
"paymentStatus": "PAID",
"total": {
"units": "960",
"decimal": "9.60",
"currencyCode": "USD",
"currencyScale": 2
},
"createdAt": "2026-09-03T12:01:00Z"
}
}
}
Free guest purchase
confirmFreeGuestShopPurchase
Confirms a purchase whose calculated total is zero. Call after the guest explicitly presses Buy, using the active guest purchase calculation. Do not request payment methods or start payment for this purchase.
input field | Type | Meaning |
|---|---|---|
gameServerId | Int! | Selected game server. |
orderRequestId | ID! | UUIDv7 for order creation. |
confirmationRequestId | ID! | A different UUIDv7 for confirmation. |
quoteId | ID! | Active zero-total calculation ID. |
characterName | String! | Calculation recipient, up to 64 characters. |
payerEmail | String! | Calculation email, up to 254 characters. |
{
"documentId": "confirmFreeGuestShopPurchase",
"variables": {
"input": {
"gameServerId": 1,
"orderRequestId": "019bf3dd-b08b-7000-8000-000000000310",
"confirmationRequestId": "019bf3dd-b08b-7000-8000-000000000311",
"quoteId": "019bf3dd-b08b-7000-8000-000000000312",
"characterName": "Asterion",
}
}
}
{
"data": {
"confirmFreeGuestShopPurchase": {
"orderId": "019bf3dd-b08b-7000-8000-000000000313",
"quoteId": "019bf3dd-b08b-7000-8000-000000000312",
"orderStatus": "CONFIRMED",
"paymentId": null,
"paymentStatus": "NOT_REQUIRED",
"total": {
"units": "0",
"decimal": "0.000",
"currencyCode": "ELX",
"currencyScale": 3
},
"createdAt": "2026-09-13T10:00:00Z"
}
}
}
For a retry, keep both request identifiers and all other fields unchanged. Prepare a new calculation if it expires. The result is ShopPurchase, with paymentId: null and paymentStatus: NOT_REQUIRED. CONFIRMED means the confirmation was accepted, not that delivery has completed.
Errors
| Code | Meaning |
|---|---|
UNAUTHENTICATED | An authenticated operation has no active session. |
STOREFRONT_INVALID_REQUEST | Request fields do not match the current contract. |
STOREFRONT_SCOPE_UNAVAILABLE | The current project or game server is unavailable. |
STOREFRONT_ACCOUNT_UNAVAILABLE | The account is unavailable or not owned by the player. |
STOREFRONT_CHARACTER_UNAVAILABLE | The character does not exist or does not belong to the selected account. |
STOREFRONT_FEATURE_UNAVAILABLE | The game service is currently unavailable. |
STOREFRONT_OFFER_UNAVAILABLE | The offer is unavailable because of its state, period, or limit. |
STOREFRONT_REFRESH_REQUIRED | A calculation, order, or payment calculation expired; restart that phase. |
STOREFRONT_INSUFFICIENT_BALANCE | The selected wallet has insufficient funds. |
STOREFRONT_PAYMENT_DEBT | Repay the selected balance's debt, then start a new purchase. |
STOREFRONT_CONFLICT | An operation identifier was reused with different data. |
STOREFRONT_METHODS_UNAVAILABLE | No payment method is eligible for the guest order. |
STOREFRONT_RATE_LIMITED | The public request rate limit was exceeded. |
STOREFRONT_UNAVAILABLE | The operation is temporarily unavailable. |
See module data types for the complete response structures.