Import Vouchers
Bring across gift cards a shop already sold in another system, many in one request. This is the same row-level import the in-app Import vouchers wizard runs, so a voucher created here behaves exactly like one imported in the app.
An imported voucher:
- keeps its code, balance, original value and expiry;
- has
sourceimportandpayment_statusimported, and can be redeemed straight away; - sends no email to the purchaser or recipient, fires no
voucher.soldwebhook and is not synced to accounting as a sale (it was sold, and booked, in the old system).
Rows that can't be saved are reported back individually rather than failing the whole request.
Endpointโ
POST /v1/vouchers/import
Requires the promotions:write scope.
Request Bodyโ
| Field | Type | Required | Description |
|---|---|---|---|
vouchers | array | Yes | 1-500 rows. Each row is an object using the fields below. |
Row fieldsโ
| Field | Type | Required | Description |
|---|---|---|---|
code | string | Yes | The code on the card. Max 50 chars, auto-uppercased. |
remaining_value | string/number | Yes | What is left on the card. 0 imports a used-up card as fully redeemed. Currency symbols and thousands separators are stripped; 40,50 reads as 40.50. |
original_value | string/number | No | What the card was first worth. Defaults to remaining_value; must not be less than it. |
valid_until | string | No | Expiry date. ISO (2026-12-31) or the supplier's own date order, with dashes, slashes or dots. Past dates are accepted and the voucher comes in expired. |
purchaser_name | string | No | Who bought it. Blank is stored as an empty string. |
purchaser_email | string | No | Buyer's email. |
recipient_name | string | No | Who it was given to. |
recipient_email | string | No | Recipient's email. |
currency | string | No | ISO code. When given it must match the supplier's currency; blank means the supplier's currency. |
Example Requestโ
curl -X POST "https://app.equipdash.com/api/v1/vouchers/import" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"vouchers": [
{
"code": "GIFT-1001",
"remaining_value": "65.50",
"original_value": 100,
"valid_until": "2026-12-31",
"purchaser_name": "Jane Doe",
"purchaser_email": "jane.doe@example.test"
},
{
"code": "GIFT-1002",
"remaining_value": 0,
"original_value": 50
},
{
"code": "GIFT-1003",
"remaining_value": "sixty"
}
]
}'
Responseโ
{
"data": {
"imported": 2,
"skipped": 1,
"skipped_rows": [
{
"row": 3,
"code": "GIFT-1003",
"reason": "Balance \"sixty\" is not a number"
}
]
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2026-10-01T10:00:00+00:00"
}
}
row is the 1-based position of the row in the vouchers array you sent.
Skip Reasonsโ
| Reason | Cause |
|---|---|
Already in your vouchers | A voucher with that code already exists. Existing vouchers are never overwritten. |
A code is required | The row has no code. |
A balance is required - use 0 for a card that has been used up | remaining_value is missing. |
Balance "โฆ" is not a number | The balance could not be read. |
The balance is more than the original value | remaining_value is larger than original_value. |
Expiry date "โฆ" not recognized - use a date like 31-12-2026 | The date could not be parsed. |
Currency โฆ is not your shop's currency (โฆ) | currency names a different currency. |
| Validation messages | An email is malformed, a name is too long, or an amount is below zero or above the maximum. |
Notesโ
- Re-sending the same list only adds what's missing.
- A maximum of 500 rows per request; send larger lists in batches.
- Vouchers are always created against the supplier the API key belongs to.