List card products
GET /v1/api-gateway/card/card-products
The response is one page, not the whole catalog: page with current_ / per_ (default 1 / 10) and read pagination.last_ to know how many there are. Any other paging parameter is ignored rather than rejected.
Request
Authentication: your API key in the x-api-key header.
Query parameters
| Field | Type | Description |
|---|---|---|
current_ | integer | Page number, starting at 1. Default 1. Matches pagination.current_ in the response. |
per_ | integer | Card products per page. Minimum 1. Default 10. No maximum: the catalog is paged in memory, so pagination.per_ always reports the value you sent. |
Example request
cURL
curl --request GET \
--url 'https://api.themooncard.com/v1/api-gateway/card/card-products' \
--header 'x-api-key: YOUR_API_KEY'Responses
200 Success
| Field | Type | Description |
|---|---|---|
card_ required | array of object | |
card_ required | string | Card product id. Use it as card_ when issuing a card. |
card_ required | string | Product display name. |
card_ required | string, nullable | ISO-4217 currency the product is denominated in, or null. |
card_ required | boolean | Always true: out-of-stock products are not listed. |
card_ required | string, nullable | Whether the product is an open-loop card, which works anywhere the card network is accepted, or a closed-loop card, which can only be spent with one merchant. Null when the product does not record it. |
card_ required | object | Countries the product can be used in; in practice an array of ISO-3166 alpha-2 codes. |
card_ required | number, nullable | Smallest amount that can be loaded, or null when unrestricted. |
card_ required | number, nullable | Largest amount that can be loaded, or null when unrestricted. |
card_ required | object | Fixed denominations offered by the product, or null when any amount is allowed. |
card_ required | boolean | Whether a card issued from this product can be locked to one merchant. Pass merchant_ on POST /cards only with a product where this is true; any other product is rejected with MERCHANT_. A lock is only as good as the merchant identity that arrives with an authorization, and not every product's authorizations carry one. |
card_ required | array of string | Lowercase category names of the product brand, e.g. ["gaming", "retail"]. Empty when uncategorized. |
card_ required | object, nullable | Brand the product belongs to, or null. |
card_ required | string | Brand id. |
card_ required | string | Brand display name. |
card_ required | string, nullable | |
card_ required | string | Hex colour, e.g. "#000000". |
card_ required | string | Hex colour to use for text on top of primary_. |
card_ required | string, nullable | Brand logo URL, or null. |
card_ required | string, nullable | Card artwork URL, or null. |
card_ required | number | Discount applied to your organization for this product, as a percentage; 0 when none. |
pagination required | object | |
pagination. required | integer | Total number of items across all pages. |
pagination. required | integer | Number of the last page (0 when there are no items). |
pagination. required | integer, nullable | Previous page number, or null on the first page. |
pagination. required | integer, nullable | Next page number, or null on the last page. |
pagination. required | integer | Page size that was applied. |
pagination. required | integer | 1-based current page. |
pagination. required | integer | 1-based index of the first item on this page (0 when empty). |
pagination. required | integer | 1-based index of the last item on this page (0 when empty). |
JSON
{
"card_products": [
{
"id": "a8358b18-be77-41b7-af4d-f4e9760cba86",
"name": "Moon Prepaid Visa (USD)",
"currency": "USD",
"in_stock": true,
"open_or_closed_loop": "OPEN",
"for_use_in_countries": [
"US"
],
"minimum_value": 5,
"maximum_value": 1000,
"denominations": null,
"supports_merchant_lock": false,
"categories": [
"prepaid"
],
"merchant": {
"id": "e5f6a7b8-c9d0-4e1f-8a2b-3c4d5e6f7a8b",
"name": "Acme Superstore",
"description": "Everything, delivered.",
"primary_brand_color": "#0B1F3B",
"primary_text_color": "#FFFFFF",
"logo_s3_url": "https://assets.paywithmoon.com/brands/acme/logo.png",
"card_image_url": "https://assets.paywithmoon.com/brands/acme/card.png"
},
"default_discount": 0
}
],
"pagination": {
"total": 1,
"last_page": 1,
"prev_page": null,
"next_page": null,
"per_page": 10,
"current_page": 1,
"from": 1,
"to": 1
}
}400 Error
Validation failed (errors[] lists each offending field) or a domain rule rejected the request ({ message, code }).
The body is the standard error object: see Errors.
401 Error
Missing or invalid credentials, e.g. { "message": "Invalid API Key", "code": "UNAUTHORIZED" }.
The body is the standard error object: see Errors.
500 Error
Unexpected server error. Body is { message: "Internal server error", code: "INTERNAL_.
The body is the standard error object: see Errors.
Last updated April 30, 2026