Get a gift request
GET /gift_requests/{id}
Description
Retrieves a single gift request by its id. The response is a single JSON
object you get back from Create a gift request:
the gift request's own fields, with its owned associations (the recipient,
the shipping_address, the offering, and the line_items) returned inline
rather than as references you have to fetch separately. The campaign and the
sender come back as small summaries, enough to label the gift request and to
fetch the full record when you need more.
When to use
Reach for this endpoint to read a gift request back after you've created it,
to follow its status as the gift is redeemed and delivered, or to pick up the
redemption_url to pass on to the recipient. To stop a gift the recipient
hasn't redeemed yet, use Cancel a gift request.
To create a gift request in the first place, use Create a gift request. To discover which campaigns are available, browse Campaigns.
Parameters
Path
id (string · uuid · required) is the gift request to retrieve. An id that doesn't
match a gift request in your account returns 404.
Headers
AndOpen-API-Version (string · required) is the API version this request
targets. Always send 2026-05. Requests authenticate with a bearer token; see
Authentication for how to present it and
Environments for the regional base URL to send it to.
Worked examples
A read is a plain GET by id, with no request body. The JavaScript,
Python, and Ruby versions fetch the gift request and read a couple of fields
off it; swap in the id you're interested in.
- cURL
- JavaScript
- Python
- Ruby
curl -X GET https://api.andopen.co/gift_requests/4fb4cb3f-9666-43b5-8884-7f5194483d1a \
-H "Authorization: Bearer <api_key>" \
-H "AndOpen-API-Version: 2026-05"
const response = await fetch(
"https://api.andopen.co/gift_requests/4fb4cb3f-9666-43b5-8884-7f5194483d1a",
{
method: "GET",
headers: {
Authorization: "Bearer <api_key>",
"AndOpen-API-Version": "2026-05",
},
},
);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const giftRequest = await response.json();
console.log(giftRequest.status, giftRequest.redemption_url);
import requests
response = requests.get(
"https://api.andopen.co/gift_requests/4fb4cb3f-9666-43b5-8884-7f5194483d1a",
headers={
"Authorization": "Bearer <api_key>",
"AndOpen-API-Version": "2026-05",
},
)
response.raise_for_status()
gift_request = response.json()
print(gift_request["status"], gift_request["redemption_url"])
require "net/http"
require "json"
uri = URI("https://api.andopen.co/gift_requests/4fb4cb3f-9666-43b5-8884-7f5194483d1a")
request = Net::HTTP::Get.new(uri)
request["Authorization"] = "Bearer <api_key>"
request["AndOpen-API-Version"] = "2026-05"
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
http.request(request)
end
response.value # raises on a non-2xx response
gift_request = JSON.parse(response.body)
puts "#{gift_request['status']} #{gift_request['redemption_url']}"
Response shape
A successful call returns 200 OK with the gift request as a flat top-level
JSON object: the same shape Create a gift request returns.
| Field | Description |
|---|---|
reference (string · required) | A human-readable handle for the gift request, unique within your account and stable for its lifetime. Show it to your own users and quote it to support; the API itself takes the id. |
status (string · required) | The public-facing status, one of submitted, redeemed, dispatched, delivered, cancelled. A freshly-created request is submitted, or redeemed for a direct send; the others are reached as the gift is redeemed, dispatched, and delivered, or cancelled. This is the field you poll to follow. delivered is not terminal, as the per-field notes below explain. |
cancellable (boolean · required) | Whether Cancel a gift request would accept this gift request as it stands. true only while status is submitted. |
invitation_method (string · required) | How this send reaches the recipient, one of email_invitation, direct_message_invitation, sender_provided_address. Fixed when the gift request is created, from the request's own invitation_method or else the campaign's. |
campaign (object · required · nullable) | The campaign this request belongs to, embedded as an { id, name, web_url } summary. null for an ad-hoc send that belongs to no campaign. Fetch the rest of the campaign with Get a campaign. |
redemption_url (string · uri · required) | The link the recipient follows to redeem. Always set, from the moment the gift request is created. |
web_url (string · uri · required) | The gift request's page in the &Open web app, on your organization's own domain. This is the sender-facing view and needs a signed-in session, so show it to your own users rather than the recipient. |
recipient (object · required) | The recipient, returned inline. |
sender (object · required) | The user recorded as responsible for the send, embedded as an { id, name, email } summary. Read their team and budget with Get a user. |
shipping_address (object · required · nullable) | The shipping address, returned inline in direct-send mode and null in choice mode. |
offering (object · required) | What was put in front of the recipient: the items on offer, whether they receive all of them or choose one, and whether they see them at redemption. |
line_items (array · required · nullable) | The line items, returned inline once locked. |
email_message (object · required · nullable) | The personal message that went into the invitation email, or null when the send carries none. |
invitation_subject (string · required · nullable) | The invitation email's subject line, or null when the send carries no invitation email. |
notecard_message (string · required · nullable) | The note packed with a Marketplace physical gift, or null when the send carries none. |
lifecycle_events (object · required) | When each step of the gift request happened, from the invitation email to delivery. Every key is always present and stays null until its event occurs. |
{
"id": "4fb4cb3f-9666-43b5-8884-7f5194483d1a",
"reference": "ACME-M5RD6J8",
"status": "redeemed",
"cancellable": false,
"invitation_method": "email_invitation",
"campaign": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Q4 Customer Appreciation",
"web_url": "https://acme.andopen.co/sender/gift-history/campaigns/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
},
"redemption_url": "https://gift.andopen.co/r/abc123",
"web_url": "https://acme.andopen.co/sender/gift-history/4fb4cb3f-9666-43b5-8884-7f5194483d1a",
"recipient": {
"id": "b2c3d4e5-f6a7-8901-bcde-f01234567890",
"thank_you_count": 1,
"first_name": "Alice",
"last_name": "Smith",
"name": "Alice Smith",
"email": "alice@example.com"
},
"sender": {
"id": "9f8e7d6c-5b4a-3210-fedc-ba9876543210",
"name": "Dana Okafor",
"email": "dana@acme.example"
},
"shipping_address": null,
"offering": {
"selection_mode": "one",
"visible_at_redemption": true,
"line_items": [
{
"id": "f6a7b8c9-d0e1-2345-6789-0abcdef01234",
"sku": "NOTEBOOK-A5",
"variant_id": "a7b8c9d0-e1f2-3456-789a-bcdef0123456",
"name": "Leather Notebook",
"quantity": 1,
"images": [
{
"name": "leather-notebook.jpg",
"url": "https://files.andopen.co/rndd63mwgj94j2vf3v2ngnye0hkn",
"urls": {
"thumbnail": "https://files.andopen.co/vw2mvwevyqxh98l7esf67nvunr4h",
"large": "https://files.andopen.co/mz4rc8kx1nvq7j93wtf5bd2hs0yl",
"large_wide": "https://files.andopen.co/q7pz3n8htv2ke0d5rjw94flxs6cb"
}
}
]
}
]
},
"line_items": [
{
"id": "d4e5f6a7-b8c9-0123-4567-890abcdef012",
"sku": "HOODIE-L-BLK",
"variant_id": "c3d4e5f6-a7b8-9012-cdef-012345678901",
"name": "Hoodie: Large / Black",
"quantity": 1,
"images": [
{
"name": "hoodie-black.jpg",
"url": "https://files.andopen.co/8k2mfp4qz7x9v1c3b5n0jhtl",
"urls": {
"thumbnail": "https://files.andopen.co/p3wq7m2zx8k4n6v0bjhtldsf",
"large": "https://files.andopen.co/r9td5c1yfw3jq7n2vk8mzbxh",
"large_wide": "https://files.andopen.co/h4nj8sv2qd6kz0wt3mfy9lpc"
}
}
]
}
],
"email_message": {
"subject": "A small thank-you",
"body": "Thanks for being a great customer!"
},
"invitation_subject": "A small thank-you",
"notecard_message": null,
"lifecycle_events": {
"invitation_email_sent_at": "2026-04-16T10:31:00.000Z",
"invitation_first_opened_at": "2026-04-16T18:40:00.000Z",
"invitation_last_opened_at": "2026-04-17T08:12:00.000Z",
"reminder_sent_at": null,
"redeemed_at": "2026-04-18T14:05:00.000Z",
"dispatched_at": null,
"delivered_at": null
},
"created_at": "2026-04-16T10:30:00.000Z",
"updated_at": "2026-04-16T10:30:00.000Z"
}
Per-field notes
shipping_addressandline_itemscome backnulluntil they're set.shipping_addressisnulluntil an address is provided, andline_itemsuntil the items are locked or chosen.line_itemsisnull, never[], before items are locked. For direct-send the items lock at creation, soline_itemsis populated from the start. For choice mode they lock at redemption, so the field staysnulluntil the recipient chooses. Treatnullas "not yet locked", not "no items".deliveredcovers partial fulfillment, and it is not terminal. It means the gift reached the recipient, including a request whose remaining items failed or were cancelled, and the status can change again while a remaining item is retried. Don't treat it as the end of the lifecycle or stop polling on it.campaignandsenderare summaries, so they carry a label, anid, and little else. Use thenameto display the gift request, and theidto fetch the full campaign or user when you need more than the label. The campaign summary also carries its ownweb_url.offering.line_itemsandline_itemshold different sets, and never the same item twice. Before redemptionoffering.line_itemscarries what the recipient was shown andline_itemsisnull; after redemptionline_itemscarries what they chose andoffering.line_itemscarries what they left. Voucher, cause, and gift-set offerings are not represented yet and come backnull.recipient.thank_you_countcounts the thank-yous the recipient has sent for this gift, and starts at0.recipient.namejoins their first and last name, and staysnulluntil they supply at least one of the two.invitation_methoddecides who passes the link on. Withemail_invitation, &Open emails the recipient theirredemption_url. Withdirect_message_invitation, &Open sends nothing, so share the link yourself. Withsender_provided_address, the gift ships to the address you supplied and there's no invitation at all.invitation_subject, once the invitation email is sent, is the subject it went out with, and later edits don't change it. It can benullbriefly while the email is being delivered, and for invitations sent before &Open recorded subjects.invitation_subject, before the invitation email is sent, is the subject a send made now would carry: youremail_message.subject, else the campaign'sdefault_email_message.subject, else the subject set in the campaign's theme (or, with none, your organization's default theme), else &Open's standard subject line. It'snullwheninvitation_methodisn'temail_invitation.notecard_messageis the handwritten note the vendor packs with a Marketplace physical gift: thenotecard_messagesent on Create a gift request, or else the campaign's default note at the time of the send. It's sent verbatim, with no template substitution, and it's independent ofemail_message.lifecycle_eventsholds seven timestamps, eachnulluntil its event happens. Use them to answer questionsstatuscan't, such as whether the recipient has opened their link yet:invitation_email_sent_at: when the invitation email was sent. Staysnullfor a send with no invitation email.invitation_first_opened_at: the recipient's first load ofredemption_url. Set once and never moves.invitation_last_opened_at: their most recent load. It moves forward on each open, so it equalsinvitation_first_opened_atafter a single open.reminder_sent_at: when &Open sent the reminder to redeem. A gift request gets at most one.redeemed_at: when the recipient committed their choice, or, for a send whose address you supplied, the first fulfillment step.dispatched_at: when the carrier dispatched the gift. Staysnullfor a gift that reaches the recipient without a carrier dispatch.delivered_at: when the gift reached the recipient.
Error cases
Every failure uses the shared error model: a top-level errors array of
objects carrying type, code, message, and (for field-level problems)
param. See Errors for the full type/code taxonomy and how
to handle each category; the codes below are the ones this endpoint produces.
| Status | Meaning |
|---|---|
| 400 | The request is malformed or violates a precondition. Typical triggers are a missing or unsupported `AndOpen-API-Version` header, a request body that is not valid JSON, or pagination parameters that fail server-side validation (`limit` non-numeric or non-positive, `after` referencing a record that does not exist). |
| 401 | Authentication failed: missing or invalid bearer token. |
| 403 | Authorized but not permitted to access this resource. |
| 404 | The requested resource does not exist. |
| 429 | Too many requests. Rate limit exceeded. |
| 500 | Internal server error. |
| 503 | Service unavailable. The account may be under maintenance. Check the `Retry-After` header. |
Every error carries a type, one of: validation_error, authentication_error, authorization_error, not_found_error, rate_limit_error, api_error.
A read takes no body, so there's nothing to validate. The failure you'll handle most is a missing resource:
404 not_found: no gift request with thatid.401 authentication_error: the token is missing, unrecognized, or expired (unauthorized). A token is only valid in the region it was issued for, so one presented to the wrong region fails the same way.403 authorization_error: the token authenticated but isn't allowed to read this resource (forbidden,insufficient_scope).400 api_error:unsupported_api_versionwhen theAndOpen-API-Versionheader is missing or unsupported (returned before authentication).429 rate_limit_error: you've exceeded the rate limit; back off using theRetry-Afterheader.500/503 api_error: a fault on our side; rare, and safe to retry after a short delay (honorRetry-Afteron a503).