Warming up the decks…
Warming up the decks…
BlendPartner APIblendapp.aiOne request returns the events you are allowed to sell, ready to render as a list.
Every partner has a catalog: the set of events Blend has switched on for them. This endpoint returns that catalog as a list of compact cards, twenty at a time, each with enough information to draw a tile in your app: a title, a cover image, the date, the venue, and the lowest ticket price. Nothing appears here that you have not been granted, and nothing appears that a customer could not actually buy today.
When a customer taps a card, fetch the full event with Event detail & tickets. To understand how the catalog itself is decided, see Which events you see.
Requires the catalog.read scope. Send both credentials on every call; the base URL is https://api.blendapp.ai/api/v1.
| Header | Type | Description |
|---|---|---|
| x-blend-key required | string | Your partner key, ck_live_…. |
| x-blend-secret required | string | Your partner secret, cs_live_…. Never ship this in a mobile app or browser bundle. |
All parameters are optional. With none, you get the first twenty upcoming events in catalog order.
| Query parameter | Type | Description |
|---|---|---|
| page | integer | Page number, starting at 1. Default 1. |
| limit | integer | Cards per page. Default 20, maximum 50. |
| search | string | Free text, up to 120 characters. Matches against the event title, location and venue. |
| city | string | Up to 80 characters. Restricts results to a city. |
| category | string | Up to 60 characters. An exact match on the event category, as returned in each card. |
| from | ISO date | Only events on or after this date, e.g. 2026-10-01. Filters on the event date. |
| to | ISO date | Only events on or before this date. Combine with from for a window. |
curl "https://api.blendapp.ai/api/v1/channel/events?page=1&limit=20" \
-H "x-blend-key: ck_live_xxxxxxxx" \
-H "x-blend-secret: cs_live_xxxxxxxx"A successful call returns 200 with the standard envelope. The cards live in data.events; paging information sits alongside in pagination. Values below are illustrative.
{
"success": true,
"code": null,
"message": null,
"data": {
"events": [
{
"id": "8fK3qLp",
"shortId": "8fK3qLp",
"slug": "beirut-jazz-night",
"title": "Beirut Jazz Night",
"coverImageUrl": "https://images.example.com/8fK3qLp/cover.jpg",
"startDate": "2026-10-03T00:00:00.000Z",
"endDate": "2026-10-03T00:00:00.000Z",
"startTime": "20:00",
"timezone": "Asia/Beirut",
"venue": "Music Hall, Beirut",
"category": "Music",
"currency": "USD",
"priceFrom": 25,
"soldOut": false
}
]
},
"pagination": {
"page": 1,
"limit": 20,
"total": 37,
"pages": 2
}
}Each entry in data.events has exactly these fields. The card is deliberately small: it is what you need to draw a list, not the full event, so the list stays fast even at fifty cards a page.
| Field | Type | Description |
|---|---|---|
| id | string | The identifier to use when fetching the event. This is the event’s short ID where one exists, otherwise its ObjectId. Either form is accepted by the detail endpoint. |
| shortId | string | The event’s short, URL-friendly identifier. |
| slug | string | The human-readable slug from the event’s public page. Also accepted by the detail endpoint. |
| title | string | The event title. |
| coverImageUrl | string | Absolute URL of the cover image. |
| startDate | string | The date the event starts. |
| endDate | string | The date the event ends. |
| startTime | string | The local start time, for display. |
| timezone | string | null | The event’s time zone. May be null when the organiser has not set one; treat the time as local to the venue in that case. |
| venue | string | The venue name. |
| category | string | The event category. Pass it back verbatim as the category filter. |
| currency | string | The currency every price for this event is quoted in. |
| priceFrom | number | The lowest effective price across the event’s enabled ticket types, in currency. Use it for “From $25” labels. |
| soldOut | boolean | true when no ticket type has stock left. Show the card, but do not offer a purchase. |
| Field | Type | Description |
|---|---|---|
| page | integer | The page you received. |
| limit | integer | The page size that was applied. |
| total | integer | Total events matching your filters across all pages. |
| pages | integer | Total number of pages at this limit. |
// Walk every page of the catalog. Stop when pagination.pages is reached.
async function fetchAllEvents() {
const headers = {
'x-blend-key': 'ck_live_xxxxxxxx',
'x-blend-secret': 'cs_live_xxxxxxxx',
};
const events = [];
let page = 1;
let pages = 1;
do {
const url = new URL('https://api.blendapp.ai/api/v1/channel/events');
url.searchParams.set('page', String(page));
url.searchParams.set('limit', '50');
const res = await fetch(url, { headers });
const body = await res.json();
events.push(...body.data.events);
pages = body.pagination.pages;
page += 1;
} while (page <= pages);
return events;
}Filters combine: a request with city, from and to returns only events in that city inside that date window. search is the only fuzzy parameter; category is an exact match, so use the value you were given in a card rather than a guess.
# Everything in Beirut during October, 50 per page
curl "https://api.blendapp.ai/api/v1/channel/events?city=Beirut&from=2026-10-01&to=2026-10-31&limit=50" \
-H "x-blend-key: ck_live_xxxxxxxx" \
-H "x-blend-secret: cs_live_xxxxxxxx"An event has to clear every one of these before it can appear in your list. There is no parameter to bypass any of them.
The “upcoming” rule is evaluated on every request from the start of the current day, so yesterday’s event disappears from the list without any change on Blend’s side. If you cache the list, expect it to shrink overnight.
A curated catalog is returned in the order Blend arranged it for you, which is what you should show. The sort is, in priority order:
The response does not carry a separate featured flag; the position in the list is the signal. If you re-sort client-side (by date, say), you lose the arrangement Blend made for you.
Every response carries two headers that you should leave alone.
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: private, no-store
Vary: x-blend-keyThe reason is simple: the list is yours. Two partners calling the same URL with different keys receive different catalogs. A CDN, a corporate proxy or a shared application cache that keyed on the URL alone would hand one partner’s catalog to another.
Cache-Control: private, no-store tells every shared cache between you and Blend not to store the body at all.Vary: x-blend-key tells any cache that does store it that the key is part of the identity of the response, so one partner’s copy can never satisfy another’s request.If you want to avoid calling Blend on every screen load, cache the parsed result inside your backend, keyed by your own partner identity, and refresh it on a short interval. Do not put a caching proxy between your servers and api.blendapp.ai and do not strip these headers.
This endpoint allows 600 requests per minute per key. A list of fifty cards is a single request, so a full crawl of even a large catalog is a handful of calls; a per-user poll on every app launch is not what the limit is for. See Rate limits for how a limit is signalled.