# Offer Instance API

Source: https://docs.aon.pro/api/offer-instances

> Derived from the same AON Docs release as the source page.

API Reference · Details

Look up as many as 100 Offer cards your application has already served, by offer\_instance\_id, using a Live API Key from your server. Get when each card was served, its placement, the Offer's current details and status, and the original tracked link while it can still be opened.

## Operations

**POST** `/v1/offers/instances`

Look up served Offer cards by offer\_instance\_id

Authentication: Bearer required. Source: Curated overlay.

### Request

Headers

#### `Authorization`

Type: string. Requirement: required.

Bearer followed by your application-owned Live API Key, sent from your server. Test Keys are not supported.

-   example: Bearer <LIVE\_API\_KEY>

#### `Content-Type`

Type: string. Requirement: required.

The request body is JSON.

-   example: application/json

Request Body

JSON payload. Unknown fields are rejected.

#### `offer_instance_ids`

Type: array. Requirement: required.

1 to 100 offer\_instance\_id UUIDs returned by Query. Duplicates are de-duplicated, keeping the first occurrence.

-   example: \["019dd208-27d2-7673-b16f-6897fa120304", "019dd208-27d2-7673-b16f-6897fa120305"\]
-   items: string

Request Examples

#### Look up three served cards

```bash
curl -X POST 'https://api.aon.pro/v1/offers/instances' \
  --header 'Authorization: Bearer <LIVE_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{"offer_instance_ids":["019dd208-27d2-7673-b16f-6897fa120304","019dd208-27d2-7673-b16f-6897fa120305","019dd208-27d2-7673-b16f-6897fa120399"]}'
```

### Response

HTTP 200 uses {code, message, data, extra}; data.instances holds one item per de-duplicated requested ID, in request order. found items carry served\_at, placement\_id and offer; not\_found items carry only offer\_instance\_id and status.

#### `code`

Type: string. Requirement: required.

SUCCESS on HTTP 200; otherwise the error code.

-   example: SUCCESS

#### `message`

Type: string. Requirement: required.

Empty on success; a readable explanation on failure.

#### `data`

Type: object. Requirement: required.

Contains instances on success; an empty object on failure.

#### `data.instances`

Type: array. Requirement: required.

Exactly one item per de-duplicated requested ID, in request order.

#### `data.instances[].offer_instance_id`

Type: string. Requirement: required.

The requested offer\_instance\_id, in canonical lowercase UUID form.

-   format: uuid

#### `data.instances[].status`

Type: string. Requirement: required.

found when the card was served to your application; otherwise not\_found, which contains only offer\_instance\_id and status.

Allowed values: `found`, `not_found`

#### `data.instances[].served_at`

Type: string. Requirement: required when status is found.

When the card was served, as RFC 3339 UTC with second precision.

-   format: date-time

#### `data.instances[].placement_id`

Type: string. Requirement: required when status is found.

The placement the instance was served through; null when the serve record itself carries no placement (legacy or static Offer Wall serves). A Query sent without a placement\_id is served anonymously and returns not\_found for your key, not a null placement\_id.

-   nullable: true

#### `data.instances[].offer`

Type: object. Requirement: required when status is found.

The Offer's current details and status, in the OfferInfo API shape, plus the echoed offer\_instance\_id. Contains only offer\_id, offer\_instance\_id and offer\_info.status when no details are available, including real-time remote Partner Offers.

#### `data.instances[].offer.offer_id`

Type: string. Requirement: required.

The canonical Offer ID of the served card.

-   format: uuid

#### `data.instances[].offer.offer_instance_id`

Type: string. Requirement: required.

Echo of the requested offer\_instance\_id, so the object can be rendered like a Query result.

-   format: uuid

#### `data.instances[].offer.offer_info`

Type: object. Requirement: required.

Query public Offer information when details are returned; otherwise only status.

#### `data.instances[].offer.offer_info.status`

Type: string. Requirement: required.

Current AgentOffer Protocol lifecycle status, identical to OfferInfo for the same offer\_id. Only active is servable; real-time remote Partner Offers report expired.

Allowed values: `active`, `paused`, `pending`, `rejected`, `expired`

#### `data.instances[].offer.version`

Type: string. Requirement: required when details are returned.

Offer document version, not the HTTP route version.

Allowed values: `3.0`

#### `data.instances[].offer.entity`

Type: object. Requirement: required when details are returned.

Public entity information using Query's entity mapping.

#### `data.instances[].offer.goals`

Type: array. Requirement: required when details are returned.

Public goals using Query's CPA/CPS pricing semantics.

#### `data.instances[].offer.action`

