API Reference
The &Open API is a RESTful JSON API for the gifting platform. You create and retrieve gift requests, browse campaigns, and integrate gifting into your own workflows over HTTPS, using resource-based URLs, standard HTTP verbs, and conventional status codes.
Base URL and authentication
Send requests to the base URL for the region your account was provisioned in, and authenticate every request with a bearer token. See Environments for the regional base URLs and Authentication for how tokens work.
Every request must also carry the AndOpen-API-Version header. See
Versioning for the supported versions and what counts as a
breaking change.
Requests
Send JSON bodies with Content-Type: application/json. Request bodies are flat
top-level objects with snake_case keys — there is no envelope and no
resource-type wrapper.
curl -X POST "https://api.andopen.co/gift_requests" \
-H "Authorization: Bearer ao-v1-production-your_secret_here" \
-H "AndOpen-API-Version: 2026-05" \
-H "Content-Type: application/json" \
-d '{
"campaign_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"recipient": {
"first_name": "Alice",
"last_name": "Smith",
"email": "alice@example.com"
}
}'
Responses
A single resource is returned as a flat top-level JSON object — no envelope.
{
"id": "4fb4cb3f-9666-43b5-8884-7f5194483d1a",
"status": "submitted",
"campaign_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"redemption_url": "https://gift.andopen.co/r/abc123",
"recipient": {
"id": "b2c3d4e5-f6a7-8901-bcde-f01234567890",
"first_name": "Alice",
"last_name": "Smith",
"email": "alice@example.com"
},
"shipping_address": null,
"line_items": null,
"created_at": "2026-04-16T10:30:00.000Z",
"updated_at": "2026-04-16T10:30:00.000Z"
}
A collection is wrapped in a { data, has_more } envelope and nothing else — no
total count, no precomputed page links. Each item in data has the same shape as
the single-resource response.
{
"data": [
{
"id": "4fb4cb3f-9666-43b5-8884-7f5194483d1a",
"status": "submitted"
}
],
"has_more": true
}
Data types
The API represents common types consistently:
| Type | Notes |
|---|---|
| Keys | Always snake_case. |
| IDs | UUIDs with no prefix, such as 4fb4cb3f-9666-43b5-8884-7f5194483d1a. |
| Timestamps | ISO 8601 strings with millisecond precision in UTC, such as 2026-04-16T10:30:00.000Z. |
| Enumerated values | Lowercase snake_case strings from a fixed set — for example a status of "delivered". The allowed values are listed on each field. |
| Money | An object — { "amount": 2500, "currency": "EUR" } — where amount is an integer in the smallest unit of the currency (cents for EUR and USD, pence for GBP) and currency is an ISO 4217 code. 2500 with "currency": "EUR" is €25.00. |
| Country codes | ISO 3166-1 alpha-2, uppercase — IE, US, GB. |
| Phone numbers | Strings. Use E.164 (a leading + and country code) for a number outside the destination country. |
| Emails | Plain strings, validated as email addresses. |
| URLs | Absolute https URLs, as plain strings. |
| Booleans | true or false. |
| Absent values | A field with no value is still included in the response and returned as null, never omitted — including nullable arrays. The schema defines the full set of keys. |
Associations and references
A related resource appears in a response in one of three shapes. Which one you get depends on what you need to use the resource:
- Bare id — a
<resource>_idUUID, such asvariant_idon a line item. The related record is not included; fetch it from its own endpoint when you need it. - Embedded summary — a small object of identifying fields that always includes
id, such as{ "id": "…", "name": "…" }. You get a usable label inline, and theidlets you fetch the full resource when you need more than the label. - Embedded full — the complete sub-resource, in the same shape its own endpoint
returns. A gift request's
recipient,shipping_address, andline_itemsare embedded in full because you need them to make sense of the request.
Two things hold whatever the shape:
- An embedded association is serialised the same way everywhere — you see the identical shape whether you fetch the resource directly, list it, or receive it in a webhook.
- The same entity can take different shapes in different responses, each chosen for
what that response is for — a variant is a bare
variant_idon a line item but a full object in a campaign's catalogue.
When you send a resource that embeds a child — a recipient in a create request, say —
you supply it by value, without an id; the response echoes it back embedded, now
carrying its server-assigned id.
Pagination
List endpoints page with a forward cursor. Pass limit to set the page size and
after to continue from where the last page ended:
limit— how many records to return. Defaults to25; each endpoint sets its own maximum.after— theidof the last record from the previous page. Omit it on the first request.
Every collection response includes has_more. When it is true, take the id of
the last item in data and pass it as after to fetch the next page; when it is
false, you have reached the end.
curl "https://api.andopen.co/campaigns?limit=25&after=4fb4cb3f-9666-43b5-8884-7f5194483d1a" \
-H "Authorization: Bearer ao-v1-production-your_secret_here" \
-H "AndOpen-API-Version: 2026-05"
Errors
Errors are always returned as an array under errors, even when there is only one,
so you can handle one and many the same way. Each error carries a type, a code,
a human-readable message, and — for errors tied to a specific field — a param in
dot notation.
{
"errors": [
{
"type": "validation_error",
"code": "required",
"message": "is required",
"param": "recipient.email"
}
]
}
See Errors for the full type and code taxonomy and the HTTP
status each maps to.
Request IDs and rate limits
Every response includes a Request-Id header — a UUID identifying that request.
Include it when you contact support so we can find the exact request in our logs.
Responses also carry rate-limit headers: RateLimit-Limit (the ceiling for the
current window), RateLimit-Remaining (requests left), and RateLimit-Reset (the
absolute Unix time, in seconds, when the window resets). When you are rate-limited,
the response includes Retry-After — the number of seconds to wait before retrying.
Use Retry-After for scheduling retries; RateLimit-Reset is an absolute timestamp,
not a delay.
Forward compatibility
Within a version, adding a field, an endpoint, or an enum value is not a breaking
change. Write your integration to ignore fields it does not recognise and to
handle unknown enum and error-code values gracefully — typically by falling back
to the error type or message. Doing so means new fields and values never break
your code. See Versioning for the full list of what is and is not
a breaking change.
OpenAPI specification
The full 2026-05 contract is available as a downloadable OpenAPI 3.1 specification. Use it to generate a client, validate requests and responses, or give an AI agent the exact request and response shapes.
Related resources
New to &Open, or scoping whether to integrate? These guides cover the business and IT context behind the API:
- &Open integrations — what &Open integrates with, and why.
- What's possible with the API? — use cases and capabilities at a glance.
- IT team: what you need to know — security and setup context for IT reviewers.