Returning.AIDevelopers
v1

API reference / Store / Products

.md

Read product

Read one Store product in your community by its ID, with price, category, access rules and current stock.

Last updated 26 Sep 2026API v1

Method
GET
Path
https://api.returning.ai/v1/products/{productID}
Permission
store
Retries
Read-only; exact retries are safe

When to use this

  • Confirm a product and its stocks after you create or update it.
  • Fetch the current settings before a full update, so you only change what you mean to.
  • Check an archived product, which List products leaves out.

Authentication#

Header
Authorization: Bearer <API_KEY>
Permission
storeShown in the dashboard as “Store”

Send a Community API key with the store permission. The key decides the community, so never send a community ID. Keep the key on your server.

Request#

Path parameters#

productID#stringREQUIRED
Product ID, from List products or Create product with vouchers.

Rule24-character hex ID

Eg66f000000000000000000101

Query parameters#

fields#stringOPTIONAL
Comma-separated fields to return. Include _id when you need the ID. categoryID also returns category; category itself is not accepted. Without it, every field is returned.

RuleProduct field names

Eg_id,name,price,categoryID,stocks

lang#stringOPTIONAL
Language code for translated names and descriptions, such as th.

RuleLanguage code

Egth

Headers#

Authorization#stringREQUIRED
Community API key with store.

RuleBearer <API_KEY>

curl --request GET \
  --url https://api.returning.ai/v1/products/66f000000000000000000101 \
  --header 'Authorization: Bearer <API_KEY>'

Response#

A 200 returns the product in data, including archived products (isArchived: true). stocks counts voucher codes that are unsold and not expired; the codes themselves are never returned. Branch on the HTTP status and meta.code, never on message.

meta#objectALWAYS
Status details.

Eg{ ... }

status#stringALWAYS
Result of the request.

Rulesuccess

statusCode#integerALWAYS
The HTTP status, repeated.

Eg200

code#stringALWAYS
Machine-readable result code.

RulePRODUCT_RETRIEVED

message#stringALWAYS
Human-readable summary. Do not branch on it.

Eg"Read product success."

data#objectALWAYS
The product.

Eg{ ... }

_id#string
Product ID. Use it to read or update the product.

Eg"66f000000000000000000101"

name#string
Product name shown in the Store.

Eg"$25 Trading Credit"

price#number
Price in coins.

Eg500

categoryID#string
Category ID, or null when the product has no category.
category#string
Category name, or null when the product has no category or its category was deleted.

Eg"Trading rewards"

stocks#integer
Vouchers left to buy: codes that are unsold and not expired. Voucher codes are never returned.

Eg2

isArchived#boolean
true when the product is archived and left out of List products and the Store.

Egfalse

image#string
Image URL, or null when there is no image.

Eg"https://cdn.example.com/store/trading-credit-25.png"

description#string
Product description as HTML. Only basic formatting tags are kept.

Eg"<p>Redeem 500 coins for a $25 trading credit on your live account.</p>"

redemptionInstructions#string
Redemption instructions for the trader, or null.

Eg"<p>Your credit is added to your trading account after approval.</p>"

discountPrice#number
Discounted price in coins, charged between the discount dates while the discount is on.

Eg0

isDiscountEnabled#boolean
true when the discount is switched on.

Egfalse

discountStartDate#string
When the discount starts, ISO 8601 UTC, or null.

Egnull

discountEndDate#string
When the discount ends, ISO 8601 UTC, or null.

Egnull

userInformation#object
What the trader is asked for when they redeem.

Eg{ ... }

isEnabled#boolean
true when the trader is asked for details.

Egfalse

shouldCollectName#boolean
true to ask for their name.

Egfalse

shouldCollectPhone#boolean
true to ask for their phone number.

Egfalse

shouldCollectAddress#boolean
true to ask for their address.

Egfalse

shouldDisplayRemainingQuantity#boolean
true to show traders how many are left.

Egtrue

shouldPrioritiesExpiringVouchers#boolean
true to prioritise the vouchers closest to expiry.

Egfalse

expiringVoucherHighlight#object
Highlight for vouchers close to expiry.

Eg{"isEnabled": false, "duration": 7, "timeframe": "days"}

isEnabled#boolean
true when the highlight is on.

Egfalse

duration#integer
How close to expiry, in timeframe units.

Eg7

timeframe#string
Unit for duration, such as days.

Eg"days"

isProductAccessEnabled#boolean
true when the product's own rules apply; false when it follows its category.

Egfalse

productPermission#object[]
Access rules. An empty array means the product has no rules of its own.

Eg[]

isEnabled#boolean
true when the rule is active.

Egtrue

type#string
What the rule matches.

Ruleuser, role, tag or role_combination

Eg"role"

