Download OpenAPI specification:
What an AI company's systems call to find, fetch and render what businesses published.
The read path. Every request is signed with RFC 9421 by a
retrieval key the AI company registered in the AI Portal (tag="mdb-retrieval");
identity comes only from the key. Every search and fetch returns a receipt: MasterDB's
signed statement of what it served, to whom and when.
The sandbox alone also accepts Authorization: Bearer <sandbox_bearer_token> in place of
a signature, for one hour after a key is registered (the token comes back once, with the
registration), so a developer can see a response before writing a signer.
Production never accepts a bearer token.
There is no list endpoint, no "all records for a business", no batch fetch and no
export: a fetch takes one id. A search returns at most 50 rows and has no
second page; if the answer is not in the 50, refine the criteria and search
again. Billing counts a search that returns at least one row and a fetch that returns
a record; refusals and failures are never billed. A prepay company whose
allowance is spent is answered 402 allowance_exhausted — and 503
unavailable with Retry-After in the moment the allowance cannot be checked (the stop
fails closed; never billed); a key over its
request rate or its per-minute query-cost budget 429 rate_limited with
Retry-After. Rows and records from a business that blocked your group are
absent, and nothing anywhere says so.
A request body is at most 16 KiB (64 KiB on the ads routes). A larger one, declared in
Content-Length or sent chunked without it, is answered 413 record_too_large and is
not read past the limit; until 5 October 2026 a declared length over the limit answered
400 request_invalid.
Errors are RFC 9457 problem details with a stable code on every response. The version is in the path; changes within v1 are additive only.
Finds candidates in one collection — products, business_files, events, jobs
or updates — with the caller's own text query, structured filter and sort. The
filter must name exactly one country and the sort is mandatory:
MasterDB never chooses an order, so a caller that wants relevance order writes
_text_match:desc. Only the fields, operators and sort keys of the collection's
allow-list exist; anything else is refused with a reason, never rewritten silently.
The answer is at most 50 short rows, each with its adl_* fields and the business's AI
policy in force (ai_policy_bits: what it permits, and the blocked contexts bc1–bc10 —
the key is GET /v1/ai-policy-key), and a signed receipt. Rows from businesses that blocked
your group are simply absent; nothing says so.
| MDB-Sandbox-Key | string [ 1 .. 8192 ] characters Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl Sandbox only. The |
| collection required | any Required on Value: "products" |
| q | string [ 1 .. 512 ] characters The text query; |
| query_by | Array of any [ 1 .. 4 ] items unique Items Enum: "product_name" "short_description" "tags" "brand" The text fields |
required | object (ProductsFilter) The structured filter for |
| sort_by required | string (ProductsSortBy) ^(?:_text_match|price_amount|published_at):(?... Mandatory: MasterDB never supplies an order. |
| limit | integer [ 1 .. 50 ] At most 50 rows; default 50. There is no second page. |
| client_query_id | string^[\x21-\x7e]{1,128}$ The caller's own reference, echoed in the event stream. |
| session_ref | string^[\x21-\x7e]{1,128}$ Optional: your opaque label for the conversation, new for every conversation and never identifying a person. HMACed with a daily salt on arrival, used only for repeat limits and fraud patterns, never shown to a business. |
| topic_keywords | Array of strings [ 1 .. 10 ] items unique [ items [ 1 .. 64 ] characters ] Optional: subject terms of the search ("vegan restaurant", "late opening"), stored — screened for anything that looks personal — as demand insight for businesses. The free text |
{- "collection": "products",
- "q": "trail running shoes",
- "query_by": [
- "product_name",
- "tags"
], - "filter": {
- "all": [
- {
- "country": "US"
}, - {
- "price_amount": {
- "lte": 150
}
}, - {
- "availability": "available"
}
]
}, - "sort_by": "price_amount:asc",
- "limit": 25,
- "client_query_id": "q-2026-10-01-0001",
- "session_ref": "9f1c2e7a-conv",
- "topic_keywords": [
- "trail running"
]
}{- "retrieval_id": "r_01J8XK2Q7R",
- "collection": "products",
- "country": "US",
- "rows": [
- {
- "record_id": "mdb_dq5jnqatnemnqj4g3xmgzgpoik",
- "business_uuid": "0b7d6c3e-2f4a-4c1b-9d8e-7f6a5b4c3d2e",
- "type": "products",
- "published_at": 1790669700,
- "product_name": "Ridge Trail Runner",
- "price_US": 129,
- "price_currency_US": "USD",
- "price_IE": 119,
- "price_currency_IE": "EUR",
- "adl_origin": "sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
- "adl_origin_cert": "cert_0b7d6c3e_3",
- "adl_proj": "products/3",
- "adl_row_sig": "3q2+7w==",
- "adl_key_id": "arnx6499M4j0-dWG9m6Z_VQIDfLERvDlhmiwnAihbdA",
- "ai_policy_version": 4,
- "ai_policy_bits": {
- "ai_policy_version": 4,
- "ai_policy_schema": 2,
- "use": 79,
- "action": 51,
- "blocked": 130
}
}
], - "receipt": {
- "payloadType": "application/vnd.masterdb.receipt.v3+json",
- "payload": "eyJyZXRyaWV2YWxfaWQiOiJyXzAxSjhYIn0=",
- "signatures": [
- {
- "keyid": "AV9-a8Wur0g3JAieklLME7UJUaa2lBJSJ2XP9NeAMG4",
- "sig": "3q2+7w=="
}
]
}
}The typed address for POST /v1/search with collection: products, routed inside the
same service with no redirect and no added latency. It exists so this page
shows only the products fields, filters and sort keys. price_amount and
price_currency apply to the one country the filter names.
| MDB-Sandbox-Key | string [ 1 .. 8192 ] characters Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl Sandbox only. The |
| collection | any Required on Value: "products" |
| q | string [ 1 .. 512 ] characters The text query; |
| query_by | Array of any [ 1 .. 4 ] items unique Items Enum: "product_name" "short_description" "tags" "brand" The text fields |
required | object (ProductsFilter) The structured filter for |
| sort_by required | string (ProductsSortBy) ^(?:_text_match|price_amount|published_at):(?... Mandatory: MasterDB never supplies an order. |
| limit | integer [ 1 .. 50 ] At most 50 rows; default 50. There is no second page. |
| client_query_id | string^[\x21-\x7e]{1,128}$ The caller's own reference, echoed in the event stream. |
| session_ref | string^[\x21-\x7e]{1,128}$ Optional: your opaque label for the conversation, new for every conversation and never identifying a person. HMACed with a daily salt on arrival, used only for repeat limits and fraud patterns, never shown to a business. |
| topic_keywords | Array of strings [ 1 .. 10 ] items unique [ items [ 1 .. 64 ] characters ] Optional: subject terms of the search ("vegan restaurant", "late opening"), stored — screened for anything that looks personal — as demand insight for businesses. The free text |
{- "q": "trail running shoes",
- "filter": {
- "all": [
- {
- "country": "US"
}, - {
- "price_amount": {
- "lte": "150.00"
}
}, - {
- "on_sale": true
}
]
}, - "sort_by": "_text_match:desc,price_amount:asc",
- "limit": 10
}{- "retrieval_id": "r_01J8XK2Q7R",
- "collection": "products",
- "country": "US",
- "rows": [
- {
- "record_id": "mdb_dq5jnqatnemnqj4g3xmgzgpoik",
- "business_uuid": "0b7d6c3e-2f4a-4c1b-9d8e-7f6a5b4c3d2e",
- "type": "products",
- "published_at": 1790669700,
- "product_name": "Ridge Trail Runner",
- "price_US": 129,
- "price_currency_US": "USD",
- "price_IE": 119,
- "price_currency_IE": "EUR",
- "adl_origin": "sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
- "adl_origin_cert": "cert_0b7d6c3e_3",
- "adl_proj": "products/3",
- "adl_row_sig": "3q2+7w==",
- "adl_key_id": "arnx6499M4j0-dWG9m6Z_VQIDfLERvDlhmiwnAihbdA",
- "ai_policy_version": 4,
- "ai_policy_bits": {
- "ai_policy_version": 4,
- "ai_policy_schema": 2,
- "use": 79,
- "action": 51,
- "blocked": 130
}
}
], - "receipt": {
- "payloadType": "application/vnd.masterdb.receipt.v3+json",
- "payload": "eyJyZXRyaWV2YWxfaWQiOiJyXzAxSjhYIn0=",
- "signatures": [
- {
- "keyid": "AV9-a8Wur0g3JAieklLME7UJUaa2lBJSJ2XP9NeAMG4",
- "sig": "3q2+7w=="
}
]
}
}The typed address for POST /v1/search with collection: business_files: a business's
Business & Brand Identity file for a set of countries — what it is, what it sells,
where it has locations, how it delivers and takes payment. The five "represent us"
texts are never on a search row; they come with a fetch.
| MDB-Sandbox-Key | string [ 1 .. 8192 ] characters Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl Sandbox only. The |
| collection | any Required on Value: "business_files" |
| q | string [ 1 .. 512 ] characters The text query; |
| query_by | Array of any [ 1 .. 4 ] items unique Items Enum: "description" "brands_owned.name" "brands_sold.name" "markets_served" The text fields |
required | object (BusinessFilesFilter) The structured filter for |
| sort_by required | string (BusinessFilesSortBy) ^(?:_text_match|year_established|published_at... Mandatory: MasterDB never supplies an order. |
| limit | integer [ 1 .. 50 ] At most 50 rows; default 50. There is no second page. |
| client_query_id | string^[\x21-\x7e]{1,128}$ The caller's own reference, echoed in the event stream. |
| session_ref | string^[\x21-\x7e]{1,128}$ Optional: your opaque label for the conversation, new for every conversation and never identifying a person. HMACed with a daily salt on arrival, used only for repeat limits and fraud patterns, never shown to a business. |
| topic_keywords | Array of strings [ 1 .. 10 ] items unique [ items [ 1 .. 64 ] characters ] Optional: subject terms of the search ("vegan restaurant", "late opening"), stored — screened for anything that looks personal — as demand insight for businesses. The free text |
{- "q": "independent bookshop",
- "filter": {
- "all": [
- {
- "country": "IE"
}, - {
- "has_locations": true
}, - {
- "location_geo": {
- "near": {
- "lat": 53.3438,
- "lng": -6.2546,
- "radius_km": 5
}
}
}
]
}, - "sort_by": "_text_match:desc"
}{- "retrieval_id": "r_01J8XK2Q7R",
- "collection": "products",
- "country": "US",
- "rows": [
- {
- "record_id": "mdb_dq5jnqatnemnqj4g3xmgzgpoik",
- "business_uuid": "0b7d6c3e-2f4a-4c1b-9d8e-7f6a5b4c3d2e",
- "type": "products",
- "published_at": 1790669700,
- "product_name": "Ridge Trail Runner",
- "price_US": 129,
- "price_currency_US": "USD",
- "price_IE": 119,
- "price_currency_IE": "EUR",
- "adl_origin": "sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
- "adl_origin_cert": "cert_0b7d6c3e_3",
- "adl_proj": "products/3",
- "adl_row_sig": "3q2+7w==",
- "adl_key_id": "arnx6499M4j0-dWG9m6Z_VQIDfLERvDlhmiwnAihbdA",
- "ai_policy_version": 4,
- "ai_policy_bits": {
- "ai_policy_version": 4,
- "ai_policy_schema": 2,
- "use": 79,
- "action": 51,
- "blocked": 130
}
}
], - "receipt": {
- "payloadType": "application/vnd.masterdb.receipt.v3+json",
- "payload": "eyJyZXRyaWV2YWxfaWQiOiJyXzAxSjhYIn0=",
- "signatures": [
- {
- "keyid": "AV9-a8Wur0g3JAieklLME7UJUaa2lBJSJ2XP9NeAMG4",
- "sig": "3q2+7w=="
}
]
}
}The typed address for POST /v1/search with collection: events: things a business
is running, in person or online, with their dates, place and price range.
| MDB-Sandbox-Key | string [ 1 .. 8192 ] characters Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl Sandbox only. The |
| collection | any Required on Value: "events" |
| q | string [ 1 .. 512 ] characters The text query; |
| query_by | Array of any [ 1 .. 2 ] items unique Items Enum: "title" "description" The text fields |
required | object (EventsFilter) The structured filter for |
| sort_by required | string (EventsSortBy) ^(?:_text_match|start_at|end_at|price_min|pri... Mandatory: MasterDB never supplies an order. |
| limit | integer [ 1 .. 50 ] At most 50 rows; default 50. There is no second page. |
| client_query_id | string^[\x21-\x7e]{1,128}$ The caller's own reference, echoed in the event stream. |
| session_ref | string^[\x21-\x7e]{1,128}$ Optional: your opaque label for the conversation, new for every conversation and never identifying a person. HMACed with a daily salt on arrival, used only for repeat limits and fraud patterns, never shown to a business. |
| topic_keywords | Array of strings [ 1 .. 10 ] items unique [ items [ 1 .. 64 ] characters ] Optional: subject terms of the search ("vegan restaurant", "late opening"), stored — screened for anything that looks personal — as demand insight for businesses. The free text |
{- "q": "wine tasting",
- "filter": {
- "all": [
- {
- "country": "US"
}, - {
- "start_at": {
- "gte": "2026-10-01T00:00:00Z",
- "lt": "2026-10-08T00:00:00Z"
}
}, - {
- "city": "Portland"
}
]
}, - "sort_by": "start_at:asc"
}{- "retrieval_id": "r_01J8XK2Q7R",
- "collection": "products",
- "country": "US",
- "rows": [
- {
- "record_id": "mdb_dq5jnqatnemnqj4g3xmgzgpoik",
- "business_uuid": "0b7d6c3e-2f4a-4c1b-9d8e-7f6a5b4c3d2e",
- "type": "products",
- "published_at": 1790669700,
- "product_name": "Ridge Trail Runner",
- "price_US": 129,
- "price_currency_US": "USD",
- "price_IE": 119,
- "price_currency_IE": "EUR",
- "adl_origin": "sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
- "adl_origin_cert": "cert_0b7d6c3e_3",
- "adl_proj": "products/3",
- "adl_row_sig": "3q2+7w==",
- "adl_key_id": "arnx6499M4j0-dWG9m6Z_VQIDfLERvDlhmiwnAihbdA",
- "ai_policy_version": 4,
- "ai_policy_bits": {
- "ai_policy_version": 4,
- "ai_policy_schema": 2,
- "use": 79,
- "action": 51,
- "blocked": 130
}
}
], - "receipt": {
- "payloadType": "application/vnd.masterdb.receipt.v3+json",
- "payload": "eyJyZXRyaWV2YWxfaWQiOiJyXzAxSjhYIn0=",
- "signatures": [
- {
- "keyid": "AV9-a8Wur0g3JAieklLME7UJUaa2lBJSJ2XP9NeAMG4",
- "sig": "3q2+7w=="
}
]
}
}The typed address for POST /v1/search with collection: jobs: openings a business
has published, with how and where the work is done and what it pays.
| MDB-Sandbox-Key | string [ 1 .. 8192 ] characters Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl Sandbox only. The |
| collection | any Required on Value: "jobs" |
| q | string [ 1 .. 512 ] characters The text query; |
| query_by | Array of any [ 1 .. 2 ] items unique Items Enum: "title" "description" The text fields |
required | object (JobsFilter) The structured filter for |
| sort_by required | string (JobsSortBy) ^(?:_text_match|salary_min|salary_max|closing... Mandatory: MasterDB never supplies an order. |
| limit | integer [ 1 .. 50 ] At most 50 rows; default 50. There is no second page. |
| client_query_id | string^[\x21-\x7e]{1,128}$ The caller's own reference, echoed in the event stream. |
| session_ref | string^[\x21-\x7e]{1,128}$ Optional: your opaque label for the conversation, new for every conversation and never identifying a person. HMACed with a daily salt on arrival, used only for repeat limits and fraud patterns, never shown to a business. |
| topic_keywords | Array of strings [ 1 .. 10 ] items unique [ items [ 1 .. 64 ] characters ] Optional: subject terms of the search ("vegan restaurant", "late opening"), stored — screened for anything that looks personal — as demand insight for businesses. The free text |
{- "q": "pastry chef",
- "filter": {
- "all": [
- {
- "country": "IE"
}, - {
- "employment_type": {
- "in": [
- "full_time",
- "part_time"
]
}
}, - {
- "salary_min": {
- "gte": "30000"
}
}
]
}, - "sort_by": "salary_max:desc",
- "limit": 20
}{- "retrieval_id": "r_01J8XK2Q7R",
- "collection": "products",
- "country": "US",
- "rows": [
- {
- "record_id": "mdb_dq5jnqatnemnqj4g3xmgzgpoik",
- "business_uuid": "0b7d6c3e-2f4a-4c1b-9d8e-7f6a5b4c3d2e",
- "type": "products",
- "published_at": 1790669700,
- "product_name": "Ridge Trail Runner",
- "price_US": 129,
- "price_currency_US": "USD",
- "price_IE": 119,
- "price_currency_IE": "EUR",
- "adl_origin": "sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
- "adl_origin_cert": "cert_0b7d6c3e_3",
- "adl_proj": "products/3",
- "adl_row_sig": "3q2+7w==",
- "adl_key_id": "arnx6499M4j0-dWG9m6Z_VQIDfLERvDlhmiwnAihbdA",
- "ai_policy_version": 4,
- "ai_policy_bits": {
- "ai_policy_version": 4,
- "ai_policy_schema": 2,
- "use": 79,
- "action": 51,
- "blocked": 130
}
}
], - "receipt": {
- "payloadType": "application/vnd.masterdb.receipt.v3+json",
- "payload": "eyJyZXRyaWV2YWxfaWQiOiJyXzAxSjhYIn0=",
- "signatures": [
- {
- "keyid": "AV9-a8Wur0g3JAieklLME7UJUaa2lBJSJ2XP9NeAMG4",
- "sig": "3q2+7w=="
}
]
}
}The typed address for POST /v1/search with collection: updates: news a business
has published about itself, with how long it stays relevant.
| MDB-Sandbox-Key | string [ 1 .. 8192 ] characters Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl Sandbox only. The |
| collection | any Required on Value: "updates" |
| q | string [ 1 .. 512 ] characters The text query; |
| query_by | Array of any [ 1 .. 2 ] items unique Items Enum: "headline" "body" The text fields |
required | object (UpdatesFilter) The structured filter for |
| sort_by required | string (UpdatesSortBy) ^(?:_text_match|published_at|relevant_until):... Mandatory: MasterDB never supplies an order. |
| limit | integer [ 1 .. 50 ] At most 50 rows; default 50. There is no second page. |
| client_query_id | string^[\x21-\x7e]{1,128}$ The caller's own reference, echoed in the event stream. |
| session_ref | string^[\x21-\x7e]{1,128}$ Optional: your opaque label for the conversation, new for every conversation and never identifying a person. HMACed with a daily salt on arrival, used only for repeat limits and fraud patterns, never shown to a business. |
| topic_keywords | Array of strings [ 1 .. 10 ] items unique [ items [ 1 .. 64 ] characters ] Optional: subject terms of the search ("vegan restaurant", "late opening"), stored — screened for anything that looks personal — as demand insight for businesses. The free text |
{- "q": "opening hours",
- "filter": {
- "all": [
- {
- "country": "GB"
}, - {
- "relevant_until": {
- "gte": "2026-10-01T00:00:00Z"
}
}
]
}, - "sort_by": "published_at:desc"
}{- "retrieval_id": "r_01J8XK2Q7R",
- "collection": "products",
- "country": "US",
- "rows": [
- {
- "record_id": "mdb_dq5jnqatnemnqj4g3xmgzgpoik",
- "business_uuid": "0b7d6c3e-2f4a-4c1b-9d8e-7f6a5b4c3d2e",
- "type": "products",
- "published_at": 1790669700,
- "product_name": "Ridge Trail Runner",
- "price_US": 129,
- "price_currency_US": "USD",
- "price_IE": 119,
- "price_currency_IE": "EUR",
- "adl_origin": "sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
- "adl_origin_cert": "cert_0b7d6c3e_3",
- "adl_proj": "products/3",
- "adl_row_sig": "3q2+7w==",
- "adl_key_id": "arnx6499M4j0-dWG9m6Z_VQIDfLERvDlhmiwnAihbdA",
- "ai_policy_version": 4,
- "ai_policy_bits": {
- "ai_policy_version": 4,
- "ai_policy_schema": 2,
- "use": 79,
- "action": 51,
- "blocked": 130
}
}
], - "receipt": {
- "payloadType": "application/vnd.masterdb.receipt.v3+json",
- "payload": "eyJyZXRyaWV2YWxfaWQiOiJyXzAxSjhYIn0=",
- "signatures": [
- {
- "keyid": "AV9-a8Wur0g3JAieklLME7UJUaa2lBJSJ2XP9NeAMG4",
- "sig": "3q2+7w=="
}
]
}
}Returns one record of any of the five types exactly as the business sealed it: the
bytes verbatim, the seal, MasterDB's signed sidecar, the business's sealed AI policy
record in force now (ai_policy — what proves a row's ai_policy_bits), the "represent us" texts for a business file, provenance (with the
source line to cite) and a receipt. For a business file with
authorised endpoints, endpoints says whether MasterDB still stands behind that section
today: suspended means continuous domain assurance lost control of one of its domains —
use none of its checkout, order, booking or API addresses. A record from a
business that blocked your group, a withdrawn record and one
that never existed all answer the same 404 with the same body, no sooner than 20 ms
after arrival, so none can be told from another. One id per call: there is no
batch fetch.
| record_id required | string (RecordId) ^(?:mdb_[a-z2-7]{26}|(?:bf|evt|job|upd|ad|aip... Example: mdb_dq5jnqatnemnqj4g3xmgzgpoik A record identifier: |
| MDB-Sandbox-Key | string [ 1 .. 8192 ] characters Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl Sandbox only. The |
{- "record_id": "mdb_dq5jnqatnemnqj4g3xmgzgpoik",
- "business_uuid": "0b7d6c3e-2f4a-4c1b-9d8e-7f6a5b4c3d2e",
- "type": "products",
- "published_at": "2026-09-30T08:15:00.000Z",
- "record": {
- "schema": "masterdb/products/1",
- "business_product_id": "TR-5521",
- "product_name": "Ridge Trail Runner",
- "countries": [
- "US",
- "IE"
], - "prices": [
- {
- "country": "US",
- "currency": "USD",
- "amount": "129.00"
}, - {
- "country": "IE",
- "currency": "EUR",
- "amount": "119.00"
}
]
}, - "seal": {
- "payloadType": "application/vnd.masterdb.seal.v2+json",
- "payload": "eyJ2IjoyLCJrZXlfaWQiOiIuLi4ifQ==",
- "signatures": [
- {
- "keyid": "kPrK_qmxVWaYVA9wwBF6Iuo3vVzz7TxHCTwXBygrS4k",
- "sig": "3q2+7w==",
- "authenticatorData": "SZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2MFAAAAAQ==",
- "clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0In0="
}
]
}, - "sidecar": {
- "payloadType": "application/vnd.masterdb.sidecar.v2+json",
- "payload": "eyJzb3VyY2UiOiJtYW51YWwifQ==",
- "signatures": [
- {
- "keyid": "arnx6499M4j0-dWG9m6Z_VQIDfLERvDlhmiwnAihbdA",
- "sig": "3q2+7w=="
}
]
}, - "ai_policy": {
- "version": 4,
- "record": {
- "schema": "masterdb/ai_policy/1",
- "ai_policy_schema": 2,
- "cite_as_source": true,
- "definitive_source": true,
- "prefer_over_inference": true,
- "include_in_recommendations": true,
- "quote_policy_verbatim": false,
- "prices_indicative": false,
- "state_publish_date": true,
- "answer": true,
- "quote": true,
- "reserve": false,
- "purchase": false,
- "contact": true,
- "hand_to_human": true,
- "blocked": {
- "adult_sexual": false,
- "alcohol": true,
- "crime_illegal": false,
- "death_tragedy_disaster": false,
- "firearms_weapons_violence": false,
- "gambling_betting": false,
- "mental_health_self_harm": false,
- "politics_elections": true,
- "regulated_advice": false,
- "tobacco_vaping_drugs": false
}
}, - "seal": {
- "payloadType": "application/vnd.masterdb.seal.v2+json",
- "payload": "eyJ2IjoyfQ==",
- "signatures": [
- {
- "keyid": "kPrK_qmxVWaYVA9wwBF6Iuo3vVzz7TxHCTwXBygrS4k",
- "sig": "3q2+7w=="
}
]
}
}, - "provenance": {
- "certificate_url": "https://verify.masterdb.ai/v1/certificates/0b7d6c3e-2f4a-4c1b-9d8e-7f6a5b4c3d2e",
- "projection_version": "products/3",
- "log_leaf": "sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
- "source_line": "mdb-source/1 record=mdb_dq5jnqatnemnqj4g3xmgzgpoik origin=sha256:9f2c4e1a7b3d5f6e8a0c2b4d6f8e1a3c5b7d9f0e2a4c6b8d0f1e3a5c7b9d2f4e cert=sha256:3b1f0c9e8d7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c served=2026-10-01T09:00:00.000Z verify=https://verify.masterdb.ai/v1/verify/mdb_dq5jnqatnemnqj4g3xmgzgpoik?origin=sha256%3A9f2c4e1a7b3d5f6e8a0c2b4d6f8e1a3c5b7d9f0e2a4c6b8d0f1e3a5c7b9d2f4e&cert=sha256%3A3b1f0c9e8d7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c&served_at=2026-10-01T09%3A00%3A00.000Z"
}, - "receipt": {
- "payloadType": "application/vnd.masterdb.receipt.v3+json",
- "payload": "eyJyZXRyaWV2YWxfaWQiOiJyXzAxSjhYIn0=",
- "signatures": [
- {
- "keyid": "AV9-a8Wur0g3JAieklLME7UJUaa2lBJSJ2XP9NeAMG4",
- "sig": "3q2+7w=="
}
]
}
}Returns up to 20 ads for one country and a few subject keywords, ordered by the sort
you state (refused without one) and optionally capped per campaign. Keywords
are an exact filter, never a text query, and must be subject terms — never the
user's question, never a user or conversation id (Rule 43). Each ad comes with its
whole creative, the advertiser's seal, signed links to its images (valid fifteen
minutes; fetch them server-side, never from an end user's browser), the net price you
would earn for it, its label and a render token; gross prices never leave MasterDB.
The sort keys are net_price, published_at, keyword_matches and random (seeded
by the pool's retrieval_id), each :asc or :desc, up to three. The pool
carries a receipt like every other response. An ad already rendered in the
conversation (session_ref) is left out of its pools for 60 minutes unless its
advertiser allows repeats. You choose what to render; confirm each render
with POST /v1/ads/render within ten minutes.
Each item verifies on its own (ADL spec): an ad is rendered alone, so
it carries the exact bytes the advertiser sealed (record_base64), its signed index row
(row: the advertiser's seal inline as adl_origin_seal, the destination as adl_dest,
a hash per image as adl_creative, and the advertiser's ai_policy_bits, as on every
search row) and the advertiser's sealed AI policy (ai_policy, as every fetch carries it). Check the row's signature, that its adl_origin is the hash of those bytes, the
seal over them, and that every text and link in creative is the sealed one; hash each
image you fetch against adl_creative. The SDKs' verifyAdItem / verify_ad_item does
all of it from public data, and POST /v1/verify {ad_item} answers the same question.
No fetch of an ad is needed, and none is offered.
| MDB-Sandbox-Key | string [ 1 .. 8192 ] characters Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl Sandbox only. The |
| country required | string (Country) ^[A-Z]{2}$ ISO 3166-1 alpha-2, from the platform vocabulary. |
| subdivision | string^[A-Z]{2}-[A-Z0-9]{1,3}$ ISO 3166-2 subdivision, when you know it. |
| keywords required | Array of strings [ 1 .. 10 ] items [ items [ 1 .. 64 ] characters ] Subject terms, matched exactly against the ads' keywords. Never the question, never a user or conversation id. |
| formats required | Array of strings (RenderFormat) non-empty unique Items Enum: "compact" "card" The render formats you can show. |
| sort_by required | string [ 1 .. 200 ] characters ^(?:net_price|published_at|keyword_matches|ra... Your order for the candidates — MasterDB never supplies one. Up to three
comma-separated keys from the allow-list, each |
| max_per_campaign | integer [ 1 .. 20 ] At most this many ads from one campaign in the pool. |
| size | integer [ 1 .. 20 ] How many ads you want; at most 20. |
| session_ref required | string [ 1 .. 128 ] characters Your opaque reference for the conversation, used only for repeat limits and fraud patterns; HMACed on arrival, kept 24 hours, never shown to a business. |
{- "country": "US",
- "keywords": [
- "running shoes",
- "trail running"
], - "formats": [
- "card",
- "compact"
], - "sort_by": "net_price:desc",
- "max_per_campaign": 2,
- "size": 5,
- "session_ref": "9f1c2e7a-conv"
}{- "retrieval_id": "r_01J8XK2Q7S",
- "ads": [
- {
- "ad_id": "ad_lisanb2yutfpdoaecdreat",
- "campaign_id": "cmp_7f6a5b4c",
- "business_uuid": "0b7d6c3e-2f4a-4c1b-9d8e-7f6a5b4c3d2e",
- "label": "Ad",
- "formats": [
- "card",
- "compact"
], - "creative": {
- "headline": "Ridge Trail Runner — 20% off",
- "description": "Grippy, light, built for wet trails.",
- "cta": "Shop Now",
- "display_domain": "ridge.example",
}, - "net_price": {
- "amount": "4.20",
- "currency": "USD",
- "basis": "cpm"
}, - "adl_origin_seal": {
- "payloadType": "application/vnd.masterdb.seal.v2+json",
- "payload": "eyJ2IjoyfQ==",
- "signatures": [
- {
- "keyid": "kPrK_qmxVWaYVA9wwBF6Iuo3vVzz7TxHCTwXBygrS4k",
- "sig": "3q2+7w=="
}
]
}, - "record_base64": "eyJzY2hlbWEiOiJtYXN0ZXJkYi9hZHMvMSJ9",
- "row": {
- "id": "ad_lisanb2yutfpdoaecdreat",
- "record_id": "ad_lisanb2yutfpdoaecdreat",
- "business_uuid": "0b7d6c3e-2f4a-4c1b-9d8e-7f6a5b4c3d2e",
- "type": "ads",
- "countries": [
- "US"
], - "published_at": 1790845231,
- "campaign_id": "cmp_7f6a5b4c",
- "headline": "Ridge Trail Runner — 20% off",
- "cta_text": "Shop Now",
- "display_domain": "ridge.example",
- "adl_creative": [
- "sha256:9f2c5b1e0d4a3c7b6e8f1a2d3c4b5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d"
], - "adl_origin_seal": "{\"payloadType\":\"application/vnd.masterdb.seal.v2+json\",\"payload\":\"eyJ2IjoyfQ==\",\"signatures\":[{\"keyid\":\"kPrK_qmxVWaYVA9wwBF6Iuo3vVzz7TxHCTwXBygrS4k\",\"sig\":\"3q2+7w==\"}]}",
- "adl_origin": "sha256:4b1e8f3a2c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a1b0c9d8e7f6a5b4c3d2e1f",
- "adl_proj": "sha256:7d1c9e2b4a6f8d0c3e5b7a9f1d3c5e7b9a1c3e5f7d9b1a3c5e7f9d1b3a5c7e9f",
- "ai_policy_version": 2,
- "adl_key_id": "AV9-a8Wur0g3JAieklLME7UJUaa2lBJSJ2XP9NeAMG4",
- "adl_row_sig": "3q2-7w",
- "ai_policy_bits": {
- "ai_policy_version": 2,
- "ai_policy_schema": 2,
- "use": 79,
- "action": 35,
- "blocked": 0
}
}, - "ai_policy": {
- "version": 2,
- "record_base64": "eyJzY2hlbWEiOiJtYXN0ZXJkYi9haV9wb2xpY3kvMSJ9",
- "seal": {
- "payloadType": "application/vnd.masterdb.seal.v2+json",
- "payload": "eyJ2IjoyfQ==",
- "signatures": [
- {
- "keyid": "kPrK_qmxVWaYVA9wwBF6Iuo3vVzz7TxHCTwXBygrS4k",
- "sig": "3q2+7w=="
}
]
}
}, - "render_token": {
- "payloadType": "application/vnd.masterdb.render.v1+json",
- "payload": "eyJ0b2tlbl9pZCI6InJ0XzEifQ==",
- "signatures": [
- {
- "keyid": "AV9-a8Wur0g3JAieklLME7UJUaa2lBJSJ2XP9NeAMG4",
- "sig": "3q2+7w=="
}
]
}
}
], - "receipt": {
- "payloadType": "application/vnd.masterdb.receipt.v3+json",
- "payload": "eyJyZXRyaWV2YWxfaWQiOiJyXzAxSjhYSzJRN1MifQ==",
- "signatures": [
- {
- "keyid": "AV9-a8Wur0g3JAieklLME7UJUaa2lBJSJ2XP9NeAMG4",
- "sig": "3q2+7w=="
}
]
}
}Confirms that you rendered an ad — with the render token from the pool — or a
sponsored or promoted row from a search, with that search's retrieval_id, the row's
id and the search's receipt, which must show the row served with its sponsored
marker (a row served unmarked is never charged). The region that minted the token, or
served the search, decides (a confirmation that reaches another region is forwarded
to it and its answer relayed unchanged), checks the ten-minute window and single use
on MasterDB's clock, turns the reserve into spend — for a sponsored row, reserves and
confirms in one step — and returns a click token, valid 24 hours, and for a
sponsored or promoted row the label to show (Sponsored, Promoted event, Promoted vacancy, Promoted update). A second render of the same item in one conversation is
accepted but neither charged nor paid, unless its advertiser allows repeats.
A late render is answered 200 with accepted: false and reason: window_expired,
a row whose budget ran out with budget_exhausted, and a replay with token_reused:
recorded, never billed, never paid.
| MDB-Sandbox-Key | string [ 1 .. 8192 ] characters Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl Sandbox only. The |
| Idempotency-Key required | string [ 1 .. 257 ] characters Example: 5f2b8c1e-7d3a-4e8f-9b6c-2a1d0e9f8c7b Required on every POST that creates something. 1–255 printable
ASCII characters. The same key with the same request replays the first answer; with a
different request it is |
object (ReceiptEnvelope) The receipt of the search the row was served in, exactly as received; its row must say | |
required | object (RenderTokenEnvelope) |
| retrieval_id | string |
| record_id | string (RecordId) ^(?:mdb_[a-z2-7]{26}|(?:bf|evt|job|upd|ad|aip... A record identifier: |
| format required | string (RenderFormat) Enum: "compact" "card" The two ways an ad can be rendered (ads contract, "Ad formats"); the AI company chooses. |
| session_ref required | string [ 1 .. 128 ] characters |
{- "render_token": {
- "payloadType": "application/vnd.masterdb.render.v1+json",
- "payload": "eyJ0b2tlbl9pZCI6InJ0XzEifQ==",
- "signatures": [
- {
- "keyid": "AV9-a8Wur0g3JAieklLME7UJUaa2lBJSJ2XP9NeAMG4",
- "sig": "3q2+7w=="
}
]
}, - "format": "card",
- "session_ref": "9f1c2e7a-conv"
}{- "accepted": true,
- "click_token": {
- "payloadType": "application/vnd.masterdb.click.v1+json",
- "payload": "eyJ0b2tlbl9pZCI6ImN0XzEifQ==",
- "signatures": [
- {
- "keyid": "AV9-a8Wur0g3JAieklLME7UJUaa2lBJSJ2XP9NeAMG4",
- "sig": "3q2+7w=="
}
]
}
}Confirms that a person clicked a rendered ad, with the click token from the render confirmation (valid 24 hours) and your conversation reference. A repeat click on the same ad from the same conversation within 15 minutes is recorded and not billed. MasterDB is never in the redirect path: send the person to the destination yourself.
| MDB-Sandbox-Key | string [ 1 .. 8192 ] characters Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl Sandbox only. The |
| Idempotency-Key required | string [ 1 .. 257 ] characters Example: 5f2b8c1e-7d3a-4e8f-9b6c-2a1d0e9f8c7b Required on every POST that creates something. 1–255 printable
ASCII characters. The same key with the same request replays the first answer; with a
different request it is |
required | object (ClickTokenEnvelope) |
| session_ref required | string [ 1 .. 128 ] characters |
{- "click_token": {
- "payloadType": "application/vnd.masterdb.click.v1+json",
- "payload": "eyJ0b2tlbl9pZCI6ImN0XzEifQ==",
- "signatures": [
- {
- "keyid": "AV9-a8Wur0g3JAieklLME7UJUaa2lBJSJ2XP9NeAMG4",
- "sig": "3q2+7w=="
}
]
}, - "session_ref": "9f1c2e7a-conv"
}{- "accepted": true,
- "click_token": {
- "payloadType": "application/vnd.masterdb.click.v1+json",
- "payload": "eyJ0b2tlbl9pZCI6ImN0XzEifQ==",
- "signatures": [
- {
- "keyid": "AV9-a8Wur0g3JAieklLME7UJUaa2lBJSJ2XP9NeAMG4",
- "sig": "3q2+7w=="
}
]
}
}Returns the receipts MasterDB issued to your own keys in a time window, per key and per legal entity, so you can reconcile what you asked for against what you were billed. Only ever your own: the key that signs this request decides whose receipts these are.
| from | string Example: from=2026-10-01T00:00:00Z Start of the window, inclusive (RFC 3339 UTC or a date). |
| to | string Example: to=2026-10-02T00:00:00Z End of the window, exclusive (RFC 3339 UTC or a date). |
| key_id | string (KeyId) ^[A-Za-z0-9_-]{43}$ Only receipts for requests signed by this key. |
| ai_company_uuid | string (AiCompanyUuid) ^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][... Only receipts for this legal entity of your group. |
| cursor | string <= 512 characters The opaque |
| MDB-Sandbox-Key | string [ 1 .. 8192 ] characters Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl Sandbox only. The |
{- "receipts": [
- {
- "retrieval_id": "r_01J8XK2Q7R",
- "served_at": "2026-10-01T14:02:11.482Z",
- "region": "us-east4",
- "key_id": "L1BSyf0VsZoYxYTQE2NWgZhhPww06EQJ73k4cJoVnsI",
- "ai_company_uuid": "1c8e7d4f-3a5b-4d2c-8e9f-8a7b6c5d4e3f",
- "receipt": {
- "payloadType": "application/vnd.masterdb.receipt.v3+json",
- "payload": "eyJyZXRyaWV2YWxfaWQiOiJyXzAxSjhYIn0=",
- "signatures": [
- {
- "keyid": "AV9-a8Wur0g3JAieklLME7UJUaa2lBJSJ2XP9NeAMG4",
- "sig": "3q2+7w=="
}
]
}
}
], - "next_cursor": "eyJhZnRlciI6InJfMDFKOFhLMlE3UiJ9"
}Your usage read model: queries and fetches by day, by key, by legal entity and by collection, and the pricing tiers consumed, as at the end of the last complete hour. Never which businesses matched and never another company's figures. No figure about blocks — no count, band or aggregate, here or anywhere on the AI side.
These are the figures the AI Portal shows, read from the same hourly read model: a count below 50 is the band <50. The window is whole UTC
days, the last 30 when neither bound is given.
| from | string Example: from=2026-10-01T00:00:00Z Start of the window, inclusive (RFC 3339 UTC or a date). |
| to | string Example: to=2026-10-02T00:00:00Z End of the window, exclusive (RFC 3339 UTC or a date). |
| MDB-Sandbox-Key | string [ 1 .. 8192 ] characters Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl Sandbox only. The |
{- "as_at": "2026-10-01T14:00:00.000Z",
- "days": [
- {
- "date": "2026-09-30",
- "key_id": "L1BSyf0VsZoYxYTQE2NWgZhhPww06EQJ73k4cJoVnsI",
- "ai_company_uuid": "1c8e7d4f-3a5b-4d2c-8e9f-8a7b6c5d4e3f",
- "collection": "products",
- "searches": 18231,
- "fetches": 4410,
- "billable": 21007
}
], - "tiers": [
- {
- "tier": 1,
- "from_queries": 0,
- "to_queries": 100000,
- "consumed": 21007
}
]
}The AI-company Terms in force now: the text, its version and its hash. The use conditions every delivery travels under — once, in one chat, no training, no caching — are stated here once and referenced by version, not repeated on every response.
| MDB-Sandbox-Key | string [ 1 .. 8192 ] characters Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl Sandbox only. The |
{- "version": 3,
- "effective_from": "2026-10-01T00:00:00.000Z",
- "sha256": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
- "text": "MasterDB AI-company Terms, version 3. …"
}Any past version of the AI-company Terms, so the version a receipt names can always be read in the words that governed it.
| version required | integer >= 1 Example: 3 |
| MDB-Sandbox-Key | string [ 1 .. 8192 ] characters Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl Sandbox only. The |
{- "version": 3,
- "effective_from": "2026-10-01T00:00:00.000Z",
- "sha256": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
- "text": "MasterDB AI-company Terms, version 3. …"
}