Type: object. Requirement: optional.

The original tracked link from Query, returned only while it can be opened right now (active Offer, placement still active and yours, tracked short link, served target an absolute http or https URL). Omitted otherwise, never null; omitted when the served target is not an http(s) URL, such as a custom-scheme app deep link.

#### `data.instances[].offer.action.type`

Type: string. Requirement: required.

Technical form of the action destination.

-   example: open\_url

#### `data.instances[].offer.action.payload`

Type: object. Requirement: required.

Action parameters.

#### `data.instances[].offer.action.payload.url`

Type: string. Requirement: required.

The tracked aon.link short link served with the card. Open it unchanged; you may append sub\_id attribution parameters.

-   format: uri

#### `data.instances[].offer.content_language`

Type: string. Requirement: optional.

Actual known language of the selected content; omitted when unknown.

#### `data.instances[].offer.material`

Type: array. Requirement: optional.

Available public creative assets using Query's material validation and limits.

#### `extra`

Type: object. Requirement: required.

Empty object for this route.

Response Examples

#### Success: a linkable card, a status-only card and an unknown instance

```json
{
  "code": "SUCCESS",
  "message": "",
  "data": {
    "instances": [
      {
        "offer_instance_id": "019dd208-27d2-7673-b16f-6897fa120304",
        "status": "found",
        "served_at": "2026-10-14T06:12:39Z",
        "placement_id": "plc_JCTbkjs19Omqe0C2",
        "offer": {
          "offer_id": "019dd208-27d2-7673-b16f-6897fa120303",
          "offer_instance_id": "019dd208-27d2-7673-b16f-6897fa120304",
          "version": "3.0",
          "content_language": "en",
          "offer_info": {
            "title": "Example offer",
            "status": "active",
            "category": {
              "id": "others"
            },
            "description": "Example offer details"
          },
          "entity": {
            "id": "example-merchant",
            "name": "Example Merchant",
            "type": "merchant"
          },
          "material": [
            {
              "format": "image",
              "url": "https://cdn.example.com/offer-banner.png",
              "tag": "banner"
            }
          ],
          "goals": [
            {
              "event": "purchase",
              "pricing": {
                "model": "cpa",
                "amount": "1.00",
                "currency": "USD"
              }
            }
          ],
          "action": {
            "type": "open_url",
            "payload": {
              "url": "https://aon.link/Ab3xY9"
            }
          }
        }
      },
      {
        "offer_instance_id": "019dd208-27d2-7673-b16f-6897fa120305",
        "status": "found",
        "served_at": "2026-10-13T02:00:00Z",
        "placement_id": null,
        "offer": {
          "offer_id": "019dd208-27d2-7673-b16f-6897fa120306",
          "offer_instance_id": "019dd208-27d2-7673-b16f-6897fa120305",
          "offer_info": {
            "status": "expired"
          }
        }
      },
      {
        "offer_instance_id": "019dd208-27d2-7673-b16f-6897fa120399",
        "status": "not_found"
      }
    ]
  },
  "extra": {}
}
```

### Errors

Errors and failure modes

#### BAD\_REQUEST: HTTP 400

The body is not JSON, offer\_instance\_ids is missing or empty, contains more than 100 IDs or a value that is not a UUID, or the body has unknown fields.

##### Recommended handling

-   Correct the request body before retrying. Split larger lookups into batches of at most 100 IDs.

#### UNAUTHORIZED: HTTP 401

Missing, invalid or revoked API Key, or an ordinary aon\_test\_ Test Key.

##### Recommended handling

-   Use a valid application-owned Live API Key.

#### ENV\_MISMATCH: HTTP 401

A Live API Key was sent together with the X-AON-Test: true header.

##### Recommended handling

-   Remove the X-AON-Test header when calling with a Live API Key.

#### APPLICATION\_NOT\_SERVING: HTTP 403

The application cannot currently serve requests.

##### Recommended handling

-   Restore the application state before retrying.

#### DEVELOPER\_SUSPENDED: HTTP 403

The developer account is suspended.

##### Recommended handling

-   Restore the account state before retrying.

#### PUBLIC\_TEST\_SCOPE\_DENIED: HTTP 403

The shared Public Test Sandbox Key is restricted to its Query route and cannot look up instances.

##### Recommended handling

-   Use your application's Live API Key.

#### 405: HTTP 405

The route only accepts POST. GET and other methods are rejected.

##### Recommended handling

-   Send the lookup as POST with a JSON body.

#### OFFER\_INSTANCE\_UNAVAILABLE: HTTP 503

Served cards or Offer details are temporarily unreadable. No partial success is returned.

##### Recommended handling

