MasterDB Retrieval API (1.0.0)

Download OpenAPI specification:

URL: https://docs.masterdb.ai License: LicenseRef-MasterDB

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.

Search

Find candidates in one collection, with your own query, filter and sort.

Search one collection

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.

Authorizations:
mdbRequestSignature
header Parameters
MDB-Sandbox-Key
string [ 1 .. 8192 ] characters
Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl

Sandbox only. The sandbox_key_grant the portal answered when the key was taken there: MasterDB's signed statement of the key and its party, which holds no secret. The sandbox does not know a key taken in the portal until a request carries its grant: the first signed request with it creates the matching party in the sandbox and registers the key there, and is then verified like any other. Send it on every sandbox request: without it the first request with a new key is refused 401 key_unknown. A key production has revoked stays refused with its grant. Production ignores the header.

Request Body schema: application/json
required
One of
collection
required
any

Required on POST /v1/search; optional on the typed address, where it must be products if given.

Value: "products"
q
string [ 1 .. 512 ] characters

The text query; * (the default) matches everything the filter admits.

query_by
Array of any [ 1 .. 4 ] items unique
Items Enum: "product_name" "short_description" "tags" "brand"

The text fields q is matched against; default: all of them.

required
object (ProductsFilter)

The structured filter for products: every clause must hold. Exactly one clause names the country. Only the fields below exist; anything else is unknown_field, and an operator a field does not list is operator_not_allowed.

