Skip to main content

Format

  • Requests and responses are JSON in UTF-8. Send Content-Type: application/json on requests with a body; a body that is not valid JSON is 400 malformed-json.
  • Property and query parameter names are camelCase; enum values, error codes and event types are kebab-case.
  • Unknown request properties and query parameters are refused (400 data-failed-validation with field code unknown-field or unknown-parameter), so typos never get ignored silently.
  • Accept-Language: de or en selects the language of money labels and of emails a request triggers (error messages are English); the response carries Content-Language. Localised content you stored is always returned in full.
  • Every response carries X-Request-Id (yours if you sent a valid one, else generated) and Cache-Control: no-store. Quote the request id when contacting support.

Response envelopes

Every resource has id, resource (a constant kind such as voucher-set), domain fields, timestamps and _links to related resources. Nullable fields are always present, with null when unset; empty lists are [].

Identifiers

Ids are positive integers ("id": 42), in paths and bodies. A malformed id (/voucher-sets/abc) is 400 data-failed-validation with field code invalid-id. A well-formed id that does not exist or belongs to another partner is 404 with the resource’s code, for example voucher-set-not-found; both cases look the same.

Dates and times

  • Timestamps are RFC 3339 in UTC with Z, at millisecond precision: no fraction when the milliseconds are zero (2026-11-01T00:00:00Z), otherwise three digits (2026-10-21T17:42:10.120Z). Accept both shapes.
  • Timestamps you send need an offset (Z or +01:00); they are converted to UTC. Without an offset → field code invalid-timestamp.
  • Dates are YYYY-MM-DD, months YYYY-MM. Calendar periods (statistics) use your partner’s timezone.
  • Durations are integers named by unit, for example gracePeriodMinutes.
  • Time ranges are half-open: [from, to), filtered with gte and lt.

Money

All amounts are in euros (EUR). value is in cent. Money is an object with the integer value and a label formatted in the response locale (de 5,00 €, en €5.00):
Send {"value": 500}; a label in a request is ignored. Amounts are never floats.

Localised text

Texts that consumers see are maps from locale to text, for example "name": {"de": "5 € Fahrguthaben", "en": "€5 ride credit"}. Every text you send must include your partner’s defaultLocale; supported locales are de and en. Responses always contain every locale you stored; pick the one you need client-side. Long texts (description, termsText) are restricted Markdown: paragraphs, line breaks, bold, italic, lists, level 3-4 headings and https links. Render them with a sanitising Markdown renderer, never as raw HTML. See Content rules.

Large integers

Ids and counters such as maxRedemptions, redemptionCount, remaining and used are unsigned 64-bit integers and may exceed 2^53. JavaScript’s JSON.parse loses precision above that: use a BigInt-safe parser (for example json-bigint or lossless-json). In OpenAPI these fields have format: uint64.

Updating resources

  • PATCH is a JSON Merge Patch: absent fields stay unchanged, null clears a field, objects merge. Lists are replaced whole.
  • PUT replaces a whole document (for example the stock alert rule).
  • An update only writes the fields you changed, so two clients that change different fields of the same resource both succeed.
  • PATCH /provider/v1/voucher-sets/{id} with {} returns the set unchanged.

Concurrent changes

There is no optimistic locking: you send no precondition header and no revision number with an update, and the API never rejects a write because someone else changed the resource since you read it.
  • Last writer wins, per field. A PATCH or PUT writes only the fields that change. When two clients change the same field at the same time, the later write wins; when they change different fields of the same resource, both changes survive. For example, one client renaming a voucher set while another changes its maxRedemptions both succeed, and the set ends up with the new name and the new limit.
  • State changes are checked when they run. Commands (:activate, :submit, :revoke, …) and edits that are only allowed in some statuses check the resource’s current status inside the request. If another change got there first, you get the operation’s own 409, for example invalid-state-transition (the voucher set is no longer a draft, or was already activated), or voucher-set-archived. These 409s are final for that request: read the resource again and decide whether the command still makes sense. Retrying unchanged gives the same answer.
  • Change requests can go stale. When AllRide corrects a live voucher set while your change request for it is open, the request is based on an older version and shows isStale: true. AllRide cannot approve it (approval answers 409 change-request-stale on AllRide’s side) until you edit it: any PATCH of the request, even only providerNote, rebases it on the current content. See Change requests.
  • 409 concurrent-update means the request collided with another one on the same data and AllRide could not apply it after retrying internally. Nothing was written: retry it with backoff (with the same Idempotency-Key for a POST, see Idempotency).
  • If several people or systems edit the same resource, read it right before you change it, and agree who owns which fields.

Commands and batch operations

  • Actions that are not plain updates are commands: POST …/{id}:verb, for example :activate, :submit, :revoke. Most take an empty body.
  • Bulk operations use POST …:batch (or …/vouchers:revoke) and are all or nothing: one invalid item fails the whole request and nothing is written. Item errors are listed in more.validationErrors: property names the item (vouchers[17].value) and constraint the reason.
  • A command not allowed in the resource’s status → 409 invalid-state-transition.

Asynchronous jobs

Voucher uploads run asynchronously:
  1. The command answers 202 with Location (the job URL), Retry-After: 2 and the job in its initial status.
  2. Poll Location, starting after Retry-After and doubling the interval up to 30 seconds.
  3. The job’s status ends in a terminal value (completed, failed, cancelled), with failureReason on failure.
An idempotent replay of a 202 shows the job as it was when accepted; always follow Location for the current state. Uploads also send the voucher-upload-completed and voucher-upload-failed webhooks.

Compatibility rules

Within v1 AllRide adds, but never removes or changes. Your client must:
  • ignore unknown response properties, _links relations and error members;
  • treat enums as open sets and handle unknown values (for example a new status);
  • not depend on the order of properties or of list items beyond the documented sort.
See Versioning and deprecation.