Skip to main content

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 source import and payment_status imported, and can be redeemed straight away;
  • sends no email to the purchaser or recipient, fires no voucher.sold webhook 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โ€‹

FieldTypeRequiredDescription
vouchersarrayYes1-500 rows. Each row is an object using the fields below.

Row fieldsโ€‹

FieldTypeRequiredDescription
codestringYesThe code on the card. Max 50 chars, auto-uppercased.
remaining_valuestring/numberYesWhat 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_valuestring/numberNoWhat the card was first worth. Defaults to remaining_value; must not be less than it.
valid_untilstringNoExpiry 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_namestringNoWho bought it. Blank is stored as an empty string.
purchaser_emailstringNoBuyer's email.
recipient_namestringNoWho it was given to.
recipient_emailstringNoRecipient's email.
currencystringNoISO 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โ€‹

ReasonCause
Already in your vouchersA voucher with that code already exists. Existing vouchers are never overwritten.
A code is requiredThe row has no code.
A balance is required - use 0 for a card that has been used upremaining_value is missing.
Balance "โ€ฆ" is not a numberThe balance could not be read.
The balance is more than the original valueremaining_value is larger than original_value.
Expiry date "โ€ฆ" not recognized - use a date like 31-12-2026The date could not be parsed.
Currency โ€ฆ is not your shop's currency (โ€ฆ)currency names a different currency.
Validation messagesAn 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.