sort_by
required
string (ProductsSortBy) ^(?:_text_match|price_amount|published_at):(?...

Mandatory: MasterDB never supplies an order. field:asc|desc, up to 3, comma-separated, from: _text_match, price_amount, published_at. For relevance order write _text_match:desc.

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 runs the search and is never stored.

Responses

Request samples

Content type
application/json
{
  • "collection": "products",
  • "q": "trail running shoes",
  • "query_by": [
    ],
  • "filter": {
    },
  • "sort_by": "price_amount:asc",
  • "limit": 25,
  • "client_query_id": "q-2026-10-01-0001",
  • "session_ref": "9f1c2e7a-conv",
  • "topic_keywords": [
    ]
}

Response samples

Content type
application/json
{
  • "retrieval_id": "r_01J8XK2Q7R",
  • "collection": "products",
  • "country": "US",
  • "rows": [
    ],
  • "receipt": {
    }
}

Search products

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.

Authorizations:
mdbRequestSignature
header Parameters
MDB-Sandbox-Key
string [ 1 .. 8192 ] characters
Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl

Sandbox only. The sandbox_key_grant the portal answered when the key was taken there: MasterDB's signed statement of the key and its party, which holds no secret. The sandbox does not know a key taken in the portal until a request carries its grant: the first signed request with it creates the matching party in the sandbox and registers the key there, and is then verified like any other. Send it on every sandbox request: without it the first request with a new key is refused 401 key_unknown. A key production has revoked stays refused with its grant. Production ignores the header.

Request Body schema: application/json
required
collection
any

Required on POST /v1/search; optional on the typed address, where it must be products if given.

Value: "products"
q
string [ 1 .. 512 ] characters

The text query; * (the default) matches everything the filter admits.

query_by
Array of any [ 1 .. 4 ] items unique
Items Enum: "product_name" "short_description" "tags" "brand"

The text fields q is matched against; default: all of them.

required
object (ProductsFilter)

The structured filter for products: every clause must hold. Exactly one clause names the country. Only the fields below exist; anything else is unknown_field, and an operator a field does not list is operator_not_allowed.

sort_by
required
string (ProductsSortBy) ^(?:_text_match|price_amount|published_at):(?...

Mandatory: MasterDB never supplies an order. field:asc|desc, up to 3, comma-separated, from: _text_match, price_amount, published_at. For relevance order write _text_match:desc.

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 runs the search and is never stored.

Responses

Request samples

Content type
application/json
{
  • "q": "trail running shoes",
  • "filter": {
    },
  • "sort_by": "_text_match:desc,price_amount:asc",
  • "limit": 10
}

Response samples

Content type
application/json
{
  • "retrieval_id": "r_01J8XK2Q7R",
  • "collection": "products",
  • "country": "US",
  • "rows": [
    ],
  • "receipt": {
    }
}

Search business files

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.

Authorizations:
mdbRequestSignature
header Parameters
MDB-Sandbox-Key
string [ 1 .. 8192 ] characters
Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl

Sandbox only. The sandbox_key_grant the portal answered when the key was taken there: MasterDB's signed statement of the key and its party, which holds no secret. The sandbox does not know a key taken in the portal until a request carries its grant: the first signed request with it creates the matching party in the sandbox and registers the key there, and is then verified like any other. Send it on every sandbox request: without it the first request with a new key is refused 401 key_unknown. A key production has revoked stays refused with its grant. Production ignores the header.

Request Body schema: application/json
required
collection
any

Required on POST /v1/search; optional on the typed address, where it must be business_files if given.

Value: "business_files"
q
string [ 1 .. 512 ] characters

The text query; * (the default) matches everything the filter admits.

query_by
Array of any [ 1 .. 4 ] items unique
Items Enum: "description" "brands_owned.name" "brands_sold.name" "markets_served"

The text fields q is matched against; default: all of them.

required
object (BusinessFilesFilter)

The structured filter for business_files: every clause must hold. Exactly one clause names the country. Only the fields below exist; anything else is unknown_field, and an operator a field does not list is operator_not_allowed.

sort_by
required
string (BusinessFilesSortBy) ^(?:_text_match|year_established|published_at...

Mandatory: MasterDB never supplies an order. field:asc|desc, up to 3, comma-separated, from: _text_match, year_established, published_at. For relevance order write _text_match:desc.

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 runs the search and is never stored.

Responses

Request samples

Content type
application/json
{
  • "q": "independent bookshop",
  • "filter": {
    },
  • "sort_by": "_text_match:desc"
}

Response samples

Content type
application/json
{
  • "retrieval_id": "r_01J8XK2Q7R",
  • "collection": "products",
  • "country": "US",
  • "rows": [
    ],
  • "receipt": {
    }
}

Search events

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.

Authorizations:
mdbRequestSignature
header Parameters
MDB-Sandbox-Key
string [ 1 .. 8192 ] characters
Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl

Sandbox only. The sandbox_key_grant the portal answered when the key was taken there: MasterDB's signed statement of the key and its party, which holds no secret. The sandbox does not know a key taken in the portal until a request carries its grant: the first signed request with it creates the matching party in the sandbox and registers the key there, and is then verified like any other. Send it on every sandbox request: without it the first request with a new key is refused 401 key_unknown. A key production has revoked stays refused with its grant. Production ignores the header.

Request Body schema: application/json
required
collection
any

Required on POST /v1/search; optional on the typed address, where it must be events if given.

Value: "events"
q
string [ 1 .. 512 ] characters

The text query; * (the default) matches everything the filter admits.

query_by
Array of any [ 1 .. 2 ] items unique
Items Enum: "title" "description"

The text fields q is matched against; default: all of them.

required
object (EventsFilter)

The structured filter for events: every clause must hold. Exactly one clause names the country. Only the fields below exist; anything else is unknown_field, and an operator a field does not list is operator_not_allowed.

sort_by
required
string (EventsSortBy) ^(?:_text_match|start_at|end_at|price_min|pri...

Mandatory: MasterDB never supplies an order. field:asc|desc, up to 3, comma-separated, from: _text_match, start_at, end_at, price_min, price_max, published_at. For relevance order write _text_match:desc.

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 runs the search and is never stored.

Responses

Request samples

Content type
application/json
{
  • "q": "wine tasting",
  • "filter": {
    },
  • "sort_by": "start_at:asc"
}

Response samples

Content type
application/json
{
  • "retrieval_id": "r_01J8XK2Q7R",
  • "collection": "products",
  • "country": "US",
  • "rows": [
    ],
  • "receipt": {
    }
}

Search jobs

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.

Authorizations:
mdbRequestSignature
header Parameters
MDB-Sandbox-Key
string [ 1 .. 8192 ] characters
Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl

Sandbox only. The sandbox_key_grant the portal answered when the key was taken there: MasterDB's signed statement of the key and its party, which holds no secret. The sandbox does not know a key taken in the portal until a request carries its grant: the first signed request with it creates the matching party in the sandbox and registers the key there, and is then verified like any other. Send it on every sandbox request: without it the first request with a new key is refused 401 key_unknown. A key production has revoked stays refused with its grant. Production ignores the header.

Request Body schema: application/json
required
collection
any

Required on POST /v1/search; optional on the typed address, where it must be jobs if given.

Value: "jobs"
q
string [ 1 .. 512 ] characters

The text query; * (the default) matches everything the filter admits.

query_by
Array of any [ 1 .. 2 ] items unique
Items Enum: "title" "description"

The text fields q is matched against; default: all of them.

required
object (JobsFilter)

The structured filter for jobs: every clause must hold. Exactly one clause names the country. Only the fields below exist; anything else is unknown_field, and an operator a field does not list is operator_not_allowed.

sort_by
required
string (JobsSortBy) ^(?:_text_match|salary_min|salary_max|closing...

Mandatory: MasterDB never supplies an order. field:asc|desc, up to 3, comma-separated, from: _text_match, salary_min, salary_max, closing_date, published_at. For relevance order write _text_match:desc.

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 runs the search and is never stored.

Responses

Request samples

Content type
application/json
{
  • "q": "pastry chef",
  • "filter": {
    },
  • "sort_by": "salary_max:desc",
  • "limit": 20
}

Response samples

Content type
application/json
{
  • "retrieval_id": "r_01J8XK2Q7R",
  • "collection": "products",
  • "country": "US",
  • "rows": [
    ],
  • "receipt": {
    }
}

Search updates

The typed address for POST /v1/search with collection: updates: news a business has published about itself, with how long it stays relevant.

Authorizations:
mdbRequestSignature
header Parameters
MDB-Sandbox-Key
string [ 1 .. 8192 ] characters
Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl

Sandbox only. The sandbox_key_grant the portal answered when the key was taken there: MasterDB's signed statement of the key and its party, which holds no secret. The sandbox does not know a key taken in the portal until a request carries its grant: the first signed request with it creates the matching party in the sandbox and registers the key there, and is then verified like any other. Send it on every sandbox request: without it the first request with a new key is refused 401 key_unknown. A key production has revoked stays refused with its grant. Production ignores the header.

Request Body schema: application/json
required
collection
any

Required on POST /v1/search; optional on the typed address, where it must be updates if given.

Value: "updates"
q
string [ 1 .. 512 ] characters

The text query; * (the default) matches everything the filter admits.

query_by
Array of any [ 1 .. 2 ] items unique
Items Enum: "headline" "body"

The text fields q is matched against; default: all of them.

required
object (UpdatesFilter)

The structured filter for updates: every clause must hold. Exactly one clause names the country. Only the fields below exist; anything else is unknown_field, and an operator a field does not list is operator_not_allowed.

sort_by
required
string (UpdatesSortBy) ^(?:_text_match|published_at|relevant_until):...

Mandatory: MasterDB never supplies an order. field:asc|desc, up to 3, comma-separated, from: _text_match, published_at, relevant_until. For relevance order write _text_match:desc.

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 runs the search and is never stored.

Responses

Request samples

Content type
application/json
{
  • "q": "opening hours",
  • "filter": {
    },
  • "sort_by": "published_at:desc"
}

Response samples

Content type
application/json
{
  • "retrieval_id": "r_01J8XK2Q7R",
  • "collection": "products",
  • "country": "US",
  • "rows": [
    ],
  • "receipt": {
    }
}

Records

Fetch one record exactly as the business sealed it.

Fetch one record

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.

Authorizations:
mdbRequestSignature
path Parameters
record_id
required
string (RecordId) ^(?:mdb_[a-z2-7]{26}|(?:bf|evt|job|upd|ad|aip...
Example: mdb_dq5jnqatnemnqj4g3xmgzgpoik

A record identifier: mdb_ + 26 base32 characters for a product, or bf_, evt_, job_, upd_, ad_, aip_, frm_ + 22 random base32 characters. Never encodes its owner. trm_ is no longer minted and still read (an AI policy sealed as terms, its earlier name).

header Parameters
MDB-Sandbox-Key
string [ 1 .. 8192 ] characters
Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl

Sandbox only. The sandbox_key_grant the portal answered when the key was taken there: MasterDB's signed statement of the key and its party, which holds no secret. The sandbox does not know a key taken in the portal until a request carries its grant: the first signed request with it creates the matching party in the sandbox and registers the key there, and is then verified like any other. Send it on every sandbox request: without it the first request with a new key is refused 401 key_unknown. A key production has revoked stays refused with its grant. Production ignores the header.

Responses

Response samples

Content type
application/json
{
  • "record_id": "mdb_dq5jnqatnemnqj4g3xmgzgpoik",
  • "business_uuid": "0b7d6c3e-2f4a-4c1b-9d8e-7f6a5b4c3d2e",
  • "type": "products",
  • "published_at": "2026-09-30T08:15:00.000Z",
  • "record": {
    },
  • "seal": {
    },
  • "sidecar": {
    },
  • "ai_policy": {
    },
  • "provenance": {
    },
  • "receipt": {
    }
}

Ads

The ad and sponsored-item pool, and the render and click confirmations.

Get the ad pool for a context

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.

Authorizations:
mdbRequestSignature
header Parameters
MDB-Sandbox-Key
string [ 1 .. 8192 ] characters
Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl

Sandbox only. The sandbox_key_grant the portal answered when the key was taken there: MasterDB's signed statement of the key and its party, which holds no secret. The sandbox does not know a key taken in the portal until a request carries its grant: the first signed request with it creates the matching party in the sandbox and registers the key there, and is then verified like any other. Send it on every sandbox request: without it the first request with a new key is refused 401 key_unknown. A key production has revoked stays refused with its grant. Production ignores the header.

Request Body schema: application/json
required
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 :asc or :desc: net_price (what you would earn, per thousand renders or per click), published_at, keyword_matches (how many of your keywords the ad names) and random (seeded by this pool's retrieval_id).

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.

Responses

Request samples

Content type
application/json
{
  • "country": "US",
  • "keywords": [
    ],
  • "formats": [
    ],
  • "sort_by": "net_price:desc",
  • "max_per_campaign": 2,
  • "size": 5,
  • "session_ref": "9f1c2e7a-conv"
}

Response samples

Content type
application/json
{
  • "retrieval_id": "r_01J8XK2Q7S",
  • "ads": [
    ],
  • "receipt": {
    }
}

Confirm a render

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.

Authorizations:
mdbRequestSignature
header Parameters
MDB-Sandbox-Key
string [ 1 .. 8192 ] characters
Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl

Sandbox only. The sandbox_key_grant the portal answered when the key was taken there: MasterDB's signed statement of the key and its party, which holds no secret. The sandbox does not know a key taken in the portal until a request carries its grant: the first signed request with it creates the matching party in the sandbox and registers the key there, and is then verified like any other. Send it on every sandbox request: without it the first request with a new key is refused 401 key_unknown. A key production has revoked stays refused with its grant. Production ignores the header.

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 idempotency_key_reused (422); while the first is still in flight it is idempotency_in_progress (409).

Request Body schema: application/json
required
One of
object (ReceiptEnvelope)

The receipt of the search the row was served in, exactly as received; its row must say sponsored.

required
object (RenderTokenEnvelope)
retrieval_id
string
record_id
string (RecordId) ^(?:mdb_[a-z2-7]{26}|(?:bf|evt|job|upd|ad|aip...

A record identifier: mdb_ + 26 base32 characters for a product, or bf_, evt_, job_, upd_, ad_, aip_, frm_ + 22 random base32 characters. Never encodes its owner. trm_ is no longer minted and still read (an AI policy sealed as terms, its earlier name).

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

Responses

Request samples

Content type
application/json
{
  • "render_token": {
    },
  • "format": "card",
  • "session_ref": "9f1c2e7a-conv"
}

Response samples

Content type
application/json
{
  • "accepted": true,
  • "click_token": {
    }
}

Confirm a click

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.

Authorizations:
mdbRequestSignature
header Parameters
MDB-Sandbox-Key
string [ 1 .. 8192 ] characters
Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl

Sandbox only. The sandbox_key_grant the portal answered when the key was taken there: MasterDB's signed statement of the key and its party, which holds no secret. The sandbox does not know a key taken in the portal until a request carries its grant: the first signed request with it creates the matching party in the sandbox and registers the key there, and is then verified like any other. Send it on every sandbox request: without it the first request with a new key is refused 401 key_unknown. A key production has revoked stays refused with its grant. Production ignores the header.

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 idempotency_key_reused (422); while the first is still in flight it is idempotency_in_progress (409).

Request Body schema: application/json
required
required
object (ClickTokenEnvelope)
session_ref
required
string [ 1 .. 128 ] characters

Responses

Request samples

Content type
application/json
{
  • "click_token": {
    },
  • "session_ref": "9f1c2e7a-conv"
}

Response samples

Content type
application/json
{
  • "accepted": true,
  • "click_token": {
    }
}

Receipts and usage

Your own receipts and usage, for reconciliation.

List your own receipts

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.

Authorizations:
mdbRequestSignature
query Parameters
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 next_cursor of the previous page.

header Parameters
MDB-Sandbox-Key
string [ 1 .. 8192 ] characters
Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl

Sandbox only. The sandbox_key_grant the portal answered when the key was taken there: MasterDB's signed statement of the key and its party, which holds no secret. The sandbox does not know a key taken in the portal until a request carries its grant: the first signed request with it creates the matching party in the sandbox and registers the key there, and is then verified like any other. Send it on every sandbox request: without it the first request with a new key is refused 401 key_unknown. A key production has revoked stays refused with its grant. Production ignores the header.

Responses

Response samples

Content type
application/json
{
  • "receipts": [
    ],
  • "next_cursor": "eyJhZnRlciI6InJfMDFKOFhLMlE3UiJ9"
}

Read your usage

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.

Authorizations:
mdbRequestSignature
query Parameters
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).

header Parameters
MDB-Sandbox-Key
string [ 1 .. 8192 ] characters
Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl

Sandbox only. The sandbox_key_grant the portal answered when the key was taken there: MasterDB's signed statement of the key and its party, which holds no secret. The sandbox does not know a key taken in the portal until a request carries its grant: the first signed request with it creates the matching party in the sandbox and registers the key there, and is then verified like any other. Send it on every sandbox request: without it the first request with a new key is refused 401 key_unknown. A key production has revoked stays refused with its grant. Production ignores the header.

Responses

Response samples

Content type
application/json
{
  • "as_at": "2026-10-01T14:00:00.000Z",
  • "days": [
    ],
  • "tiers": [
    ]
}

Terms

The AI-company Terms in force and every past version.

Read the Terms in force

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.

Authorizations:
mdbRequestSignature
header Parameters
MDB-Sandbox-Key
string [ 1 .. 8192 ] characters
Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl

Sandbox only. The sandbox_key_grant the portal answered when the key was taken there: MasterDB's signed statement of the key and its party, which holds no secret. The sandbox does not know a key taken in the portal until a request carries its grant: the first signed request with it creates the matching party in the sandbox and registers the key there, and is then verified like any other. Send it on every sandbox request: without it the first request with a new key is refused 401 key_unknown. A key production has revoked stays refused with its grant. Production ignores the header.

Responses

Response samples

Content type
application/json
{
  • "version": 3,
  • "effective_from": "2026-10-01T00:00:00.000Z",
  • "sha256": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
  • "text": "MasterDB AI-company Terms, version 3. …"
}

Read a past version of the Terms

Any past version of the AI-company Terms, so the version a receipt names can always be read in the words that governed it.

Authorizations:
mdbRequestSignature
path Parameters
version
required
integer >= 1
Example: 3
header Parameters
MDB-Sandbox-Key
string [ 1 .. 8192 ] characters
Example: mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl

Sandbox only. The sandbox_key_grant the portal answered when the key was taken there: MasterDB's signed statement of the key and its party, which holds no secret. The sandbox does not know a key taken in the portal until a request carries its grant: the first signed request with it creates the matching party in the sandbox and registers the key there, and is then verified like any other. Send it on every sandbox request: without it the first request with a new key is refused 401 key_unknown. A key production has revoked stays refused with its grant. Production ignores the header.

Responses

Response samples

Content type
application/json
{
  • "version": 3,
  • "effective_from": "2026-10-01T00:00:00.000Z",
  • "sha256": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
  • "text": "MasterDB AI-company Terms, version 3. …"
}