Payment API
This page describes the Hive Axyl Server API that the app server calls directly for 'Payment'. It includes the receipt verification APIs, with which the app server rechecks payment receipts with the market, and the API that retrieves the purchase history for each payment provider.
Verify consumable product receipts
POST /payment/v1/purchase/verify
Rechecks the payment receipt of a consumable product with the official APIs of Apple App Store, Google Play, Steam, and PG. This step prevents products from being fraudulently delivered through forged or tampered receipts or requests without an actual payment; deliver products only when this verification passes. For Steam payments, the server checks the order with Steam and then proceeds with the actual charge while it processes this API, so the payment is confirmed at the time you call this API.
Receipt verification is requested only through this API. When the app client passes the receipt information to the app server after payment, the app server calls this API and delivers the product according to the verification result. For the implementation procedure for each payment provider, see Verify Apple consumable product receipts, Verify Google Play consumable product receipts, Verify Steam consumable product receipts, and Verify PG consumable product receipts.
Before calling the API
- Caller:
app server - Base URL
- Production:
https://commerce-api.hiveaxyl.com - Sandbox:
https://sandbox-commerce-api.hiveaxyl.com
- Production:
- Authentication:
Authorization: Bearer {access-token}
Warning
Put the token for the app server that you received from Issue a token in the authentication header. Keep the access token and the Client Secret used for token issuance only on the app server, and do not include them in the app client.
Call parameters
| Name | Location | Type | Required | Description |
|---|---|---|---|---|
X-App-Id | header | string | true | The App ID registered in the Hive Console. |
X-SDK-Version | header | string | false | Client SDK version information. |
X-Platform | header | string | false | Platform information. |
X-OS-Version | header | string | false | Operating system version information. |
Accept-Language | header | string | false | Client language setting. |
traceparent | header | string | false | W3C Trace Context header for distributed tracing. |
User-Agent | header | string | false | User-Agent information of the client application. |
| body | body | PurchaseVerifyRequest | true | Receipt verification request information. |
Request body PurchaseVerifyRequest
| Field | Type | Required | Description |
|---|---|---|---|
accountUuid | string(uuid) | true | Value that links the logged-in user to this purchase record. Put the value the app client created in Generate an AccountUuid. It is used to check that the user who paid and the user who requested verification are the same, and it must be in UUID format. |
appVersion | string | false | App version. If omitted, the X-SDK-Version header value is saved. The app server does not send this header, so to record the app version, pass it in this field. |
axylReceipt | string | true | Purchase receipt. The value to put differs by market, so see Request values by market. |
country | string | false | Country code. Uses the ISO 3166-1 two-letter format. |
currency | string | false | Payment currency. Uses the ISO 4217 three-letter format. Paired with price, it is used to compare against the payment information the server has. If you send only one of the two, only the amount is compared, not the currency. |
iapPayload | string | false | Payload defined by the app. The value you send is saved as is and returned as hiveAxylPayload in the response. |
language | string | false | Language code. Uses the ISO 639-1 two-letter format. |
orderId | string | false | Order number. The server looks up the order using storeTransactionId, orderId, and axylReceipt, in that order. |
price | number | false | Payment amount. Includes decimals depending on the currency. If you send it, the server compares it with the payment amount it has; if you omit it, no comparison is made. How a different amount is handled differs by market. The payment history stores not this value but the amount the server confirmed from the market verification result or the order information. |
productId | string | true | In-app product ID registered in the market. |
projectInfo | object | false | Additional data that each app defines freely. It is only saved and is not returned in the response, so to get a value back in the response, use iapPayload. |
providerId | string | true | Market type. Specify one of APPLE, GOOGLE, STEAM, and PG. |
requestType | integer | true | Request type. 1 is a new purchase and 2 is purchase restoration; only these two values are allowed. |
serverId | string | false | Server ID registered in App Info > App Server of the Hive Console. For details, see App server. |
storeTransactionId | string | false | Store transaction ID. It is the first key used to look up the order. |
Request values by market
The following fields take different values, or are processed differently by the server, depending on the market.
providerId:APPLEaxylReceipt: The original StoreKit 2 transaction JWS issued by Apple App Store. StoreKit 2 is the set of in-app purchase features that Apple provides for iOS and macOS apps; when a payment finishes, it issues a JWS, which is a signed string of the transaction information. Pass the value returned by StoreKit 2'sjwsRepresentationas is, in its three parts: header, payload, and signature. For how the app client prepares it, see Prepare Apple receipt information.accountUuid: Pass the same value you put inappAccountTokenof the Apple purchase request. The result of the server comparing the two values is returned ashiveAxylAccountUuidComparein the response.price: If the amount differs, the request is rejected withPRICE_VERIFY_FAIL.storeTransactionId: Apple transaction ID
providerId:GOOGLEaxylReceipt: ThepurchaseTokenstring issued by Google Play. A JSON string that containspurchase_dataandsignatureis also accepted; in that case, put the original string returned bygetOriginalJson()of the Google Play Billing Library inpurchase_dataas is. If you reserialize the value, signature verification fails. For how the app client prepares it, see Prepare Google receipt information.productId: The purchase token contains no product information, so you must pass it. If omitted, the response isINVALID_REQUEST.accountUuid: Pass the same value you put inObfuscatedAccountIdof the Google purchase request. The result of the server comparing the two values is returned ashiveAxylAccountUuidComparein the response.price: The request is not rejected even if the amount differs.storeTransactionId: Google Play store transaction ID
providerId:STEAMaxylReceipt: The sealed receipt issued by the Hive Axyl server. Pass theAxylReceiptvalue that the app client received in the response when it started or restored a purchase as is, without modifying it. The server reseals the receipt with the saved order information and compares the two, so if the value has been forged or tampered with, the response isRECEIPT_VERIFY_FAIL. For how the app client prepares it, see Prepare Steam receipt information.productId: Not used for comparison, because verification is based on the order information saved on the server.accountUuid: The value you pass is saved in the payment history and serves as the basis for identifying which user made the payment. Steam has no payment-side account information to compare against, sohiveAxylAccountUuidComparein the response is always9.price: The request is not rejected even if the amount differs.orderId,storeTransactionId: The Steam order number, which consists of digits. If you send neither value, the server extracts the order number fromaxylReceipt, so you can omit them.
providerId:PGaxylReceipt: The sealed receipt issued by the Hive Axyl server. Pass theAxylReceiptvalue of the undelivered order that the app client received from Get completed payment information as is, without modifying it. The server reseals the receipt with the saved order information and compares the two, so if the value has been forged or tampered with, the response isRECEIPT_VERIFY_FAIL.productId: Not used for comparison, because verification is based on the order information saved on the server.accountUuid: The value you pass is saved in the payment history and serves as the basis for identifying which user made the payment. PG has no payment-side account information to compare against, sohiveAxylAccountUuidComparein the response is always9.price: If the amount differs, the request is rejected withPRICE_VERIFY_FAIL.orderId,storeTransactionId: The PG order number that starts withH. If you send neither value, the server extracts the order number fromaxylReceipt, so you can omit them.
Call example
curl -X POST 'https://commerce-api.hiveaxyl.com/payment/v1/purchase/verify' \
-H 'Authorization: Bearer {access-token}' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'X-App-Id: {app-id}' \
-d '{
"providerId": "APPLE",
"requestType": 1,
"axylReceipt": "{apple-transaction-jws}",
"productId": "com.game.item.gold_100",
"price": 1200,
"currency": "KRW",
"accountUuid": "123e4567-e89b-12d3-a456-426614174000",
"storeTransactionId": "2000000123456789",
"iapPayload": "iap_payload_data"
}'
curl -X POST 'https://commerce-api.hiveaxyl.com/payment/v1/purchase/verify' \
-H 'Authorization: Bearer {access-token}' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'X-App-Id: {app-id}' \
-d '{
"providerId": "GOOGLE",
"requestType": 1,
"axylReceipt": "{google-purchase-token}",
"productId": "com.game.item.gold_100",
"price": 1200,
"currency": "KRW",
"accountUuid": "123e4567-e89b-12d3-a456-426614174000",
"storeTransactionId": "GPA.3389-9543-8198-17604",
"iapPayload": "iap_payload_data"
}'
curl -X POST 'https://commerce-api.hiveaxyl.com/payment/v1/purchase/verify' \
-H 'Authorization: Bearer {access-token}' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'X-App-Id: {app-id}' \
-d '{
"providerId": "STEAM",
"requestType": 1,
"axylReceipt": "{steam-axyl-receipt}",
"productId": "com.game.item.gold_100",
"price": 1200,
"currency": "KRW",
"accountUuid": "123e4567-e89b-12d3-a456-426614174000",
"storeTransactionId": "421799706624185538",
"iapPayload": "iap_payload_data"
}'
curl -X POST 'https://commerce-api.hiveaxyl.com/payment/v1/purchase/verify' \
-H 'Authorization: Bearer {access-token}' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'X-App-Id: {app-id}' \
-d '{
"providerId": "PG",
"requestType": 1,
"axylReceipt": "{pg-axyl-receipt}",
"productId": "com.game.item.gold_100",
"price": 1200,
"currency": "KRW",
"accountUuid": "123e4567-e89b-12d3-a456-426614174000",
"storeTransactionId": "H517815844374710159",
"iapPayload": "iap_payload_data"
}'
Response
For the common data and meta, the error body, the product common error codes, and the receipt verification outcome.message values, see Payment responses and errors. This section describes the objects this API actually returns and the handling specific to this API.
Success response data object
| Field | Type | Description |
|---|---|---|
data.hiveAxylAccountUuidCompare | integer | Result of comparing accountUuid in the request with the purchase account identifier the market reported. 1 means a match, 2 a mismatch, and 9 that comparison is not possible. If 2 is returned, handle it according to your app's security policy; Hive Axyl does not automatically block the payment or product delivery. 9 is not a mismatch. Steam and PG always return 9. |
data.hiveAxylCurrency | string or null | Verified payment currency. In the ISO 4217 three-letter format. |
data.hiveAxylDuplicated | boolean | Whether the receipt verification is a duplicate. true means the receipt was already verified, so no new verification record was created and the existing result was returned as is. |
data.hiveAxylGameServerPriceVerifyKey | string or null | App server payment amount verification key. When the payment was made with a custom amount, the verification key issued by the app server is returned as is. |
data.hiveAxylPayload | string or null | The iapPayload value of the request, returned as is. |
data.hiveAxylPrice | number or null | Verified payment amount. Based on the local currency, and includes decimals depending on the currency. |
data.hiveAxylProductId | string | In-app product ID registered in the market. |
data.hiveAxylProviderId | string | Market type. One of APPLE, GOOGLE, STEAM, and PG. |
data.hiveAxylProviderTransactionId | string | Market-side transaction ID. For Apple it is the transactionId value, and for Google and Steam it is the orderId value. |
data.hiveAxylPurchaseCancelState | integer | Payment cancellation status. 0 means normal and 1 means a canceled payment. |
data.hiveAxylPurchaseTest | string | Whether it is a test payment. N means an actual payment and Y a test payment. It becomes Y for Apple when the environment of the verification result is Sandbox, for Google when the purchase type is a test purchase, and for Steam and PG according to the server's sandbox setting. |
data.hiveAxylQuantity | integer | Purchase quantity. |
data.hiveAxylReceipt | string | The axylReceipt sent in the request, returned by the server as is without modification. |
data.hiveAxylReceiptVerifyResult | object or null | Original result object of the market receipt verification. Use it when the app server needs additional verification. All date fields in the Apple result are in Unix epoch milliseconds. Always null for Steam. |
data.hiveAxylStoreTransactionId | string or null | Store transaction ID. For Apple it is the transactionId value, and for Google the orderId value. For Steam, a value different from hiveAxylProviderTransactionId is returned. |
data.hiveAxylTransactionId | string | Hive Axyl payment transaction ID, in the format of a prefix and a number joined by an underscore. The app client uses it as axylTransactionId when it saves the product delivery result with ItemResultAsync, so return this value from the app server to the app client. |
Response example
{
"data": {
"hiveAxylAccountUuidCompare": 1,
"hiveAxylCurrency": "KRW",
"hiveAxylDuplicated": false,
"hiveAxylGameServerPriceVerifyKey": "verify-key-001",
"hiveAxylPayload": "iap_payload_data",
"hiveAxylPrice": 1200,
"hiveAxylProductId": "com.game.item.gold_100",
"hiveAxylProviderId": "APPLE",
"hiveAxylProviderTransactionId": "2000000123456789",
"hiveAxylPurchaseCancelState": 0,
"hiveAxylPurchaseTest": "N",
"hiveAxylQuantity": 1,
"hiveAxylReceipt": "{apple-transaction-jws}",
"hiveAxylReceiptVerifyResult": { ... },
"hiveAxylStoreTransactionId": "2000000123456789",
"hiveAxylTransactionId": "{axyl-transaction-id}"
},
"meta": null
}
{
"data": {
"hiveAxylAccountUuidCompare": 1,
"hiveAxylCurrency": "KRW",
"hiveAxylDuplicated": false,
"hiveAxylGameServerPriceVerifyKey": "verify-key-001",
"hiveAxylPayload": "iap_payload_data",
"hiveAxylPrice": 1200,
"hiveAxylProductId": "com.game.item.gold_100",
"hiveAxylProviderId": "GOOGLE",
"hiveAxylProviderTransactionId": "GPA.3389-9543-8198-17604",
"hiveAxylPurchaseCancelState": 0,
"hiveAxylPurchaseTest": "N",
"hiveAxylQuantity": 1,
"hiveAxylReceipt": "{google-purchase-token}",
"hiveAxylReceiptVerifyResult": { ... },
"hiveAxylStoreTransactionId": "GPA.3389-9543-8198-17604",
"hiveAxylTransactionId": "{axyl-transaction-id}"
},
"meta": null
}
{
"data": {
"hiveAxylAccountUuidCompare": 9,
"hiveAxylCurrency": "KRW",
"hiveAxylDuplicated": false,
"hiveAxylGameServerPriceVerifyKey": "verify-key-001",
"hiveAxylPayload": "iap_payload_data",
"hiveAxylPrice": 1200,
"hiveAxylProductId": "com.game.item.gold_100",
"hiveAxylProviderId": "STEAM",
"hiveAxylProviderTransactionId": "2026010100001",
"hiveAxylPurchaseCancelState": 0,
"hiveAxylPurchaseTest": "N",
"hiveAxylQuantity": 1,
"hiveAxylReceipt": "{steam-axyl-receipt}",
"hiveAxylReceiptVerifyResult": null,
"hiveAxylStoreTransactionId": "421799706624185538",
"hiveAxylTransactionId": "{axyl-transaction-id}"
},
"meta": null
}
{
"data": {
"hiveAxylAccountUuidCompare": 9,
"hiveAxylCurrency": "KRW",
"hiveAxylDuplicated": false,
"hiveAxylGameServerPriceVerifyKey": "verify-key-001",
"hiveAxylPayload": "iap_payload_data",
"hiveAxylPrice": 1200,
"hiveAxylProductId": "com.game.item.gold_100",
"hiveAxylProviderId": "PG",
"hiveAxylProviderTransactionId": "{pg-transaction-id}",
"hiveAxylPurchaseCancelState": 0,
"hiveAxylPurchaseTest": "N",
"hiveAxylQuantity": 1,
"hiveAxylReceipt": "{pg-axyl-receipt}",
"hiveAxylReceiptVerifyResult": { ... },
"hiveAxylStoreTransactionId": "H517815844374710159",
"hiveAxylTransactionId": "{axyl-transaction-id}"
},
"meta": null
}
Notes for each API
If hiveAxylDuplicated is true, the same receipt has already been verified. The values returned in this case are the result of the first verification, so check the delivery history before you decide whether to deliver, so that you do not deliver the same product twice.
If hiveAxylPurchaseCancelState is 1, the payment was canceled. In this case, do not deliver the product.
If hiveAxylPurchaseTest is Y, it is a test payment. Decide whether to deliver products for test payments in the production environment according to your app's operating policy.
For Steam, the payment is confirmed when you call this API, so do not call it repeatedly with the same receipt without need. If you did not receive a response because of a network error or a similar problem and cannot tell whether the request was processed, resend the same request and check whether hiveAxylDuplicated in the response is true to see whether it has already been processed. For Steam, hiveAxylReceiptVerifyResult is always null, so check what to deliver with the hiveAxylPrice, hiveAxylProductId, and hiveAxylQuantity values.
If there are multiple undelivered PG orders, call this API once for each order. You cannot verify multiple orders in one request.
Response status
| Status | Content type | Meaning | Response header | Response body or handling |
|---|---|---|---|---|
200 | application/json | Verification succeeded | - | data contains the verification result. |
400 | application/problem+json | Request error or payment product error | - | - |
500 | application/problem+json | Server error | - | - |
Error codes by API
| Code | Condition | How to handle |
|---|---|---|
app_not_found | The app information for X-App-Id cannot be found. | Check the App ID again in Project Settings > App ID. |
Verify subscription product receipts
POST /payment/v1/subscription/verify
Rechecks a subscription receipt with Apple App Store or Google Play to verify that the subscription is valid. The response also contains the subscription expiration time and the refund time, so use this result to decide whether to deliver or reclaim subscription benefits. Subscription payments are supported only for Apple App Store and Google Play.
Subscription receipt verification is also requested only through this API. When the app client saves the subscription purchase information with PurchaseSubscriptionAsync and then passes the receipt information to the app server, the app server calls this API. For the implementation procedure for each payment provider, see Verify Apple subscription product receipts and Verify Google Play subscription product receipts.
Before calling the API
- Caller:
app server - Base URL
- Production:
https://commerce-api.hiveaxyl.com - Sandbox:
https://sandbox-commerce-api.hiveaxyl.com
- Production:
- Authentication:
Authorization: Bearer {access-token}
Warning
Put the token for the app server that you received from Issue a token in the authentication header. Keep the access token and the Client Secret used for token issuance only on the app server, and do not include them in the app client.
Call parameters
| Name | Location | Type | Required | Description |
|---|---|---|---|---|
X-App-Id | header | string | true | The App ID registered in the Hive Console. |
X-SDK-Version | header | string | false | Client SDK version information. |
X-Platform | header | string | false | Platform information. |
X-OS-Version | header | string | false | Operating system version information. |
Accept-Language | header | string | false | Client language setting. |
traceparent | header | string | false | W3C Trace Context header for distributed tracing. |
User-Agent | header | string | false | User-Agent information of the client application. |
| body | body | SubscriptionPurchaseVerifyRequest | true | Subscription receipt verification request information. |
Request body SubscriptionPurchaseVerifyRequest
| Field | Type | Required | Description |
|---|---|---|---|
accountUuid | string(uuid) | true | Value that links the logged-in user to this subscription record. Put the value the app client created in Generate an AccountUuid. Auto-renewal notifications contain no user information, so this value is also used as the key to find the user who receives the benefits on renewal. If you send a different value with each request, the previous payment record cannot be found on auto-renewal or purchase restoration, and iapPayload cannot be restored. |
appVersion | string | false | App version. |
axylReceipt | string | true | Subscription purchase receipt. The value to put differs by market, so see Request values by market. |
country | string | true | Country code. Uses the ISO 3166-1 two-letter format. |
currency | string | false | Currency. Uses the ISO 4217 three-letter format. |
iapPayload | string | false | Payload defined by the app. The value you send is saved as is and returned as hiveAxylPayload in the response. |
language | string | true | Language code. Uses the ISO 639-1 two-letter format. |
projectInfo | object | false | Additional information for each app. |
providerId | string | true | Market type. Subscriptions support only APPLE and GOOGLE. |
requestType | integer | true | Request type. 1 is a new purchase and 2 is purchase restoration; only these two values are allowed. |
serverId | string | false | Server ID registered in App Info > App Server of the Hive Console. For details, see App server. |
storeTransactionId | string | false | Store transaction ID. How it is used differs by market, so see Request values by market. |
Request values by market
The following fields take different values, or are processed differently by the server, depending on the market.
providerId:APPLEaxylReceipt: The original StoreKit 2 transaction JWS issued by Apple App Store. Pass the string, which consists of three parts (header, payload, and signature), as is.accountUuid: Pass the same value you put inappAccountTokenof the Apple purchase request. The result of the server comparing the two values is returned ashiveAxylAccountUuidComparein the response.storeTransactionId: If you pass the transaction JWS, the lookup keyoriginalTransactionIdis inside the receipt, so you can omit it. Even if you send a value with it, the value inside the receipt takes precedence.
providerId:GOOGLEaxylReceipt: ThepurchaseTokenstring issued by Google PlayaccountUuid: Pass the same value you put inObfuscatedAccountIdof the Google purchase request. The result of the server comparing the two values is returned ashiveAxylAccountUuidComparein the response.storeTransactionId: You do not need to pass it. The server creates the lookup key from the market reverification result and does not use this value even if you pass it.
Call example
curl -X POST 'https://commerce-api.hiveaxyl.com/payment/v1/subscription/verify' \
-H 'Authorization: Bearer {access-token}' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'X-App-Id: {app-id}' \
-d '{
"providerId": "APPLE",
"axylReceipt": "{apple-transaction-jws}",
"country": "KR",
"language": "ko",
"currency": "KRW",
"accountUuid": "123e4567-e89b-12d3-a456-426614174000",
"requestType": 1,
"serverId": "server01",
"iapPayload": "iap_payload_data"
}'
curl -X POST 'https://commerce-api.hiveaxyl.com/payment/v1/subscription/verify' \
-H 'Authorization: Bearer {access-token}' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'X-App-Id: {app-id}' \
-d '{
"providerId": "GOOGLE",
"axylReceipt": "{google-purchase-token}",
"country": "KR",
"language": "ko",
"currency": "KRW",
"accountUuid": "123e4567-e89b-12d3-a456-426614174000",
"requestType": 1,
"serverId": "server01",
"iapPayload": "iap_payload_data"
}'
Response
For the common data and meta, the error body, the product common error codes, and the receipt verification outcome.message values, see Payment responses and errors. This section describes the objects this API actually returns and the handling specific to this API.
Success response data object
| Field | Type | Description |
|---|---|---|
data.hiveAxylAccountUuidCompare | integer | Result of comparing accountUuid in the request with the account identifier in the market verification result. 1 means a match, 2 a mismatch, and 9 that comparison is not possible. If 2 is returned, handle it according to your app's security policy; Hive Axyl does not automatically block the payment or benefit delivery. 9 is not a mismatch. |
data.hiveAxylAutoRenewProductId | string or null | Product ID to be renewed in the next cycle. If it differs from hiveAxylProductId, the product changes in the next cycle; if it is the same, the subscription renews as is. If auto-renewal is off, it is null. For Apple, it is the renewalInfo.autoRenewProductId value; for Google, the current product ID is returned if no product replacement is scheduled. |
data.hiveAxylCurrency | string or null | Currency code. It is the value the server received from the market, so it can differ from the request value; if the currency cannot be obtained from the market, it is null. |
data.hiveAxylDuplicated | boolean | true if the receipt has already been verified. Even when it is true, the verification itself succeeded; only the duplicate save is skipped. |
data.hiveAxylExpiresDate | integer or null | Subscription expiration time. In Unix epoch milliseconds; null if the market does not provide the value. |
data.hiveAxylOriginalStoreTransactionId | string or null | Transaction ID of the first payment. Every cycle of this subscription has the same value, so look at it together with hiveAxylStoreTransactionId to tell whether it is a renewal or a new subscription. For Apple, it is originalTransactionId; for Google, it is the order ID of the first payment. |
data.hiveAxylPayload | string or null | The iapPayload value of the request, returned as is. |
data.hiveAxylPrice | number or null | Verified payment amount. It is the value the server received from the market: for Apple, it is the unit price set in App Store Connect, and for Google, it is the total amount including tax, so the values from the two markets have different meanings. null if the amount cannot be obtained from the market. |
data.hiveAxylProductId | string | Verified subscription product ID. It is based on the market verification result, so it can differ from the request value. |
data.hiveAxylQuantity | integer | Purchase quantity. Subscriptions cannot be sold in bundled quantities, so it is 1. |
data.hiveAxylReceiptVerifyResult | object | Original market verification result. It is the entire value that the server received from the market and normalized; use it when the app server needs to make additional decisions. |
data.hiveAxylRefundDate | integer or null | Refund time. In Unix epoch milliseconds; null if not refunded. For Google, the market does not provide the refund time, so it is always null. |
data.hiveAxylStoreTransactionId | string | Market transaction ID. For Apple, it is the originalTransactionId value, and for Google, the orderId value; use it to identify and reconcile subscriptions. |
data.hiveAxylTransactionId | string(uuid) | Transaction ID of the verification record. If hiveAxylDuplicated is true, the value issued at the first verification is returned as is. |
Response example
{
"data": {
"hiveAxylAccountUuidCompare": 1,
"hiveAxylAutoRenewProductId": "com.test.sub.monthly",
"hiveAxylCurrency": "KRW",
"hiveAxylDuplicated": false,
"hiveAxylExpiresDate": 1785376709000,
"hiveAxylOriginalStoreTransactionId": "2000000000000001",
"hiveAxylPayload": "iap_payload_data",
"hiveAxylPrice": 1200,
"hiveAxylProductId": "com.test.sub.monthly",
"hiveAxylQuantity": 1,
"hiveAxylReceiptVerifyResult": { ... },
"hiveAxylRefundDate": null,
"hiveAxylStoreTransactionId": "2000000000000001",
"hiveAxylTransactionId": "019fc59f-8340-7656-b91e-3a47d465e594"
},
"meta": null
}
{
"data": {
"hiveAxylAccountUuidCompare": 1,
"hiveAxylAutoRenewProductId": "com.test.sub.monthly",
"hiveAxylCurrency": "KRW",
"hiveAxylDuplicated": false,
"hiveAxylExpiresDate": 1785376709000,
"hiveAxylOriginalStoreTransactionId": "GPA.3301-9758-9251-77321",
"hiveAxylPayload": "iap_payload_data",
"hiveAxylPrice": 1200,
"hiveAxylProductId": "com.test.sub.monthly",
"hiveAxylQuantity": 1,
"hiveAxylReceiptVerifyResult": { ... },
"hiveAxylRefundDate": null,
"hiveAxylStoreTransactionId": "GPA.3389-9543-8198-17604",
"hiveAxylTransactionId": "019fc59f-8340-7656-b91e-3a47d465e594"
},
"meta": null
}
Notes for each API
If hiveAxylRefundDate has a value, the subscription was refunded. In this case, reclaim the subscription benefits. For Google subscriptions, hiveAxylRefundDate is always null, so do not use this value to determine whether a refund occurred. If you need the original information that the market provided, check hiveAxylReceiptVerifyResult.
hiveAxylExpiresDate is the time the subscription expires. After this time passes, do not maintain the subscription benefits.
If hiveAxylDuplicated is true, the receipt has already been verified. The verification itself succeeded, so do not treat it as an error; check the delivery history so that you do not deliver the same subscription benefits again.
Response status
| Status | Content type | Meaning | Response header | Response body or handling |
|---|---|---|---|---|
200 | application/json | Verification succeeded | - | data contains the verified subscription information. |
400 | application/problem+json | Request error or payment product error | - | - |
500 | application/problem+json | Server error | - | - |
Get purchase history
POST /payment/v1/transactions
Retrieves the purchase history from Google Play, Apple App Store, Steam, and PG. Check each user's purchase history and use it to handle payment inquiries and for operational checks. You can specify only one payment provider per request, so if you need the purchase history of multiple payment providers, retrieve it for each provider.
Items are returned starting from the newest, based on the verification processing time; if there are many results, use the cursor to continue retrieving the next page.
Before calling the API
- Caller:
app server - Base URL
- Production:
https://commerce-api.hiveaxyl.com - Sandbox:
https://sandbox-commerce-api.hiveaxyl.com
- Production:
- Authentication:
Authorization: Bearer {access-token}
Warning
Put the token for the app server that you received from Issue a token in the authentication header. Keep the access token and the Client Secret used for token issuance only on the app server, and do not include them in the app client.
Call parameters
| Name | Location | Type | Required | Description |
|---|---|---|---|---|
X-App-Id | header | string | true | The App ID registered in the Hive Console. |
X-SDK-Version | header | string | false | Client SDK version information. |
X-Platform | header | string | false | Platform information. |
X-OS-Version | header | string | false | Operating system version information. |
Accept-Language | header | string | false | Client language setting. |
traceparent | header | string | false | W3C Trace Context header for distributed tracing. |
User-Agent | header | string | false | User-Agent information of the client application. |
| body | body | TransactionRequest | true | Purchase history retrieval conditions. |
Request body TransactionRequest
| Field | Type | Required | Description |
|---|---|---|---|
cursor | string | false | When you retrieve the next page, pass the meta.page.nextCursor value from the previous response as is, without modifying it. Omit it for the first page. |
endDate | string(date-time) | false | Retrieval end time. In UTC; if omitted, the current time is used. It must be later than startDate. |
providerId | string | true | Payment provider to retrieve. Specify one of APPLE, GOOGLE, PG, and STEAM. |
size | integer | false | Number of items per page. Specify 1 to 100; the default value is 20. |
startDate | string(date-time) | true | Retrieval start time. In UTC. |
targetPlayerId | integer(int64) | false | Filters the results by the Player ID of a specific user. Available only when you call with the token for the app server; if omitted, the Player ID of the authentication token is used. |
transactionId | string | false | Retrieves a single item by store purchase number. Returns the transaction that exactly matches storeTransactionId in the response. |
Call example
curl -X POST 'https://commerce-api.hiveaxyl.com/payment/v1/transactions' \
-H 'Authorization: Bearer {access-token}' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'X-App-Id: {app-id}' \
-d '{
"providerId": "GOOGLE",
"startDate": "2026-04-16T00:00:00",
"endDate": "2026-05-16T23:59:59",
"size": 20,
"targetPlayerId": 12345
}'
Response
For the common data and meta, the error body, and the product common error codes, see Payment responses and errors. This section describes the objects this API actually returns and the handling specific to this API.
Success response data object
| Field | Type | Description |
|---|---|---|
data | array | List of purchase history items. The items are ordered from the newest, based on verifiedDate. |
Nested success response object data[]
| Field | Type | Description |
|---|---|---|
providerId | string | Payment provider. One of APPLE, GOOGLE, PG, and STEAM. |
purchaseAmount | string | Purchase amount. |
purchaseCurrency | string | Purchase currency. |
purchaseDate | string(date-time) | Time related to the purchase. In UTC; which event's time it is differs by payment provider. For Apple and Google, it is the store payment time; for PG, the payment confirmation time; and for Steam, the order creation time. The Steam value is earlier than the actual payment time, so do not use it as is for settlement reconciliation. If the value cannot be determined, it contains the same value as verifiedDate; check which event it is with purchaseDateSource. |
purchaseDateSource | string | Indicates which event's time purchaseDate is. STORE_PAYMENT is the store payment time, PAYMENT_CONFIRMED the payment confirmation time, and ORDER_CREATED the order creation time; VERIFIED means that the actual purchase time is unknown, so verifiedDate was used as is. |
storeTransactionId | string | Purchase number for each store. For Apple, it is the transactionId value; for Google, PG, and Steam, it is the orderId value. |
transactionId | string(uuid) | Hive Axyl transaction ID. |
verifiedDate | string(date-time) | Verification processing time. In UTC; it is the basis for list sorting and for the cursor. |
Success response meta object
| Field | Type | Description |
|---|---|---|
meta.page.hasNext | boolean | true if there is a next page. |
meta.page.nextCursor | string or null | Cursor used to retrieve the next page. |
meta.page.hasPrevious | null | This API does not support retrieving the previous page, so it is always null. |
meta.page.previousCursor | null | This API does not support retrieving the previous page, so it is always null. |
API-specific additional error object
In a 400 error response, the cause of the failure is identified by the following outcome.message values.
UNAUTHORIZED_REQUEST: Authentication failedFORBIDDEN_REQUEST: A request that specifiedtargetPlayerIdwhile calling with a user login tokenINVALID_CURSOR: InvalidcursorformatCURSOR_CONTEXT_MISMATCH: Retrieval conditions changed while paging
Response example
{
"data": [
{
"providerId": "GOOGLE",
"purchaseAmount": "1200",
"purchaseCurrency": "KRW",
"purchaseDate": "2026-05-16T12:34:56",
"purchaseDateSource": "STORE_PAYMENT",
"storeTransactionId": "GPA.3312-1234-5678-90123",
"transactionId": "019fc59f-8340-7656-b91e-3a47d465e594",
"verifiedDate": "2026-05-16T12:35:10"
}
],
"meta": {
"page": {
"hasNext": true,
"nextCursor": "{next-cursor}",
"hasPrevious": null,
"previousCursor": null
}
}
}
Notes for each API
The retrieval period is up to 30 days. This limit applies even if you omit endDate. However, when you retrieve a single item by transactionId, there is no period limit, so you can also find old orders.
Omit cursor in the first request. If meta.page.hasNext in the response is true, put the meta.page.nextCursor value as is in cursor of the next request and call again. The cursor also contains the retrieval conditions of the first request, so if you change providerId, the retrieval period, transactionId, or targetPlayerId in the next request, a CURSOR_CONTEXT_MISMATCH error is returned. To change the conditions, retrieve again from the first page.
This API retrieves in only one direction, starting from the newest items. It does not provide a cursor that goes back to the previous page, so to check earlier pages again, retrieve from the first page.
Caution
Purchase history items tell you the payment amount, the time, and the transaction number. Do not use this response to determine refunds and cancellations.
Response status
| Status | Content type | Meaning | Response header | Response body or handling |
|---|---|---|---|---|
200 | application/json | Retrieval succeeded | - | data contains the purchase history list, and meta.page contains the cursor information. |
400 | application/problem+json | Request error or payment product error | - | - |
500 | application/problem+json | Server error | - | - |
Error codes by API
| Code | Condition | How to handle |
|---|---|---|
payment_forbidden | The request is not allowed. | Check the cause with outcome.message in the response. |