-   Retry later.

#### HTTP 400: invalid offer\_instance\_ids

```json
{
  "code": "BAD_REQUEST",
  "message": "offer_instance_ids must contain between 1 and 100 Offer instance IDs",
  "data": {},
  "extra": {}
}
```

### Behavior, compatibility, and source notes

Look up as many as 100 Offer cards your application has already served, by the offer\_instance\_id returned with each Query result, using an application-owned Live API Key. Each found card returns when it was served, its placement, the Offer's current details and status, and the original tracked link only while that link can still be opened.

-   Use this when an Offer detail page is opened outside the Query response that produced the card, for example from a deep link, a bookmark, a share or a reload. Look the card up by its offer\_instance\_id instead of re-running Query, and never replace action with the Offer's landing page: that link carries no attribution.
-   Send Authorization: Bearer <LIVE\_API\_KEY> from your server only. Never call this route from a browser or mobile client, because that exposes your Live API Key. Live and Live Limited applications can call this route; paused or suspended applications cannot. Offer Query and MCP search continue to use placement identity.
-   Send Content-Type: application/json with a body of {"offer\_instance\_ids": \[...\]}: 1 to 100 offer\_instance\_id UUIDs returned by Query. Duplicate IDs are de-duplicated, keeping the first occurrence. Unknown body fields are rejected. Send offer\_instance\_id values only: a canonical Offer ID returns not\_found and an aonlink is rejected as not a UUID. Use the OfferInfo API to read by Offer ID.
-   data.instances contains exactly one item per de-duplicated requested ID, in request order. Each item is either found or not\_found; there is no 404 or partial-failure response.
-   An instance belongs to the application whose identity served it. not\_found means the ID is unknown, was served to another application, was served by a test or sandbox request, or is a legacy record without a resolvable Offer. A not\_found item contains only offer\_instance\_id and status.
-   An instance belongs to the application of the identity that served it. Where anonymous mode is available, a Query sent without a placement\_id is served anonymously through the AON default placement, so its instances belong to the AON default application and return not\_found for your key; where it is not available, such a Query is rejected with 401. Always send your placement\_id on Query if you need to look cards up later.
-   A found item returns served\_at (when the card was served, UTC, second precision), placement\_id (the placement the instance was served through, or null when the serve record itself carries no placement, such as legacy or static Offer Wall serves) and offer. offer always echoes offer\_id and offer\_instance\_id.
-   offer uses the OfferInfo API projection of the Offer's current stored details and offer\_info.status, so the status of a found card always matches what OfferInfo returns for the same offer\_id. Treat any status other than active as not servable. When the Offer has no stored details, offer contains only offer\_id, offer\_instance\_id and offer\_info.status.
-   Real-time remote Partner Offers are not stored in the AON catalog. Their cards are found, but report offer\_info.status expired, the same as OfferInfo, and include no details and no action.
-   action is the original tracked link from the Query response and is returned only while that link can be opened right now: the Offer is active, the card's placement is still active and belongs to your application (or the card was served without a placement), the card has a tracked short link, and the target frozen at serve time is an absolute http or https URL. Otherwise action is omitted; it is never null or a replacement link. Offers whose served target is not an http(s) URL, such as a custom-scheme app deep link, do not return action; a deep-link Offer whose target is an https universal link can.
-   Clicks on a returned action are attributed to the original card. This route is read-only: it creates no offer instance, impression, click or link, does not call Partners, and consumes no serving quota. There is no application-level rate limit.

### Implementation checklist · 5 items

-   Create a Live API Key in Developer Portal under your application's API & Webhooks → API Keys, and call this route from your server only. The application must be Live or Live Limited.
-   Always send your placement\_id on Query. Where anonymous mode is available, a Query without one is served anonymously under the AON default application and its instances return not\_found to your key; otherwise it is rejected with 401.
-   POST a JSON body with offer\_instance\_ids: 1 to 100 offer\_instance\_id UUIDs returned by Query. Duplicates are de-duplicated.
-   Render found items like a Query result. Show action only when it is returned, and never replace it with the Offer's landing page.
-   Treat offer\_info.status other than active as not servable. Real-time remote Partner Offers report expired with no details or action.

## Related links

[

OfferInfo API

Read current details and status by canonical Offer ID when you have no offer\_instance\_id.

](https://docs.aon.pro/api/offer-info)[

Offer Query

Send your placement\_id on Query so the cards it serves can be looked up later.

](https://docs.aon.pro/api/offer-query)[

Errors & Rate Limits

Shared HTTP status, body envelope, and retry guidance.

](https://docs.aon.pro/api/errors-rate-limits)
