Email Code API

Issues personalised unique single-use coupon codes at scale.


The Email Code API issues unique single-use coupon codes for a given promotion on demand. It is designed for platforms that send personalised messages to large numbers of customers at once — such as Customer Engagement Platforms (CEPs), CRM systems, SMS, and push notifications — where each recipient needs their own unique code at send time.

Each request identifies a recipient via a linkedUniqueReference (typically their email address or customer ID). If a code has already been issued to that recipient for the same promotion, the existing code is returned rather than generating a new one, making repeated calls safe.


Endpoint

POST https://email-code.uniqodo.com/api/code

Authentication

All requests must include a valid API key in the X-API-Key header.

X-API-Key: your-api-key

API keys are scoped to an account type:

TypeAccess rule
MerchantCan issue codes for promotions owned by their merchant account
DistributorCan issue codes for promotions assigned to their distributor account

Request

Headers

HeaderRequiredValue
Content-TypeYesapplication/json
X-API-KeyYesYour API key

Body

FieldTypeRequiredDescription
promotionIdstringYesUUID of the promotion
linkedUniqueReferencestringYesUnique identifier for the recipient (typically their email address)
localestringNoLocale of the request (e.g. en). Accepted but not currently used
expiresAtstring (ISO-8601)NoOverride the code expiry date. If omitted, expiry is determined by the promotion's settings
countdownStartsAtstring (ISO-8601)NoStart point for countdown-based expiry. Used when the promotion has a relative expiry window (e.g. "valid for 7 days")

Example request

curl -X POST https://email-code.uniqodo.com/api/code \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-api-key" \
  -d '{
    "locale": "en",
    "promotionId": "d939a3683ce2c4f5ca51015504cce370",
    "linkedUniqueReference": "[email protected]",
    "expiresAt": "2026-06-15T00:00:00+00:00",
    "countdownStartsAt": "2026-05-15T00:00:00+00:00"
  }'

Response

Success — 200 OK

{
  "codeClaim": {
    "code": "ABC123",
    "createdAt": "2026-05-15T10:00:00+00:00",
    "endDate": "2026-06-15T00:00:00+00:00",
    "promotionId": "d939a3683ce2c4f5ca51015504cce370",
    "destinationUrl": "https://example.com/shop?code={code}",
    "userId": "a1b2c3d4e5f6..."
  },
  "errors": []
}
FieldDescription
codeThe issued promo code
createdAtWhen the code was issued (UTC, ISO-8601)
endDateWhen the code expires (UTC, ISO-8601)
promotionIdUUID of the promotion
destinationUrlLanding page URL for the promotion. May be null if not configured
userIdHashed representation of linkedUniqueReference

Idempotency: if the same linkedUniqueReference requests a code for the same promotion again and their per-user limit has not been exceeded, the existing code is returned rather than a new one being issued.


Error responses

All errors follow the same envelope:

{
  "codeClaim": null,
  "errors": [
    {
      "code": <http-status>,
      "message": "<description>"
    }
  ]
}
HTTP statusCause
400 Bad RequestMissing or invalid request body fields (see messages below)
401 UnauthorizedX-API-Key header is missing, or the key is invalid/inactive
403 ForbiddenAPI key is valid but not authorised for the requested promotion
404 Not FoundNo promotion found for the given promotionId UUID
422 Unprocessable EntityCode could not be issued — e.g. the promotion's third-party code list is exhausted
500 Internal Server ErrorUnexpected server error

400 error messages

MessageCause
Request body must be valid JSON.The Body is missing or not valid JSON
promotionId is required.promotionId field is absent or empty
linkedUniqueReference is required.linkedUniqueReference field is absent or empty
expiresAt must be a valid ISO-8601 date string.expiresAt value cannot be parsed as a date
countdownStartsAt must be a valid ISO-8601 date string.countdownStartsAt value cannot be parsed as a date

Notes

  • expiresAt and countdownStartsAt are mutually usable but serve different purposes. Use expiresAt to set an absolute expiry; use countdownStartsAt with promotions configured for relative expiry (e.g. "code valid for 7 days from email send date"). If both are provided, expiresAt takes precedence.
  • userId in the response is a hashed value by default unless disabled on your account, not the raw linkedUniqueReference.
  • A cookie (cl_<promotionId>) is set on the response for browser-based flows. This can be safely ignored for server-to-server integrations.