---
title: "Catalog and recipients"
description: "Each product in the catalog is one item at one fixed amount. Its recipient_fields tell you which account fields to collect for a top-up."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.cardzone.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Catalog and recipients

This page explains the product list (the catalog) and how to collect the customer's account details for a top-up.

The catalog is a list of **products**. Each product is one item at one fixed amount, such as *PUBG 60 UC* or *PlayStation Saudi 160 USD*. To order a product, send its `id` as `product_id`.

## Product fields you need

| Field | What it is for |
| --- | --- |
| `id` | The `product_id` you send when you order. |
| `delivery_type` | `topup` adds credit to a game account. `voucher` returns a code or PIN in `codes[]`. |
| `recipient_fields` | The account fields a top-up needs, in the order you should show them. Empty for vouchers. |
| `player_lookup` | `true` when [player lookup](https://docs.cardzone.ai/guides/player-lookups/) can show the account name before the customer orders. |
| `purchase_price` | What your store wallet pays for one unit. |
| `recommended_retail_price` | The price Cardzone suggests you charge your customer. |
| `status` | `available`, `out_of_stock`, or `unavailable`. See [availability](#availability). |
| `product_code` | Cardzone's internal code. Give it to support when you ask about a product. Don't parse it. |
| `description` | Optional HTML in the request language. Cardzone cleans (sanitizes) it first. It can have paragraphs, lists, links, and images. Show it as HTML, or remove the tags. If it is missing, leave it out of your page. |

Amounts are decimal strings with a currency, such as `{"amount": "12.00", "currency": "SAR"}`. Parse them as decimals, not floats. Floating-point numbers can round money amounts wrongly.

[List products](https://docs.cardzone.ai/reference/products/list/) returns your whole catalog in one response. It is sorted by category name, then by product name. There is no pagination (no pages) and no sort parameter. [List categories](https://docs.cardzone.ai/reference/categories/list/) is sorted by name.

## Build the form from `recipient_fields`

A **recipient** is the person who receives the order. For a top-up, `recipient` holds the player's game account details. For a voucher, it can hold contact details.

NEVER hardcode which games need which fields. Instead, build the form from `recipient_fields`:

1. Show one input for each entry in `recipient_fields`.
2. Use the entry's `label` as the input's label.
3. Send the value in `recipient`, under the entry's `key`.

For example, these `recipient_fields`:

```json
"recipient_fields": [
  { "key": "player_id", "label": "Player ID", "required": true },
  { "key": "zone_id", "label": "Zone ID", "required": true }
]
```

become this `recipient` in your order:

```json
"recipient": { "player_id": "12345678", "zone_id": "1234" }
```

Try it with the sandbox catalog. Switch to **العربية** (Arabic) to see the labels the API returns for `Accept-Language: ar`. The form is then laid out right to left:

## Rules the API enforces

- **Send every key in `recipient_fields`.** If a key is missing, you get `422 validation_failed`. This happens before any order or fulfillment exists. `details` says what is missing, for example `"recipient": ["is missing zone_id"]`.
- **Send values as strings.** Player IDs can start with zero. `"00123456789"` and `123456789` are different accounts.
- **Use the exact key from `recipient_fields`.** NEVER use another name for the same field. Send `player_id`, not `userId` or `account_id`, unless that exact key is in `recipient_fields`.
- **Vouchers take delivery contacts only.** For voucher products, `recipient` may hold `name`, `email`, and `mobile`. If you send a top-up field such as `player_id`, you get `422` with `topup recipient fields are not accepted for voucher products`.
- **Top-ups take `recipient_fields` keys only.** If you send `name`, `email`, `mobile`, or any other key that the top-up doesn't list, you get `422` with `"recipient": ["contains unexpected fields: email"]`. If `recipient` isn't a JSON object, you get `"recipient": ["must be an object"]`.

## Cardzone delivers voucher codes too

When a voucher order is fulfilled, Cardzone sends the code to the contacts in `recipient`:

- by email to `email`.
- by SMS to `mobile`, and also by WhatsApp where it is enabled.

The codes are also in `codes[]` on the order.

If you deliver codes yourself, leave out `email` and `mobile`. Otherwise your customer gets the code twice.

When an order has an `email` or `mobile`, Cardzone also creates or updates a customer record in your Cardzone store.

## Filter by category

[List categories](https://docs.cardzone.ai/reference/categories/list/) returns category slugs (short text IDs) such as `pubg`. To show only one category, pass its slug as `category_id` to [List products](https://docs.cardzone.ai/reference/products/list/). An unknown slug returns `404`.

## Availability

Every product and category has a `status`:

| `status` | Meaning |
| --- | --- |
| `available` | Your store can order it now. |
| `out_of_stock` | Sold out for now. It usually comes back. Keep it in your catalog and show it as sold out. |
| `unavailable` | Your store can't order it right now, for any other reason. |

By default, [List products](https://docs.cardzone.ai/reference/products/list/) and [List categories](https://docs.cardzone.ai/reference/categories/list/) return only what you can order now. So every row is `available`.

Add `include_unavailable=true` to also get products that you can see but can't order right now. They are marked `out_of_stock` or `unavailable`. Then you can show "sold out" instead of hiding the product with no explanation.

A category's `status` is the best status among its products.

Some products never appear, even with `include_unavailable`: products that are hidden from your store, and products that have no price.

Availability can change between the time you list products and the time you order. If you order a product you can't order, you get `404` with `details: "product_not_found"`. When Cardzone knows why, `error.product_status` tells you:

```json
{
  "error": {
    "code": "validation_failed",
    "message": "Validation failed",
    "details": "product_not_found",
    "product_status": "out_of_stock"
  }
}
```

What to do:

- `out_of_stock`: try again later.
- `unavailable`, or no `product_status` at all (the product is unknown or deleted): refresh your saved copy of the catalog.

In every case, refresh your saved copy of the catalog regularly.

Source: https://docs.cardzone.ai/concepts/catalog-and-recipients/index.mdx
