Offer Wall
An Offer Wall is a Developer Portal placement type (offerwall) that shows a
scrollable list of offers your users can browse and open. Create an Offer
Wall placement in your application's Placements page in the
Developer Portal.
The placement id (plc_…) is the only identity the wall needs — you do not
send an API key.
There are two ways to show the wall:
| Option | Use it when | What you build |
|---|---|---|
| Hosted page | You want a wall live with no code, or your app can open a web view. | Nothing: open the AON-hosted link in a web view or browser. |
| API | You want the wall rendered in your own native or web UI, with your own layout and styling. | A list screen that calls Offer Query with your placement id and pages through the results. |
Both options use the same placement, the same offers, and the same sub_id
attribution, so you can start with the hosted page and move to the API later.
Hosted page (no code)
Every Offer Wall placement has a hosted page. Replace the placement id with
yours and {USER_ID} with your own identifier for the user:
https://offerwall.aon.pro/plc_7c2e0dR9kL4mN8pQ?sub_id={USER_ID}- Open the link in an in-app web view (or the system browser) from wherever your users should find the wall.
- The page shows the wall's current offers and handles the paused and empty states for you.
- It takes the same attribution slots as the API:
sub_idplus optionalsub_id_2…sub_id_5.
On an Offer Wall placement, the Developer Portal shows this link with copy, QR code, and open actions. The placement's Integration & test dialog also has a Copy for LLM button that copies an integration brief for this exact placement, ready to paste into a coding assistant.
API
Call Offer Query with your placement id in the
X-AON-Placement-Id header (or as the top-level body field placement_id).
No Authorization header is needed — the placement is the identity, and a key
sent alongside it is ignored for identity.
curl --request POST \
"https://api.aon.pro/v1/offers/query" \
--header "Content-Type: application/json" \
--header "AON-Protocol-Version: 1.0" \
--header "X-AON-Placement-Id: plc_7c2e0dR9kL4mN8pQ" \
--data '{
"context": {},
"pagination": { "limit": 20, "offset": 0 }
}'| Header | Value |
|---|---|
Content-Type | application/json |
AON-Protocol-Version | 1.0 |
X-AON-Placement-Id | Your Offer Wall placement id, plc_… |
The request body differs from other placement types in two ways, for Offer Wall placements only:
intentmay be omitted. The server supplies a neutral one, because the wall is browsed rather than asked.pagination({ "limit": 20, "offset": 0 }) is accepted under Protocol v1.0. Top-levellimitandoffsetare accepted too.limitis 1–20 and defaults to 3 when omitted, so always send it.
Other placement types are unchanged: under v1.0 they still require intent
and reject pagination.
Response
The response uses the standard envelope (code, message, data, extra).
Offers are in data.offers in the v1.0 Offer shape, and Offer Wall placements
also return paging state in extra.pagination:
{
"code": "SUCCESS",
"message": "",
"data": {
"request_id": "0195ef94-f17d-7a4f-b6e0-2c52bb49e13f",
"protocol_version": "1.0",
"language": "en",
"offers": [
{
"offer_id": "019fc211-c6cd-7e62-9c4d-699c243e6c96",
"offer_instance_id": "019fc211-c695-7bd2-9e1b-9a06c2952770",
"offer_info": {
"title": "TeamFlow Pro Plan",
"short_description": "Docs, wikis, and planning in one workspace.",
"description": "Collaborative workspace for docs, wikis, and project planning."
},
"entity": {
"id": "ent_teamflow",
"name": "TeamFlow",
"logo": "https://cdn.teamflow.example/logo.png"
},
"material": [
{
"url": "https://cdn.teamflow.example/cover-1200x628.png",
"format": "image"
}
],
"claims": [
{
"kind": "user_benefit",
"text": "14-day free trial"
}
],
"action": {
"type": "open_url",
"name": "Start free trial",
"payload": {
"url": "https://aon.link/oyMJZTta"
}
}
}
]
},
"extra": {
"pagination": {
"limit": 20,
"offset": 0,
"returned": 20,
"total": 37,
"has_more": true,
"next_offset": 20
}
}
}extra.pagination field | Meaning |
|---|---|
limit, offset | The page you asked for |
returned | Offers in this page |
total | Offers this wall can serve right now. For walls that draw on the AON network, it can change between pages. |
has_more | Whether another page is available |
next_offset | The offset to send for the next page |
Paging
Request the first page with offset: 0. While extra.pagination.has_more is
true, request the next page with offset set to
extra.pagination.next_offset — for example, when the user scrolls near the
end of the list. Stop when has_more is false. Drive paging from has_more
and next_offset rather than from total, since total can change between
pages.
Render each offer
| Show | Field |
|---|---|
| Title | offer_info.title |
| Description | offer_info.short_description, falling back to offer_info.description |
| Brand name and logo | entity.name, entity.logo |
| Cover image | The first material[] item with format "image", falling back to entity.logo |
| Badge | claims[].text |
| Tap target | action.payload.url — the tracked click link to open when the user taps the offer |
Attribution with sub_id
Append your own attribution values to action.payload.url as query parameters
before opening it: sub_id, plus optional sub_id_2 … sub_id_5. Conversions
come back on your conversion Webhook with the same sub_id
values, so you can credit the right user.
Do not cache or rewrite click links beyond appending sub_id parameters.
Open action.payload.url as returned so the click is recorded — see
Tracking.
Conversion Webhooks are always delivered on Protocol v1.0, with
AON-Protocol-Version: 1.0.
Checklist
- Offer Wall placement created in Developer Portal.
- Webhook endpoint configured to receive conversions.
Hosted page:
- Hosted link opened in a web view, with
sub_idset to your user id.
API:
- Offer Query sent with
X-AON-Placement-Id,AON-Protocol-Version: 1.0, andpagination.limitset explicitly. - Next pages fetched with
extra.pagination.next_offsetwhileextra.pagination.has_moreistrue. sub_idappended toaction.payload.urlbefore opening it.