permission#object
The traders the rule covers, by readable name.
roleNames#string[]
Role names.
tagNames#string[]
Tag names.
usernames#string[]
Usernames.
userIDs#string[]
Record IDs of the traders the rule names. Send usernames when you write rules.
combination#object[]
Role or tag groups a trader must hold together.
type#string
role or tag.

Eg"role"

values#string[]
Role or tag names in the group.
isSelectAll#boolean
true when the rule covers all traders.
purchaseAccess#object
Special price for traders the rule covers.
specialPrice#number
Special price in coins.

Eg80

isSpecialPriceEnabled#boolean
true when the special price applies.

Egfalse

purchaseLimit#object
How often a covered trader can buy.
isPurchaseLimitEnabled#boolean
true when the limit applies.

Egfalse

quantity#number
Purchases allowed in each window.

Eg1

intervalCount#number
Length of the window, in intervalUnits.

Eg1

intervalUnit#string
Unit of the window, such as months.

Eg"months"

accessLevel#string
What covered traders can do.

Rulefull-access, view-only or access-denied

Eg"full-access"

isExclusiveTagEnabled#boolean
true to show the exclusive tag.

Egfalse

purchaseStatusOverride#object
The status new orders for this product start in, when set.

Eg{"isEnabled": false, "status": null}

isEnabled#boolean
true when new orders start in status.

Egfalse

status#string
Order status name, or null when the category or community default applies.

Egnull

totalOrders#integer
Orders placed for this product.

Eg0

communityID#string
Your community ID.

Eg"66f000000000000000000010"

createdAt#string
When the product was created, ISO 8601 UTC.

Eg"2026-09-26T08:30:00.000Z"

updatedAt#string
When the product last changed, ISO 8601 UTC.

Eg"2026-09-26T09:15:00.000Z"

{
  "meta": {
    "status": "success",
    "statusCode": 200,
    "code": "PRODUCT_RETRIEVED"
  },
  "message": "Read product success.",
  "data": {
    "_id": "66f000000000000000000101",
    "communityID": "66f000000000000000000010",
    "name": "$25 Trading Credit",
    "description": "<p>Redeem 500 coins for a $25 trading credit on your live account.</p>",
    "image": "https://cdn.example.com/store/trading-credit-25.png",
    "price": 500,
    "categoryID": "66f000000000000000000201",
    "category": "Trading rewards",
    "stocks": 2,
    "discountPrice": 0,
    "isDiscountEnabled": false,
    "discountStartDate": null,
    "discountEndDate": null,
    "userInformation": {
      "isEnabled": false,
      "shouldCollectName": false,
      "shouldCollectPhone": false,
      "shouldCollectAddress": false
    },
    "shouldPrioritiesExpiringVouchers": false,
    "shouldDisplayRemainingQuantity": true,
    "expiringVoucherHighlight": {
      "isEnabled": false,
      "duration": 7,
      "timeframe": "days"
    },
    "isArchived": false,
    "totalOrders": 0,
    "redemptionInstructions": "<p>Your credit is added to your trading account after approval.</p>",
    "productPermission": [],
    "isProductAccessEnabled": false,
    "purchaseStatusOverride": {
      "isEnabled": false,
      "status": null
    },
    "createdAt": "2026-09-26T08:30:00.000Z",
    "updatedAt": "2026-09-26T09:15:00.000Z"
  }
}

Errors#

Every error carries its code in meta.code, with the reason in detail. A product in another community returns 404, the same as a missing one.

Fix the request04

400VALIDATION_FAILEDFix the request
productID isn't a 24-character hex ID, or fields names a field that can't be returned. detail says which.
401AUTH_API_KEY_REQUIREDFix the request
No key was sent. Send Authorization: Bearer <API_KEY>.
401AUTH_API_KEY_INVALIDFix the request
The key is unknown, expired or malformed. Use a current Community API key.
403AUTH_PERMISSION_REQUIREDFix the request
The key lacks store. Add the permission in Settings > Integration > API Keys.

Fix the data01

404STORE_RESOURCE_NOT_FOUNDFix the data
No product with this ID in your community. Find the right ID with List products; a deleted product returns this too.

Retry with backoff03

502STORE_DEPENDENCY_UNAVAILABLERetry with backoff
The Store is briefly unavailable. Retry the same request with exponential backoff.
500INTERNAL_ERRORRetry with backoff
Retry the same request with exponential backoff. If it keeps failing, contact Returning.AI with the time of the request.
401AUTH_API_KEY_VALIDATION_FAILEDRetry with backoff
The key could not be checked just now. Retry with backoff; the key itself may be fine.
{
  "meta": {
    "status": "error",
    "statusCode": 400,
    "code": "VALIDATION_FAILED"
  },
  "message": "Validation failed",
  "detail": {
    "productID": "productID must be a valid MongoDB ObjectId string"
  },
  "solution": "Please check the request and try again"
}

Next step#

Update product and append vouchersPUT/v1/products/{productID}Change the product or add stock, starting from the values you just read.