/consumer/v1) and the Workspace API (/partner/v1) follows the conventions on this page. Learn them once and every reference page reads the same way.
Format
- Requests and responses are JSON in UTF-8. Send
Content-Type: application/jsonwith every request that has a body. - The API is HTTPS only (TLS 1.2 or later). Production is
https://api.voucher.allride.io, the sandbox ishttps://api.voucher-staging.allride.io. - Property names are
camelCase; enum values arekebab-case(deactivation-scheduled). - Nullable properties are always present. A value that is not set is
null, never a missing key, so you can rely on the shape of every resource. - Send
Accept-Language: deorento choose the language of server-formatted text such as money labels and error messages. The response carriesContent-Language. - Every response carries
X-Request-Id. You can send your ownX-Request-Id(1-100 characters of letters, digits and._:-) to correlate requests with your logs.
Response envelopes
A response that returns one resource wraps it indata:
data:
Every resource has
id, resource (its type, for example redemption or redemption-link) and _links. _links maps a relation name to {href, type}; self is always present. A link appears only when your key or user holds the permissions to follow it. Value objects and statistics rows (for example analytics rows) carry resource but no id or _links.
Identifiers
- Ids are positive integers (
"id": 42), unique per resource type. They are JSON numbers in bodies and plain numbers in paths (/consumer/v1/redemptions/6017). - An id that is not a positive integer, in the path, the query or the body, is answered with
400 data-failed-validation; the entry inmore.validationErrorshas the constraintinvalid-idand names the parameter or property. - A well-formed id that does not exist or belongs to another partner is answered with
404and the resource’s not-found code, for exampleredemption-not-found. You never see another partner’s data, not even its existence. - Your own references use separate fields:
refIdon redemption entities (1-128 characters of letters, digits and._:@/+=-) andexternalRefon catalog settings (at most 64 characters). Never put personal data into them.
Dates and times
- Timestamps are RFC 3339 in UTC with
Z, at millisecond precision, truncated: no fraction when the milliseconds are zero (2026-11-01T00:00:00Z), otherwise exactly three digits (2026-10-21T17:42:10.120Z). Accept both shapes. - Timestamps you send must carry an offset (
Zor+01:00); they are normalised to UTC.2026-12-31T23:59:59+01:00is stored and returned as2026-12-31T22:59:59Z. A timestamp without an offset fails with the constraintinvalid-timestamp. - Dates are
YYYY-MM-DD, monthsYYYY-MM. - Calendar periods (analytics months and days, per-entity monthly limits) are evaluated in your partner
timezone, an IANA id such asEurope/Berlin. - Exception for billing: billing service months and billing dates (
issueDate,dueDate,collectionDate) are calendar months and dates inEurope/Berlin, whatever your partner timezone. Billing resources that carry a month also carrybillingZone: "Europe/Berlin". A redemption at2026-10-31T23:30:00Zby a partner inEurope/Londoncounts in analytics month2026-10and in billing service month2026-11. See Billing. - Durations are integers whose unit is in the property name:
gracePeriodMinutes,expiresInMinutes,paymentTermsDays. - Intervals are half-open:
[from, to). Filter ranges withgteandlt.
Money
All amounts are in euros (EUR).value is in cent.
Money is an object with the amount in cent and a formatted label:
valueis an integer, never a float.labelis formatted in the response language (€29.00in English,29,00 €in German).- In requests send
{"value": 2900}. Alabelyou send is accepted and ignored, so you can send back what you read. - Amounts that can be negative (Stornorechnungen, balances) use the same shape with a signed
value, for example{"value": -1250, "label": "-12,50 €"}. - Per-redemption unit prices in billing and pricing add a
scaleproperty:{value, scale, label}withscalealways4andvaluein ten-thousandths of a euro.1000is €0.10 and1250is €0.1250:
"19.00"), never JSON numbers. See Billing and Prices and price acceptance.
Localised text
Texts that providers and partners write per language (voucher set names, terms, landing texts) are objects keyed by locale:- Responses always return the full map. Pick the locale for your customer on your side.
- When you send localised text, include your partner’s default locale.
- Rich text fields use a restricted Markdown subset (paragraphs, line breaks, bold, italic, lists, headings level 3-4 and https links). Render them with a sanitising Markdown renderer, never as raw HTML.
Large integers
Ids and large counters (maxRedemptions, redemptionCount) are unsigned 64-bit integers. They are JSON numbers and can exceed 2^53, the largest integer a JavaScript number represents exactly. In JavaScript, parse responses with a BigInt-safe JSON parser (for example json-bigint) or keep these values as strings. In the OpenAPI document these fields have format: uint64; configure your client generator to map them to a 64-bit or arbitrary-precision type.
Updating resources
PATCHis a JSON Merge Patch: a property you leave out stays unchanged,nullclears it, any other value replaces it.PUTreplaces the whole resource (for examplePUT /partner/v1/smtp-configuration).DELETEanswers204without a body.- Request bodies are strict: a property the operation does not define is refused with the constraint
unknown-field, and an undeclared query parameter withunknown-parameter. Read-only properties such asidorlabelin money are the only values you may echo back.
Concurrent changes
Updates are last-writer-wins per field. Resources carry no version number, responses carry no entity tag, and there are no conditional request headers: you never send a precondition with a write.- An update writes only the properties you sent. Two clients that change different properties of the same resource both succeed, and neither overwrites the other.
- When two clients change the same property at the same time, the later write wins. If you need one writer, coordinate it on your side.
-
A command that changes the state checks the current state inside the same transaction. If another request changed it in the meantime, the command answers
409with a code that names the state it found (a state race). On this site these are, for example:Read the resource again before you decide what to do; retrying the same request gives the same answer. -
If the database could not complete your write because of a concurrent one (a deadlock or a serialization failure), you get
409concurrent-update; retry with backoff and the sameIdempotency-Key. This is the only transient conflict code; there is no per-resource concurrency error.
Commands and batch operations
- Actions that are not plain updates are commands:
POSTto the resource path with a colon and a verb, for examplePOST /consumer/v1/redemptions/{redemptionId}:voidorPOST /consumer/v1/redemption-links/{redemptionLinkId}:revoke. - Bulk operations are
POSTto the collection with:batch, for examplePOST /consumer/v1/redemptions:batch. Batches are all or nothing: if one item fails, nothing is created, and the error names the item (items[2]) inmore.validationErrors. - Batch results use the single-object envelope around one result resource whose
itemskeep the order of your request. - Every
POST, commands and batches included, accepts anIdempotency-Key.
Asynchronous jobs
No operation on the consumer site runs as an asynchronous job: every request answers when its work is done, and there are no export jobs (to get a whole list, see Downloading large lists). Asynchronous jobs exist only on the provider site (voucher uploads) and follow this pattern:1
Start the job
The command answers
202 Accepted with the job in its initial status, a Location header with the job URL and Retry-After: 2.2
Poll the job
GET the Location URL after Retry-After seconds. Double the interval on each poll, up to 30 seconds.3
Use the result
When the job’s status is final, read its result.
202 shows the job as it was when it was accepted. Always follow Location for the current state.
Compatibility rules
Withinv1 the API changes only in backwards-compatible ways (see Versioning and deprecation). To keep working when it does, your client must:
- ignore response properties and
_linksrelations it does not know; - treat enum values it does not know as “other” (every enum is an open set);
- ignore members of an error entry or its
moreobject that it does not know; - ignore webhook event types it has not subscribed to or does not know.
X-Request-Id of the response (for server errors it is also in requestId).