{
  "openapi": "3.1.0",
  "info": {
    "title": "MasterDB Business Machine API",
    "version": "1.0.0",
    "summary": "What a business's own systems call to publish, read back and audit what they published.",
    "description": "The business machine API, for a business's own\nintegration, a Shopify-style connector or an agency's feed — ADL Path A. There is no\nbearer token: every request is signed with RFC 9421 by an integration key the business\ngenerated and registered (`tag=\"mdb-push\"`), and what authorises that key is a\npublishing mandate an admin sealed with their passkey, scoped to record types and\ncountries and valid for at most 92 days.\n\nReads — the catalogue read-back, push attempts and analytics — are signed with the tag\n`mdb-business-read` instead, and need a registered key but no mandate.\n\nSealed, or not published: every record is sealed by the business, a batch with\none Merkle root, and a record whose seal does not verify is refused with a reason that\nnames the seal. A push replaces the record; there is no merge on this path. Nothing\npublishes without a seal, and a bare `DELETE` is refused.\n",
    "contact": {
      "name": "MasterDB developer documentation",
      "url": "https://docs.masterdb.ai"
    },
    "license": {
      "name": "Proprietary",
      "identifier": "LicenseRef-MasterDB"
    }
  },
  "servers": [
    {
      "url": "https://api.masterdb.ai",
      "description": "Production."
    },
    {
      "url": "https://sandbox.api.masterdb.ai",
      "description": "Sandbox — the same publish path and the full validator with every reason."
    }
  ],
  "security": [
    {
      "mdbRequestSignature": [
        "mdb-push"
      ]
    }
  ],
  "tags": [
    {
      "name": "Publishing",
      "description": "Sealed batch pushes, withdrawals and deletes."
    },
    {
      "name": "Catalogue",
      "description": "Read back what you published — a manifest, not an export."
    },
    {
      "name": "Push attempts",
      "description": "The ingestion audit."
    },
    {
      "name": "Pushes",
      "description": "A push's status while it is processed, and the bulk-file route for very large loads."
    },
    {
      "name": "Seal context",
      "description": "What a seal must name — the certificate and the AI policy version in force."
    },
    {
      "name": "Analytics",
      "description": "Your own figures."
    }
  ],
  "paths": {
    "/v1/publish/{type}": {
      "post": {
        "operationId": "publishBatch",
        "tags": [
          "Publishing"
        ],
        "summary": "Push a sealed batch",
        "description": "Publishes a batch of records of one type, each exactly the bytes the business sealed,\nunder one batch seal: a Merkle root over the records' raw bytes signed with the\nbusiness's own key, carrying the per-key sequence number `seq` that must be greater\nthan the last accepted one (so a stolen key cannot roll a price back by replaying an\nold seal) and a `sealed_at` within five minutes of receipt. Each record is validated\nwith every reason at once and answered `accepted`, `updated` or `rejected`; a push\nreplaces the record it names. A push that would move more than a fifth of the\ncatalogue's prices is held for the owner (the price-shock hold). Only `products` is published through this route.\n\nEvery record is also held to the scope rule (text naming another company or brand,\nor directing how other sources are treated, is `scope_violation`; a brand the business\nsells belongs in its Business & Brand Identity file's `brands_sold`) and to a malware and phishing check (`url_flagged`), and a `display_domain` must be its `destination_url`'s own host\n(`display_domain_mismatch`) — each a per-record rejection, never the batch's.\n\n**Back-pressure**: the per-key caps stamped on the mandate — records per\nhour and bytes per day — are judged before the body is parsed, and a request over\neither is answered `429 rate_limited` with `Retry-After`. A mandate with a source\nallow-list (CIDR ranges and `AS` numbers) is honoured only from inside it\n(`403 source_not_allowed`).\n\n**Accepted, then processed**. Everything that must refuse a batch is checked\nbefore the answer: the request signature, the key, the mandate and its caps, the\nverified business, the batch seal, its Merkle root over the records, the certificate,\nthe AI policy version, `seq`, and the business's fair use. Then:\n\n- **up to 50 records** are processed inside the request and answered **`200`** with\n  every outcome (`PublishOutcome`), as before;\n- **51 to 10,000 records** are stored for processing and answered **`202`** at once with\n  the push's status (`PushStatus`) and a `Location` header: poll\n  `GET /v1/pushes/{push_id}` until `state` is `complete` (or `held`, or `failed`). The\n  records are checked and published in chunks of 200 in the background; a notice tells\n  the business's owners and admins when it finishes.\n\nIf background processing cannot be reached, a push of up to 500 records is processed\ninside its request (`200`). A larger one is answered `503` with `Retry-After: 60` and\n`retry_after_seconds`: send the same batch again later; a batch that was already accepted\nis kept and resumes.\nFor more than 10,000 records, upload a bulk file (`POST /v1/bulk-uploads`, then\n`POST /v1/bulk-imports`).\n\n**A push that does not answer, or stops** (a timeout, a dropped connection, a `5xx`, a\n`failed` status): every record of the batch has a row in `GET /v1/push-attempts` and on\nits status — `rejected` with its reasons, or `pending` — and each `pending` row becomes\n`accepted`, `updated` or `held` in the same commit that publishes (or holds) its record.\nSending the **exact batch again** (the same `batch_seal` and records, a new request\nsignature — accepted after the five-minute `sealed_at` window too, since it was accepted\nbefore) resumes it: the records it already settled keep their outcome, the rest are\ncompleted, and nothing is published twice. A push still being processed is only reported.\nAny other batch under the same `seq` is refused (`seq_not_increasing`).\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/SandboxKey"
          },
          {
            "$ref": "#/components/parameters/PublishType"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublishBatch"
              },
              "example": {
                "batch_seal": {
                  "payloadType": "application/vnd.masterdb.batch-seal.v2+json",
                  "payload": "eyJ2IjoyLCJzZXEiOjQyfQ==",
                  "signatures": [
                    {
                      "keyid": "0aWsmgFfrC73s0FnNjVRKhUR9B_jfREbJn8DnuxdT1g",
                      "sig": "3q2+7w=="
                    }
                  ]
                },
                "records": [
                  "eyJzY2hlbWEiOiJtYXN0ZXJkYi9wcm9kdWN0cy8xIiwiYnVzaW5lc3NfcHJvZHVjdF9pZCI6IlRSLTU1MjEifQ==",
                  "eyJzY2hlbWEiOiJtYXN0ZXJkYi9wcm9kdWN0cy8xIiwiYnVzaW5lc3NfcHJvZHVjdF9pZCI6IlRSLTU1MjIifQ=="
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One outcome per record, in the order sent.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublishOutcome"
                },
                "example": {
                  "batch_id": "bat_7d3a4e8f9b6c",
                  "seq": 42,
                  "held": false,
                  "results": [
                    {
                      "leaf_index": 0,
                      "outcome": "updated",
                      "record_id": "mdb_dq5jnqatnemnqj4g3xmgzgpoik",
                      "version": 7,
                      "sha256": "sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae",
                      "seal_digest": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
                    },
                    {
                      "leaf_index": 1,
                      "outcome": "rejected",
                      "errors": [
                        {
                          "code": "money_not_string",
                          "pointer": "/prices/0/amount",
                          "detail": "amount is a decimal string, e.g. \"129.00\""
                        }
                      ]
                    }
                  ]
                }
              }
            }
          },
          "202": {
            "description": "Accepted (51 to 10,000 records); processed in the background. Poll `status_url`.",
            "headers": {
              "Location": {
                "description": "The push's status, `/v1/pushes/{push_id}`.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushStatus"
                },
                "example": {
                  "push_id": "bat_7d3a4e8f9b6c1a2b3c4d5e6f",
                  "batch_id": "bat_7d3a4e8f9b6c1a2b3c4d5e6f",
                  "type": "products",
                  "seq": 42,
                  "source": "api",
                  "mode": "queued",
                  "state": "queued",
                  "held": false,
                  "held_reasons": [],
                  "records": 8000,
                  "counts": {
                    "rejected": 0,
                    "pending": 8000,
                    "accepted": 0,
                    "updated": 0,
                    "held": 0
                  },
                  "progress": {
                    "stage": "check",
                    "chunk": 0,
                    "chunks": 40
                  },
                  "received_at": "2026-10-03T14:02:11.482Z",
                  "updated_at": "2026-10-03T14:02:11.482Z",
                  "completed_at": null,
                  "error": null,
                  "status_url": "/v1/pushes/bat_7d3a4e8f9b6c1a2b3c4d5e6f",
                  "poll_after_seconds": 5
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          }
        }
      }
    },
    "/v1/pushes/{push_id}": {
      "get": {
        "operationId": "getPushStatus",
        "security": [
          {
            "mdbRequestSignature": [
              "mdb-business-read"
            ]
          }
        ],
        "tags": [
          "Pushes"
        ],
        "summary": "Read a push's status and its per-record outcomes",
        "description": "A push or bulk import accepted then processed: its totals, its progress and a page\nof its records' outcomes in leaf order (100 a page; `next_cursor` for the next). With\n`outcome`, only the records with that outcome — e.g. `rejected`, to fix and send again.\nPoll every `poll_after_seconds` while it is present. A push that has completed no step for\nten minutes carries `stalled: true` and a `resume` instruction (send the exact batch again —\na bulk import, the same import request again; what it already published is not published\ntwice). Signed with `mdb-business-read`: any live integration key of the business may read it.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/SandboxKey"
          },
          {
            "name": "push_id",
            "in": "path",
            "required": true,
            "schema": {
              "$ref": "#/components/schemas/PushId"
            }
          },
          {
            "name": "outcome",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "accepted",
                "updated",
                "rejected",
                "held",
                "pending"
              ]
            },
            "example": "rejected"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "The push's status and a page of its records.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushStatusPage"
                },
                "example": {
                  "push_id": "bat_7d3a4e8f9b6c1a2b3c4d5e6f",
                  "batch_id": "bat_7d3a4e8f9b6c1a2b3c4d5e6f",
                  "type": "products",
                  "seq": 42,
                  "source": "api",
                  "mode": "queued",
                  "state": "processing",
                  "held": false,
                  "held_reasons": [],
                  "records": 8000,
                  "counts": {
                    "rejected": 3,
                    "pending": 3797,
                    "accepted": 4100,
                    "updated": 100,
                    "held": 0
                  },
                  "progress": {
                    "stage": "commit",
                    "chunk": 21,
                    "chunks": 40
                  },
                  "received_at": "2026-10-03T14:02:11.482Z",
                  "updated_at": "2026-10-03T14:04:40.120Z",
                  "completed_at": null,
                  "error": null,
                  "status_url": "/v1/pushes/bat_7d3a4e8f9b6c1a2b3c4d5e6f",
                  "poll_after_seconds": 5,
                  "results": [
                    {
                      "leaf_index": 17,
                      "outcome": "rejected",
                      "business_product_id": "TR-5521",
                      "errors": [
                        {
                          "code": "money_not_string",
                          "pointer": "/prices/0/amount",
                          "detail": "amount is a decimal string, e.g. \"129.00\""
                        }
                      ]
                    }
                  ],
                  "next_cursor": "eyJhZnRlciI6IjE4In0"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          }
        }
      }
    },
    "/v1/bulk-uploads": {
      "post": {
        "operationId": "createBulkUpload",
        "tags": [
          "Pushes"
        ],
        "summary": "Get a signed upload for a bulk file",
        "description": "The bulk-file route for very large loads, step 1: a signed upload (valid one hour) for one file of up to 100,000 records and 256 MiB. The file\nis newline-delimited: **one record a line, each line the base64 of the record's exact\nbytes** (`application/x-ndjson`); line *i* is leaf *i* of the batch seal's Merkle tree.\nPOST the file to `url` as `multipart/form-data` with every member of `fields`, then the\nfile as `file`. The key needs a live mandate for the record type. Uploaded files are\ndeleted after 7 days, or as soon as their import completes.\n\nAnswered `503` with `Retry-After` (60 seconds) and `reason: staging_unavailable` where the\nupload area cannot be written, and `503` with a longer `Retry-After` where bulk import is\nnot available.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/SandboxKey"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "record_type": {
                    "$ref": "#/components/schemas/RecordType"
                  }
                }
              },
              "example": {
                "record_type": "products"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The upload slot.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkUpload"
                },
                "example": {
                  "upload_id": "bup_5f1c0e9a8b7d6c5b4a3f2e1d",
                  "record_type": "products",
                  "url": "https://upload.example.com/bulk/",
                  "fields": {
                    "key": "bulk/0f3c9a/bup_5f1c0e9a8b7d6c5b4a3f2e1d.ndjson",
                    "Content-Type": "application/x-ndjson",
                    "policy": "eyJjb25kaXRpb25zIjpbXX0=",
                    "x-algorithm": "SHA256"
                  },
                  "content_type": "application/x-ndjson",
                  "max_bytes": 268435456,
                  "max_records": 100000,
                  "expires_at": "2026-10-03T15:02:11.482Z"
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          }
        }
      }
    },
    "/v1/bulk-imports": {
      "post": {
        "operationId": "createBulkImport",
        "tags": [
          "Pushes"
        ],
        "summary": "Import an uploaded bulk file under its batch seal",
        "description": "The bulk-file route, step 2: the uploaded file's `upload_id` and the batch seal over its\nrecords — the same seal as a push's (`tree_size` the number of lines, `root` the Merkle\nroot over the records' raw bytes, a `seq` above the key's last). The seal, the key, the\nmandate and its caps (over the file's bytes and records), the certificate, the AI policy\nversion and fair use are checked here; the file is then read once in the background, and\nif its records are not exactly the ones the seal names the import is `failed` with\n`seal_invalid` before any record is checked. Otherwise it is processed as a queued push:\npoll `GET /v1/pushes/{push_id}`. The same request again answers the import's status, and\nresumes one that stopped. Answered `503` with `Retry-After` where bulk import is not available\n(the upload area cannot be written, `reason: staging_unavailable`), and where background\nprocessing cannot be reached (the import is kept: send the same request again).\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/SandboxKey"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "upload_id",
                  "batch_seal"
                ],
                "properties": {
                  "upload_id": {
                    "type": "string",
                    "pattern": "^bup_[0-9a-f]{24}$"
                  },
                  "batch_seal": {
                    "$ref": "#/components/schemas/BatchSealEnvelope"
                  }
                }
              },
              "example": {
                "upload_id": "bup_5f1c0e9a8b7d6c5b4a3f2e1d",
                "batch_seal": {
                  "payloadType": "application/vnd.masterdb.batch-seal.v2+json",
                  "payload": "eyJ2IjoyLCJzZXEiOjQzfQ==",
                  "signatures": [
                    {
                      "keyid": "0aWsmgFfrC73s0FnNjVRKhUR9B_jfREbJn8DnuxdT1g",
                      "sig": "3q2+7w=="
                    }
                  ]
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted; processed in the background. Poll `status_url`.",
            "headers": {
              "Location": {
                "description": "The import's status, `/v1/pushes/{push_id}`.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushStatus"
                },
                "example": {
                  "push_id": "bat_7d3a4e8f9b6c1a2b3c4d5e6f",
                  "batch_id": "bat_7d3a4e8f9b6c1a2b3c4d5e6f",
                  "type": "products",
                  "seq": 42,
                  "source": "bulk",
                  "mode": "queued",
                  "state": "queued",
                  "held": false,
                  "held_reasons": [],
                  "records": 8000,
                  "counts": {
                    "rejected": 3,
                    "pending": 3797,
                    "accepted": 4100,
                    "updated": 100,
                    "held": 0
                  },
                  "progress": {
                    "stage": "split",
                    "chunk": 21,
                    "chunks": 40
                  },
                  "received_at": "2026-10-03T14:02:11.482Z",
                  "updated_at": "2026-10-03T14:04:40.120Z",
                  "completed_at": null,
                  "error": null,
                  "status_url": "/v1/pushes/bat_7d3a4e8f9b6c1a2b3c4d5e6f",
                  "poll_after_seconds": 5
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          }
        }
      }
    },
    "/v1/publish/{type}/withdraw": {
      "post": {
        "operationId": "withdrawRecord",
        "tags": [
          "Publishing"
        ],
        "summary": "Withdraw a record, sealed",
        "description": "Takes a record out of serving with a tiny sealed document `{record_id, action:\nwithdraw, at}` signed by the business — never an HTTP verb on a bare id. The record of\ntruth is never removed and history stays; the published pointer moves and the fan-out\nremoves the rows and mirror documents from every region within seconds.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/SandboxKey"
          },
          {
            "$ref": "#/components/parameters/PublishType"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SealedAction"
              },
              "example": {
                "document_base64": "eyJyZWNvcmRfaWQiOiJtZGJfZHE1am5xYXRuZW1ucWo0ZzN4bWd6Z3BvaWsiLCJhY3Rpb24iOiJ3aXRoZHJhdyJ9",
                "seal": {
                  "payloadType": "application/vnd.masterdb.seal.v2+json",
                  "payload": "eyJ2IjoyfQ==",
                  "signatures": [
                    {
                      "keyid": "0aWsmgFfrC73s0FnNjVRKhUR9B_jfREbJn8DnuxdT1g",
                      "sig": "3q2+7w=="
                    }
                  ]
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/SealedActionResult"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          }
        }
      }
    },
    "/v1/publish/{type}/delete": {
      "post": {
        "operationId": "deleteRecord",
        "tags": [
          "Publishing"
        ],
        "summary": "Delete a record, sealed",
        "description": "Deletes a record with a sealed document `{record_id, action: delete, at}`. Deletion\nmeans deletion: the record leaves serving in seconds and its bytes are purged\nfrom the master copy and backups within 30 days; only its fingerprints — the hashes\nand log leaves — stay, which is what lets the public disavowal check still say when a\nrecord with that hash was live.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/SandboxKey"
          },
          {
            "$ref": "#/components/parameters/PublishType"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SealedAction"
              },
              "example": {
                "document_base64": "eyJyZWNvcmRfaWQiOiJtZGJfZHE1am5xYXRuZW1ucWo0ZzN4bWd6Z3BvaWsiLCJhY3Rpb24iOiJkZWxldGUifQ==",
                "seal": {
                  "payloadType": "application/vnd.masterdb.seal.v2+json",
                  "payload": "eyJ2IjoyfQ==",
                  "signatures": [
                    {
                      "keyid": "0aWsmgFfrC73s0FnNjVRKhUR9B_jfREbJn8DnuxdT1g",
                      "sig": "3q2+7w=="
                    }
                  ]
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/SealedActionResult"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          }
        }
      }
    },
    "/v1/catalogue": {
      "get": {
        "operationId": "listCatalogue",
        "security": [
          {
            "mdbRequestSignature": [
              "mdb-business-read"
            ]
          }
        ],
        "tags": [
          "Catalogue"
        ],
        "summary": "Read back your catalogue manifest",
        "description": "The manifest of what your business has published — ids, your own `business_product_id`,\n`last_updated` and `source` (manual, import or api) — in cursor pages, rate-limited above\n1,000 records. It is how a connector reconciles its own state with MasterDB's; it is\nnot an export, and the only full-record path is the account export in the Business\nPortal.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/SandboxKey"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/RecordType"
            },
            "example": "products"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of the manifest.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogueManifest"
                },
                "example": {
                  "entries": [
                    {
                      "record_id": "mdb_dq5jnqatnemnqj4g3xmgzgpoik",
                      "business_product_id": "TR-5521",
                      "type": "products",
                      "last_updated": "2026-09-30T08:15:00.000Z",
                      "source": "api"
                    }
                  ],
                  "next_cursor": "eyJhZnRlciI6Im1kYl9kcTVqIn0="
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          }
        }
      }
    },
    "/v1/catalogue/{record_id}": {
      "get": {
        "operationId": "getCatalogueRecord",
        "security": [
          {
            "mdbRequestSignature": [
              "mdb-business-read"
            ]
          }
        ],
        "tags": [
          "Catalogue"
        ],
        "summary": "Read back one of your records",
        "description": "One of your own records as stored, by MasterDB's record id or by your own\n`business_product_id` — the bytes you sealed, the seal, the sidecar and where it is\nlive. Only your own business's records are ever returned here.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/SandboxKey"
          },
          {
            "name": "record_id",
            "in": "path",
            "required": true,
            "description": "A MasterDB record id, or your `business_product_id` (URL-encoded).",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 256
            },
            "example": "mdb_dq5jnqatnemnqj4g3xmgzgpoik"
          }
        ],
        "responses": {
          "200": {
            "description": "The record.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CatalogueRecord"
                },
                "example": {
                  "record_id": "mdb_dq5jnqatnemnqj4g3xmgzgpoik",
                  "business_product_id": "TR-5521",
                  "type": "products",
                  "record": {
                    "schema": "masterdb/products/1",
                    "business_product_id": "TR-5521",
                    "product_name": "Ridge Trail Runner"
                  },
                  "seal": {
                    "payloadType": "application/vnd.masterdb.seal.v2+json",
                    "payload": "eyJ2IjoyfQ==",
                    "signatures": [
                      {
                        "keyid": "0aWsmgFfrC73s0FnNjVRKhUR9B_jfREbJn8DnuxdT1g",
                        "sig": "3q2+7w=="
                      }
                    ]
                  },
                  "live_in": [
                    "us-east4"
                  ],
                  "last_updated": "2026-09-30T08:15:00.000Z",
                  "source": "api"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          }
        }
      }
    },
    "/v1/push-attempts": {
      "get": {
        "operationId": "listPushAttempts",
        "security": [
          {
            "mdbRequestSignature": [
              "mdb-business-read"
            ]
          }
        ],
        "tags": [
          "Push attempts"
        ],
        "summary": "Read the ingestion audit",
        "description": "Every row a push tried to publish in a window, with its outcome and reason — a seal\nfailure is its own category, distinct from a validation failure — so a rejected push\nis visible within seconds.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/SandboxKey"
          },
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "accepted",
                "updated",
                "rejected",
                "held",
                "pending"
              ]
            },
            "example": "rejected"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of push attempts, newest first.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PushAttempts"
                },
                "example": {
                  "attempts": [
                    {
                      "batch_id": "bat_7d3a4e8f9b6c",
                      "leaf_index": 1,
                      "received_at": "2026-09-30T08:15:00.000Z",
                      "source": "api",
                      "key_id": "0aWsmgFfrC73s0FnNjVRKhUR9B_jfREbJn8DnuxdT1g",
                      "business_product_id": "TR-5521",
                      "product_name": "Ridge Trail Runner",
                      "outcome": "rejected",
                      "reason": "money_not_string"
                    }
                  ]
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          }
        }
      }
    },
    "/v1/seal-context": {
      "get": {
        "operationId": "getSealContext",
        "security": [
          {
            "mdbRequestSignature": [
              "mdb-business-read"
            ]
          }
        ],
        "tags": [
          "Seal context"
        ],
        "summary": "Read the certificate and the AI policy version a seal must name",
        "parameters": [
          {
            "$ref": "#/components/parameters/SandboxKey"
          }
        ],
        "description": "What the next seal must name: `cert_id`, the business's certificate\nin force (a seal naming any other is refused), and `ai_policy_version`, the business's\nown AI policy version in force — the live generation of its AI policy record, 0 before\none is sealed. A seal binds the version in force at `sealed_at` (seal format 2's\n`ai_policy_version`; format 1 named `terms_version`); an AI policy record's own\nseal names the version it creates, `next_ai_policy_version`. Before this read a pushing\nsystem learned the version only from a refusal (`seal_invalid` with an\n`ai_policy_version` extension). Any live integration key of the business may read it.\n",
        "responses": {
          "200": {
            "description": "The seal context in force now.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SealContext"
                },
                "example": {
                  "business_uuid": "0b7d6c3e-2f4a-4c1b-9d8e-7f6a5b4c3d2e",
                  "cert_id": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
                  "certificate_status": "active",
                  "ai_policy_version": 3,
                  "ai_policy_live_from": "2026-09-15T10:00:00.000Z",
                  "ai_policy_record_id": "aip_abcdefghijklmnopqrstuv",
                  "next_ai_policy_version": 4
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          }
        }
      }
    },
    "/v1/analytics/daily": {
      "get": {
        "operationId": "getBusinessAnalyticsDaily",
        "security": [
          {
            "mdbRequestSignature": [
              "mdb-business-read"
            ]
          }
        ],
        "tags": [
          "Analytics"
        ],
        "summary": "Read your daily figures",
        "description": "Your business's own figures per day, per country and per AI group (one name per group)\n— searches that returned your records, fetches, ad renders, clicks and spend — as at\nthe end of the last complete hour. Never an impression figure MasterDB cannot know,\nnever share of showings.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/From"
          },
          {
            "$ref": "#/components/parameters/To"
          }
        ],
        "responses": {
          "200": {
            "description": "The figures.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BusinessDaily"
                },
                "example": {
                  "as_at": "2026-10-01T14:00:00.000Z",
                  "days": [
                    {
                      "date": "2026-09-30",
                      "country": "US",
                      "ai_group": "Example AI",
                      "searches": 1204,
                      "fetches": 310,
                      "ad_renders": 88,
                      "ad_clicks": 4,
                      "spend_gross": {
                        "amount": "12.40",
                        "currency": "USD"
                      }
                    }
                  ]
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          }
        }
      }
    },
    "/v1/analytics/who-is-asking": {
      "get": {
        "operationId": "getWhoIsAsking",
        "security": [
          {
            "mdbRequestSignature": [
              "mdb-business-read"
            ]
          }
        ],
        "tags": [
          "Analytics"
        ],
        "summary": "See which AI groups retrieved your records",
        "description": "The AI groups that retrieved your business's records over the last 30 days, by name,\nwith counts, country as the axis. It is what the business-side block decision\nis made from.\n",
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/Country"
            },
            "example": "US"
          }
        ],
        "responses": {
          "200": {
            "description": "The groups and their counts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhoIsAsking"
                },
                "example": {
                  "as_at": "2026-10-01T14:00:00.000Z",
                  "window_days": 30,
                  "groups": [
                    {
                      "ai_group_id": "Qm3vT8kLp2XwZ9aB4cDe",
                      "name": "Example AI",
                      "country": "US",
                      "searches": 18231,
                      "fetches": 4410
                    }
                  ]
                }
              }
            }
          },
          "default": {
            "$ref": "#/components/responses/Problem"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "mdbRequestSignature": {
        "type": "apiKey",
        "in": "header",
        "name": "Signature",
        "description": "Every request is signed with RFC 9421 HTTP Message Signatures by a key the caller\nregistered; there is no bearer token. Covered components: `@method`,\n`@authority`, `@path`, `@query` when there is a query string, and `content-digest`\n(RFC 9530, sha-256) when there is a body. Signature parameters: `created`, `expires`\n(at most 300 s after `created`), `nonce` (single use per key within the window),\n`keyid` (the RFC 7638 thumbprint of the public key) and `tag`. The value in a\nsecurity requirement is the `tag` the operation accepts: `mdb-retrieval` for an AI\ncompany's retrieval key, `mdb-push` for a business's integration key under a\npublishing mandate, `mdb-business-read` for a business's reads of its own\ndata — catalogue read-back, push attempts, analytics — authorised by ownership of a\nregistered integration key alone, no mandate (a mandate authorises\npublishing, not reading). Identity comes only from the key; any identifier in a\nbody, query string or header is ignored. The SDKs sign for you.\n"
      }
    },
    "parameters": {
      "PublishType": {
        "name": "type",
        "in": "path",
        "required": true,
        "description": "The record type. Only `products` is published through this route.",
        "schema": {
          "$ref": "#/components/schemas/PathRecordType"
        },
        "example": "products"
      },
      "SandboxKey": {
        "name": "MDB-Sandbox-Key",
        "in": "header",
        "required": false,
        "description": "Sandbox only. The `sandbox_key_grant` the portal answered when the\nkey was taken there: MasterDB's signed statement of the key and its party,\nwhich holds no secret. The sandbox does not know a key taken in the portal\nuntil a request carries its grant: the first signed request with it\ncreates the matching party in the sandbox and registers the key there, and is then\nverified like any other. Send it on every sandbox request: without it the first request\nwith a new key is refused `401` `key_unknown`. A key production has revoked stays refused\nwith its grant. Production ignores the header.\n",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 8192
        },
        "example": "mdb_sbxk1.eyJ2IjoxLCJraW5kIjoicmV0cmlldmFsIn0.c2lnbmF0dXJl"
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "Required on every POST that creates something. 1–255 printable\nASCII characters. The same key with the same request replays the first answer; with a\ndifferent request it is `idempotency_key_reused` (422); while the first is still in\nflight it is `idempotency_in_progress` (409).\n",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 257
        },
        "example": "5f2b8c1e-7d3a-4e8f-9b6c-2a1d0e9f8c7b"
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "required": false,
        "description": "The opaque `next_cursor` of the previous page.",
        "schema": {
          "type": "string",
          "maxLength": 512
        }
      },
      "From": {
        "name": "from",
        "in": "query",
        "required": false,
        "description": "Start of the window, inclusive (RFC 3339 UTC or a date).",
        "schema": {
          "type": "string"
        },
        "example": "2026-10-01T00:00:00Z"
      },
      "To": {
        "name": "to",
        "in": "query",
        "required": false,
        "description": "End of the window, exclusive (RFC 3339 UTC or a date).",
        "schema": {
          "type": "string"
        },
        "example": "2026-10-02T00:00:00Z"
      }
    },
    "responses": {
      "SealedActionResult": {
        "description": "The action was accepted; the fan-out removes the record from every region.",
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "record_id",
                "action",
                "live_in"
              ],
              "properties": {
                "record_id": {
                  "$ref": "#/components/schemas/RecordId"
                },
                "action": {
                  "type": "string",
                  "enum": [
                    "withdraw",
                    "delete"
                  ]
                },
                "live_in": {
                  "type": "array",
                  "description": "Regions still serving the record; empty once every region acknowledged.",
                  "items": {
                    "type": "string"
                  }
                }
              }
            },
            "example": {
              "record_id": "mdb_dq5jnqatnemnqj4g3xmgzgpoik",
              "action": "withdraw",
              "live_in": []
            }
          }
        }
      },
      "Problem": {
        "description": "A refusal or failure, as RFC 9457 problem details with a stable `code`.",
        "headers": {
          "x-request-id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "example": {
              "type": "https://docs.masterdb.ai/errors/sort_required",
              "title": "A sort is required",
              "status": 400,
              "code": "sort_required",
              "detail": "sort_by is required; for relevance order write \"_text_match:desc\"",
              "errors": [
                {
                  "code": "sort_required",
                  "pointer": "/sort_by",
                  "detail": "sort_by is required; for relevance order write \"_text_match:desc\""
                }
              ]
            }
          }
        }
      },
      "RateLimited": {
        "description": "Back-pressure (`rate_limited`): a cap was reached. On the business API the caps are the\nmandate's own — records per hour and bytes per day per key — judged before the body is\nparsed. `Retry-After` says when to try again; the problem's extension\nmembers `retry_after_seconds` (the same number), `cap` (`records_per_hour` or\n`bytes_per_day`) and `limit` say which cap and how much. A push is also held to the\nbusiness's fair use: at most 3 pushes or bulk imports in progress at once\n(`cap: concurrent_pushes`, retry after 60 s) and 250,000 records an hour across all its\nkeys (`cap: business_records_per_hour`, retry at the next hour).\n",
        "headers": {
          "x-request-id": {
            "$ref": "#/components/headers/RequestId"
          },
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "example": {
              "type": "https://docs.masterdb.ai/errors/rate_limited",
              "title": "Too many requests",
              "status": 429,
              "code": "rate_limited",
              "detail": "the mandate allows 100000 records an hour for this key; 100000 used this hour"
            }
          }
        }
      },
      "NotFound": {
        "description": "Not found. On the retrieval API a blocked, withdrawn or absent record all answer this\nsame body, no sooner than 20 ms after arrival.\n",
        "headers": {
          "x-request-id": {
            "$ref": "#/components/headers/RequestId"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "example": {
              "type": "https://docs.masterdb.ai/errors/not_found",
              "title": "Not found",
              "status": 404,
              "code": "not_found"
            }
          }
        }
      }
    },
    "schemas": {
      "PublishBatch": {
        "type": "object",
        "additionalProperties": false,
        "description": "A batch: the batch seal and the records' exact bytes, base64-encoded so that nothing\nbetween the business and the store re-serialises them. Leaf i of the Merkle tree is\nrecord i's raw bytes (RFC 6962 hashing).\n",
        "required": [
          "batch_seal",
          "records"
        ],
        "properties": {
          "batch_seal": {
            "$ref": "#/components/schemas/BatchSealEnvelope"
          },
          "records": {
            "type": "array",
            "minItems": 1,
            "maxItems": 10000,
            "description": "At most 10,000 records and 32 MiB of request body; 50 or fewer are answered inline (200), more are accepted and processed in the background (202).",
            "items": {
              "type": "string",
              "contentEncoding": "base64",
              "maxLength": 204800
            }
          }
        }
      },
      "RecordOutcome": {
        "type": "object",
        "required": [
          "leaf_index",
          "outcome"
        ],
        "properties": {
          "leaf_index": {
            "type": "integer",
            "minimum": 0
          },
          "outcome": {
            "type": "string",
            "description": "`accepted` (a record that was not live), `updated` (a new version of a live one),\n`rejected` (with every reason in `errors`), or `held` — stored in the record of\ntruth but not projected, because the batch tripped the price-shock rule; the owner\nconfirms it in the Business Portal.\n",
            "enum": [
              "accepted",
              "updated",
              "rejected",
              "held"
            ]
          },
          "record_id": {
            "$ref": "#/components/schemas/RecordId"
          },
          "version": {
            "type": "integer",
            "description": "The record's generation — the per-record counter of its publication pointer, the same number the portal shows as the version."
          },
          "sha256": {
            "$ref": "#/components/schemas/Sha256"
          },
          "seal_digest": {
            "$ref": "#/components/schemas/Sha256"
          },
          "errors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FieldError"
            }
          }
        }
      },
      "PublishOutcome": {
        "type": "object",
        "required": [
          "batch_id",
          "seq",
          "held",
          "results"
        ],
        "properties": {
          "batch_id": {
            "type": "string"
          },
          "push_id": {
            "type": "string",
            "description": "The same as `batch_id`; its status is at `status_url`."
          },
          "status_url": {
            "type": "string"
          },
          "seq": {
            "type": "integer"
          },
          "held": {
            "type": "boolean",
            "description": "True when the batch is held for the owner by the price-shock rule (more than 20% of the catalogue's prices moved, any price moved more than 50%, or more than 20% of its listings removed); its records are stored with outcome `held`, and nothing in it is live until they confirm."
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RecordOutcome"
            }
          }
        }
      },
      "BulkUpload": {
        "type": "object",
        "required": [
          "upload_id",
          "record_type",
          "url",
          "fields",
          "content_type",
          "max_bytes",
          "max_records",
          "expires_at"
        ],
        "properties": {
          "upload_id": {
            "type": "string",
            "pattern": "^bup_[0-9a-f]{24}$"
          },
          "record_type": {
            "$ref": "#/components/schemas/RecordType"
          },
          "url": {
            "type": "string",
            "description": "Where to POST the file (`multipart/form-data`)."
          },
          "fields": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "Every form member to send before the file, exactly as given."
          },
          "content_type": {
            "const": "application/x-ndjson"
          },
          "max_bytes": {
            "type": "integer"
          },
          "max_records": {
            "type": "integer"
          },
          "expires_at": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "SealedAction": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "document_base64",
          "seal"
        ],
        "properties": {
          "document_base64": {
            "type": "string",
            "contentEncoding": "base64",
            "description": "The exact bytes of `{\"record_id\": …, \"action\": \"withdraw\" | \"delete\", \"at\": …}`."
          },
          "seal": {
            "$ref": "#/components/schemas/SealEnvelope"
          }
        }
      },
      "CatalogueEntry": {
        "type": "object",
        "required": [
          "record_id",
          "type",
          "last_updated",
          "source"
        ],
        "properties": {
          "record_id": {
            "$ref": "#/components/schemas/RecordId"
          },
          "business_product_id": {
            "type": "string"
          },
          "type": {
            "$ref": "#/components/schemas/RecordType"
          },
          "last_updated": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "source": {
            "type": "string",
            "enum": [
              "manual",
              "import",
              "api"
            ]
          }
        }
      },
      "CatalogueManifest": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Page"
          },
          {
            "type": "object",
            "required": [
              "entries"
            ],
            "properties": {
              "entries": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/CatalogueEntry"
                }
              }
            }
          }
        ]
      },
      "CatalogueRecord": {
        "allOf": [
          {
            "$ref": "#/components/schemas/CatalogueEntry"
          },
          {
            "type": "object",
            "required": [
              "record",
              "seal",
              "live_in"
            ],
            "properties": {
              "record": {
                "type": "object",
                "additionalProperties": true
              },
              "seal": {
                "$ref": "#/components/schemas/RecordSeal"
              },
              "sidecar": {
                "$ref": "#/components/schemas/Envelope"
              },
              "live_in": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          }
        ]
      },
      "SealContext": {
        "type": "object",
        "required": [
          "business_uuid",
          "cert_id",
          "certificate_status",
          "ai_policy_version",
          "ai_policy_live_from",
          "ai_policy_record_id",
          "next_ai_policy_version"
        ],
        "properties": {
          "business_uuid": {
            "$ref": "#/components/schemas/Uuid"
          },
          "cert_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The certificate in force (`sha256:` of its payload); null before the business is verified."
          },
          "certificate_status": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "active",
              "suspended",
              "closed",
              "revoked",
              "withdrawn",
              null
            ],
            "description": "The status of the certificate in force; a seal is accepted only while it is `active` (`withdrawn` is refused as `party_not_verified`)."
          },
          "ai_policy_version": {
            "type": "integer",
            "minimum": 0,
            "description": "The business's AI policy version in force; 0 before an AI policy record is sealed."
          },
          "ai_policy_live_from": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "ai_policy_record_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "The AI policy record's id (`aip_…`; `trm_…` for one sealed under the earlier name)."
          },
          "next_ai_policy_version": {
            "type": "integer",
            "minimum": 1,
            "description": "What a new AI policy record's own seal names."
          }
        }
      },
      "PushAttempts": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Page"
          },
          {
            "type": "object",
            "required": [
              "attempts"
            ],
            "properties": {
              "attempts": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "batch_id",
                    "leaf_index",
                    "received_at",
                    "source",
                    "key_id",
                    "outcome"
                  ],
                  "properties": {
                    "batch_id": {
                      "type": "string"
                    },
                    "leaf_index": {
                      "type": "integer"
                    },
                    "received_at": {
                      "$ref": "#/components/schemas/Timestamp"
                    },
                    "source": {
                      "type": "string",
                      "description": "How the row arrived (product contract `business_product_push_events`). This audit is the pushes', so always `api` here; the portal's read carries the import rows too.",
                      "enum": [
                        "api",
                        "import"
                      ]
                    },
                    "key_id": {
                      "$ref": "#/components/schemas/KeyId"
                    },
                    "record_id": {
                      "$ref": "#/components/schemas/RecordId"
                    },
                    "business_product_id": {
                      "type": "string",
                      "description": "The business's own id, as submitted — present on a rejection too."
                    },
                    "product_name": {
                      "type": "string",
                      "description": "Absent where the record was rejected before a name could be read."
                    },
                    "outcome": {
                      "type": "string",
                      "description": "`held`: stored, not published — the price-shock rule holds the push for the owner.\n`pending`: the record passed every check and its push has not yet settled it — written\nbefore any record of the push is stored. A row still `pending` after its push answered,\nor after a push that never answered, was not published by it; sending the exact batch\nagain finishes it.\n",
                      "enum": [
                        "accepted",
                        "updated",
                        "rejected",
                        "held",
                        "pending"
                      ]
                    },
                    "reason": {
                      "$ref": "#/components/schemas/ErrorCode"
                    }
                  }
                }
              }
            }
          }
        ]
      },
      "BusinessDaily": {
        "type": "object",
        "required": [
          "as_at",
          "days"
        ],
        "properties": {
          "as_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "days": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "date",
                "country",
                "ai_group"
              ],
              "properties": {
                "date": {
                  "type": "string",
                  "format": "date"
                },
                "country": {
                  "$ref": "#/components/schemas/Country"
                },
                "ai_group": {
                  "type": "string",
                  "description": "The AI group, by name."
                },
                "searches": {
                  "type": "integer"
                },
                "fetches": {
                  "type": "integer"
                },
                "ad_renders": {
                  "type": "integer"
                },
                "ad_clicks": {
                  "type": "integer"
                },
                "spend_gross": {
                  "$ref": "#/components/schemas/UsdAmount"
                }
              }
            }
          }
        }
      },
      "WhoIsAsking": {
        "type": "object",
        "required": [
          "as_at",
          "window_days",
          "groups"
        ],
        "properties": {
          "as_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "window_days": {
            "type": "integer"
          },
          "groups": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "ai_group_id",
                "name"
              ],
              "properties": {
                "ai_group_id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "country": {
                  "$ref": "#/components/schemas/Country"
                },
                "searches": {
                  "type": "integer"
                },
                "fetches": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "PathRecordType": {
        "type": "string",
        "description": "The five published types as they appear in a path.",
        "enum": [
          "products",
          "business-files",
          "events",
          "jobs",
          "updates"
        ]
      },
      "KeyId": {
        "type": "string",
        "description": "The RFC 7638 JWK thumbprint of a public key, base64url, 43 characters.",
        "pattern": "^[A-Za-z0-9_-]{43}$"
      },
      "Sha256": {
        "type": "string",
        "description": "A SHA-256 digest, `sha256:` + 64 lower-case hex.",
        "pattern": "^sha256:[0-9a-f]{64}$"
      },
      "Timestamp": {
        "type": "string",
        "description": "RFC 3339 UTC with milliseconds, e.g. 2026-09-23T14:02:11.482Z.",
        "format": "date-time"
      },
      "BatchSealPayload": {
        "type": "object",
        "description": "A Path A batch seal, format 2 (`batch-seal.v2`; format 1 names `terms_version` and is still accepted). `seq` is the per-key anti-rollback counter; `tree_size` comes from here, never from a proof.",
        "required": [
          "v",
          "key_id",
          "cert_id",
          "root",
          "tree_size",
          "seq",
          "sealed_at",
          "record_type",
          "ai_policy_version"
        ],
        "properties": {
          "v": {
            "const": 2
          },
          "key_id": {
            "$ref": "#/components/schemas/KeyId"
          },
          "cert_id": {
            "type": "string"
          },
          "root": {
            "$ref": "#/components/schemas/Sha256"
          },
          "tree_size": {
            "type": "integer",
            "minimum": 1
          },
          "seq": {
            "type": "integer",
            "minimum": 0
          },
          "sealed_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "record_type": {
            "type": "string"
          },
          "ai_policy_version": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "EnvelopeSignature": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "keyid",
          "sig"
        ],
        "properties": {
          "keyid": {
            "$ref": "#/components/schemas/KeyId"
          },
          "sig": {
            "type": "string",
            "contentEncoding": "base64",
            "description": "The signature, base64. ES256 is raw `r || s` (64 bytes); a WebAuthn assertion's signature stays DER."
          },
          "authenticatorData": {
            "type": "string",
            "contentEncoding": "base64",
            "description": "A passkey signature only — the WebAuthn authenticator data."
          },
          "clientDataJSON": {
            "type": "string",
            "contentEncoding": "base64",
            "description": "A passkey signature only — the WebAuthn client data, whose challenge is `\"mdb-seal\" || SHA-256(PAE(payloadType, payload))`."
          }
        }
      },
      "Signatures": {
        "type": "array",
        "description": "One or two signatures over PAE(payloadType, payload) — the classical one and, for long-lived artefacts, the ML-DSA-65 one in the second slot.",
        "minItems": 1,
        "maxItems": 2,
        "items": {
          "$ref": "#/components/schemas/EnvelopeSignature"
        }
      },
      "BatchSealEnvelope": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "payloadType",
          "payload",
          "signatures"
        ],
        "properties": {
          "payloadType": {
            "type": "string",
            "enum": [
              "application/vnd.masterdb.batch-seal.v2+json",
              "application/vnd.masterdb.batch-seal.v1+json"
            ]
          },
          "payload": {
            "type": "string",
            "contentEncoding": "base64",
            "contentMediaType": "application/json",
            "contentSchema": {
              "$ref": "#/components/schemas/BatchSealPayload"
            }
          },
          "signatures": {
            "$ref": "#/components/schemas/Signatures"
          }
        }
      },
      "ErrorCode": {
        "type": "string",
        "description": "The stable, machine-readable reason. A code, once published, is never renamed or reused; callers branch on it. `x-masterdb-status` gives the HTTP status each code is returned with when it is a refusal.",
        "enum": [
          "sort_required",
          "filter_required",
          "country_required",
          "unknown_field",
          "operator_not_allowed",
          "sort_not_allowed",
          "value_invalid",
          "limit_exceeded",
          "collection_unknown",
          "request_invalid",
          "signature_missing",
          "signature_invalid",
          "signature_expired",
          "key_unknown",
          "nonce_reused",
          "digest_mismatch",
          "no_grant",
          "permission_denied",
          "grant_expired",
          "grant_deactivated",
          "party_not_verified",
          "party_suspended",
          "party_held",
          "party_not_funded",
          "admin_hold",
          "passkey_required",
          "device_bound_required",
          "invitation_invalid",
          "invitation_email_mismatch",
          "domain_claimed",
          "assembly_pending",
          "agreement_required",
          "challenge_invalid",
          "registration_invalid",
          "assertion_invalid",
          "passkey_test_failed",
          "credential_unknown",
          "credential_exists",
          "mint_assertion_missing",
          "session_invalid",
          "record_invalid",
          "json_invalid",
          "record_too_large",
          "duplicate_key",
          "depth_exceeded",
          "string_too_long",
          "too_many_keys",
          "control_character",
          "zero_width_character",
          "bidi_override",
          "not_nfc",
          "invalid_utf8",
          "bom_present",
          "number_invalid",
          "money_not_string",
          "money_invalid",
          "schema_missing",
          "schema_invalid",
          "not_canonical",
          "seal_invalid",
          "seal_key_unknown",
          "seal_payload_type",
          "seal_hash_mismatch",
          "seal_time_skew",
          "seq_not_increasing",
          "price_country_not_published",
          "unsafe_url",
          "field_required",
          "plain_text_required",
          "role_address_required",
          "personal_data",
          "country_invalid",
          "currency_invalid",
          "language_invalid",
          "vocabulary_invalid",
          "seal_required",
          "mandate_required",
          "mandate_scope",
          "draft_revision_conflict",
          "scope_violation",
          "url_flagged",
          "display_domain_mismatch",
          "image_type_refused",
          "image_invalid",
          "source_not_allowed",
          "domain_unproven",
          "verification_level_insufficient",
          "screening_not_passed",
          "verification_locked",
          "feature_not_enabled",
          "prf_unsupported",
          "budget_exhausted",
          "window_expired",
          "token_invalid",
          "token_reused",
          "allowance_exhausted",
          "idempotency_key_missing",
          "idempotency_key_invalid",
          "idempotency_key_reused",
          "idempotency_in_progress",
          "unauthenticated",
          "step_up_required",
          "forbidden",
          "not_found",
          "conflict",
          "rate_limited",
          "internal",
          "not_implemented",
          "unavailable"
        ],
        "x-enumDescriptions": {
          "sort_required": "A sort is required",
          "filter_required": "A filter naming exactly one country is required",
          "country_required": "A country is required",
          "unknown_field": "Field not allowed for this collection",
          "operator_not_allowed": "Operator not allowed for this field",
          "sort_not_allowed": "Sort key not allowed for this collection",
          "value_invalid": "Value is not valid for this field",
          "limit_exceeded": "Limit exceeds the maximum",
          "collection_unknown": "Unknown collection",
          "request_invalid": "Request is not valid",
          "signature_missing": "Request is not signed",
          "signature_invalid": "Request signature is not valid",
          "signature_expired": "Request signature is outside its validity window",
          "key_unknown": "Signing key is not registered or not live",
          "nonce_reused": "Nonce has already been used",
          "digest_mismatch": "Content-Digest does not match the body",
          "no_grant": "You hold no grant on this party",
          "permission_denied": "Your roles on this party do not include this action",
          "grant_expired": "Your access to this party has expired",
          "grant_deactivated": "Your access to this party is deactivated",
          "party_not_verified": "The party must be verified for this action",
          "party_suspended": "The party is suspended",
          "party_held": "The party is on hold: its records stay live, new publishing is paused",
          "party_not_funded": "The party has no funds for this action",
          "admin_hold": "A new admin cannot change grants, keys or mandates for 24 hours",
          "passkey_required": "This action requires a passkey",
          "device_bound_required": "This party requires a device-bound passkey for sealing",
          "invitation_invalid": "Invitation is not valid",
          "invitation_email_mismatch": "Sign in with the email address the invitation was sent to",
          "domain_claimed": "This email domain belongs to an existing party",
          "assembly_pending": "This AI company's setup is not complete",
          "agreement_required": "The AI-company Terms in force must be accepted first",
          "challenge_invalid": "Challenge is unknown, expired or already used",
          "registration_invalid": "Passkey registration is not valid",
          "assertion_invalid": "Passkey assertion is not valid",
          "passkey_test_failed": "The new passkey failed its test signature and was not saved",
          "credential_unknown": "Passkey is not registered or has been revoked",
          "credential_exists": "Passkey is already registered",
          "mint_assertion_missing": "Sign-in token has no recent mint assertion",
          "session_invalid": "The session is not bound to a live MasterDB sign-in; sign in again",
          "record_invalid": "Record is not valid",
          "json_invalid": "Body is not one strict JSON value",
          "record_too_large": "Record is too large",
          "duplicate_key": "Object has a duplicate key",
          "depth_exceeded": "Nesting is too deep",
          "string_too_long": "String is too long",
          "too_many_keys": "Object has too many keys",
          "control_character": "String contains a control character",
          "zero_width_character": "String contains a zero-width space or U+FEFF",
          "bidi_override": "String contains a bidirectional override",
          "not_nfc": "String is not in Unicode Normalization Form C",
          "invalid_utf8": "Body is not valid UTF-8",
          "bom_present": "Body starts with a byte-order mark",
          "number_invalid": "Number is outside the range every parser agrees on",
          "money_not_string": "Money must be a decimal string",
          "money_invalid": "Money string is not a valid decimal",
          "schema_missing": "Record has no top-level schema field",
          "schema_invalid": "Record schema field is not valid",
          "not_canonical": "Bytes are not in the canonical form",
          "seal_invalid": "Seal does not verify",
          "seal_key_unknown": "Seal names a key that is not registered",
          "seal_payload_type": "Envelope carries the wrong payload type",
          "seal_hash_mismatch": "Seal hash does not match the record bytes",
          "seal_time_skew": "sealed_at is too far from the time of receipt",
          "seq_not_increasing": "Batch sequence number is not greater than the last accepted",
          "price_country_not_published": "A price names a country the record is not published in",
          "unsafe_url": "URL points at a private or unsafe address",
          "field_required": "A required field is missing",
          "plain_text_required": "Text must be plain text",
          "role_address_required": "A published contact must be a role address, not a person",
          "personal_data": "Freeform text must not carry personal data",
          "country_invalid": "Not a country code in the platform vocabulary",
          "currency_invalid": "Not a currency code in the platform vocabulary",
          "language_invalid": "Not a language in the platform vocabulary",
          "vocabulary_invalid": "Value is not in the controlled vocabulary",
          "seal_required": "A seal is required",
          "mandate_required": "The signing key has no live publishing mandate",
          "mandate_scope": "The mandate does not cover this record type or country",
          "draft_revision_conflict": "The draft has changed since you read it",
          "scope_violation": "Text names another company or brand, or directs how other sources are treated",
          "url_flagged": "URL is flagged as unsafe",
          "display_domain_mismatch": "display_domain is not the destination host",
          "image_type_refused": "Only JPEG, PNG and WebP images are accepted",
          "image_invalid": "Image could not be decoded within the limits",
          "source_not_allowed": "The request comes from outside the mandate’s source allow-list",
          "domain_unproven": "An endpoint domain has no live proof of control",
          "verification_level_insufficient": "This action is not available to this party until its verification is complete: finish it, then try again",
          "screening_not_passed": "A check this action needs has not passed: try again later, and if it still has not passed, get in touch with us",
          "verification_locked": "Locked while verification is submitted or decided",
          "feature_not_enabled": "This feature is not enabled",
          "prf_unsupported": "The passkey does not support the PRF extension",
          "budget_exhausted": "Budget exhausted",
          "window_expired": "Confirmation window has expired",
          "token_invalid": "Token is not valid",
          "token_reused": "Token has already been confirmed",
          "allowance_exhausted": "Query allowance exhausted",
          "idempotency_key_missing": "Idempotency-Key header is required",
          "idempotency_key_invalid": "Idempotency-Key header is not valid",
          "idempotency_key_reused": "Idempotency-Key was used with a different request",
          "idempotency_in_progress": "A request with this Idempotency-Key is in progress",
          "unauthenticated": "Not signed in",
          "step_up_required": "A stronger sign-in is required for this action",
          "forbidden": "Not permitted",
          "not_found": "Not found",
          "conflict": "Conflict",
          "rate_limited": "Too many requests",
          "internal": "Internal error",
          "not_implemented": "Not implemented",
          "unavailable": "Temporarily unavailable"
        }
      },
      "FieldError": {
        "type": "object",
        "description": "One reason among several: a request or record that fails several checks is answered with every reason at once.",
        "additionalProperties": false,
        "required": [
          "code",
          "pointer",
          "detail"
        ],
        "properties": {
          "code": {
            "$ref": "#/components/schemas/ErrorCode"
          },
          "pointer": {
            "type": "string",
            "description": "JSON Pointer (RFC 6901) into the request or record; \"\" is the whole document."
          },
          "detail": {
            "type": "string"
          }
        }
      },
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details, the one error shape on every MasterDB API. `type` is the documentation page of `code`. Extension members may appear; they never shadow the standard ones.",
        "required": [
          "type",
          "title",
          "status",
          "code"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "`https://docs.masterdb.ai/errors/{code}`"
          },
          "title": {
            "type": "string",
            "description": "The code's human title; may be reworded, never branch on it."
          },
          "status": {
            "type": "integer",
            "minimum": 400,
            "maximum": 599
          },
          "code": {
            "$ref": "#/components/schemas/ErrorCode"
          },
          "detail": {
            "type": "string"
          },
          "instance": {
            "type": "string",
            "description": "The request path, or the request id."
          },
          "errors": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/FieldError"
            }
          }
        }
      },
      "RecordId": {
        "type": "string",
        "description": "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).",
        "pattern": "^(?:mdb_[a-z2-7]{26}|(?:bf|evt|job|upd|ad|aip|frm|trm)_[a-z2-7]{22})$"
      },
      "PushId": {
        "type": "string",
        "description": "A push (or bulk import) — the same id as its `batch_id`.",
        "pattern": "^bat_[0-9a-f]{24}$",
        "example": "bat_7d3a4e8f9b6c1a2b3c4d5e6f"
      },
      "RecordType": {
        "type": "string",
        "description": "The five published types, as collection names.",
        "enum": [
          "products",
          "business_files",
          "events",
          "jobs",
          "updates"
        ]
      },
      "PushCounts": {
        "type": "object",
        "description": "How many of the push's records have each outcome so far. `pending` is every record not yet\nsettled; when the push is `complete` it is 0 and the rest add up to `records`.\n",
        "required": [
          "rejected",
          "pending",
          "accepted",
          "updated",
          "held"
        ],
        "properties": {
          "rejected": {
            "type": "integer",
            "minimum": 0
          },
          "pending": {
            "type": "integer",
            "minimum": 0
          },
          "accepted": {
            "type": "integer",
            "minimum": 0
          },
          "updated": {
            "type": "integer",
            "minimum": 0
          },
          "held": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "PushStatus": {
        "type": "object",
        "description": "A push accepted then processed: its totals and where its processing is. `state`\nmoves `queued` → `processing` → `complete` (or `held`, then `confirming` → `confirmed`\nonce an owner confirms); `failed` means it stopped on an error it cannot get past by\nitself (`error` says which) — what it settled stays settled, and sending the exact batch\nagain (or, for a held push, confirming again) resumes it where it stopped.\n",
        "required": [
          "push_id",
          "batch_id",
          "type",
          "seq",
          "source",
          "mode",
          "state",
          "held",
          "held_reasons",
          "records",
          "counts",
          "progress",
          "received_at",
          "updated_at",
          "completed_at",
          "error",
          "status_url"
        ],
        "properties": {
          "push_id": {
            "$ref": "#/components/schemas/PushId"
          },
          "batch_id": {
            "$ref": "#/components/schemas/PushId"
          },
          "type": {
            "$ref": "#/components/schemas/RecordType"
          },
          "seq": {
            "type": "integer"
          },
          "source": {
            "type": "string",
            "enum": [
              "api",
              "bulk"
            ],
            "description": "`api`: a push's own body; `bulk`: an uploaded bulk file."
          },
          "mode": {
            "type": "string",
            "enum": [
              "inline",
              "queued"
            ],
            "description": "`inline`: processed inside the push request (small pushes); `queued`: in the background, a chunk at a time."
          },
          "state": {
            "type": "string",
            "enum": [
              "queued",
              "processing",
              "complete",
              "held",
              "confirming",
              "confirmed",
              "failed"
            ]
          },
          "held": {
            "type": "boolean"
          },
          "held_reasons": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "records": {
            "type": "integer",
            "minimum": 1
          },
          "counts": {
            "$ref": "#/components/schemas/PushCounts"
          },
          "progress": {
            "type": "object",
            "required": [
              "stage",
              "chunk",
              "chunks"
            ],
            "description": "The stage running and the chunk it is on (a chunk is at most 200 records). Each chunk is checked, then each is published.",
            "properties": {
              "stage": {
                "type": "string",
                "enum": [
                  "split",
                  "check",
                  "commit",
                  "finish",
                  "confirm",
                  "confirm_finish",
                  "done",
                  "failed"
                ]
              },
              "chunk": {
                "type": "integer",
                "minimum": 0
              },
              "chunks": {
                "type": "integer",
                "minimum": 0
              }
            }
          },
          "received_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "updated_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "error": {
            "type": [
              "object",
              "null"
            ],
            "required": [
              "code",
              "detail"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "detail": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "status_url": {
            "type": "string",
            "description": "Where to read this status (`GET /v1/pushes/{push_id}`)."
          },
          "poll_after_seconds": {
            "type": "integer",
            "description": "Present while the push is still moving — how long to wait before reading the status again."
          },
          "stalled": {
            "type": "boolean",
            "enum": [
              true
            ],
            "description": "Present, `true`, when no step of the push has completed for ten minutes — its background task may have been dropped after the queue's retries. `resume` says what to send. Absent while the push is moving, and once it is `complete`, `held` or `failed`."
          },
          "resume": {
            "type": "string",
            "description": "Present with `stalled`. The instruction to resume the push — send the exact batch again (a bulk import, the same import request again)."
          }
        }
      },
      "Page": {
        "type": "object",
        "description": "A cursor page. `next_cursor` is absent on the last page.",
        "properties": {
          "next_cursor": {
            "type": "string"
          }
        }
      },
      "PushRecordResult": {
        "type": "object",
        "description": "One record of a push, by leaf index. `pending` until its chunk is checked and published.",
        "required": [
          "leaf_index",
          "outcome"
        ],
        "properties": {
          "leaf_index": {
            "type": "integer",
            "minimum": 0
          },
          "outcome": {
            "type": "string",
            "enum": [
              "accepted",
              "updated",
              "rejected",
              "held",
              "pending"
            ]
          },
          "record_id": {
            "type": "string"
          },
          "business_product_id": {
            "type": "string"
          },
          "product_name": {
            "type": "string"
          },
          "version": {
            "type": "integer"
          },
          "sha256": {
            "type": "string"
          },
          "seal_digest": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FieldError"
            }
          }
        }
      },
      "PushStatusPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/PushStatus"
          },
          {
            "$ref": "#/components/schemas/Page"
          },
          {
            "type": "object",
            "required": [
              "results"
            ],
            "properties": {
              "results": {
                "type": "array",
                "maxItems": 100,
                "items": {
                  "$ref": "#/components/schemas/PushRecordResult"
                }
              }
            }
          }
        ]
      },
      "SealPayload": {
        "type": "object",
        "description": "A record's seal, format 2 (`seal.v2`). `hash` is over the exact bytes stored;\n`sealed_at` is inside the signed payload; `ai_policy_version` is the business's AI policy\nversion in force at `sealed_at` (an AI policy record's own seal: the version it creates).\nFormat 1 (`seal.v1`: `v` 1 and `terms_version`) is still verified and,\nstill accepted from a pushing system.\n",
        "required": [
          "v",
          "key_id",
          "cert_id",
          "hash",
          "sealed_at",
          "record_type",
          "ai_policy_version"
        ],
        "properties": {
          "v": {
            "const": 2
          },
          "key_id": {
            "$ref": "#/components/schemas/KeyId"
          },
          "cert_id": {
            "type": "string"
          },
          "hash": {
            "$ref": "#/components/schemas/Sha256"
          },
          "sealed_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "record_type": {
            "type": "string"
          },
          "ai_policy_version": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "SealEnvelope": {
        "description": "A Path B seal (one record, sealed by a person's passkey). Format 2 (`seal.v2`); format 1 (`seal.v1`) is still verified.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "payloadType",
          "payload",
          "signatures"
        ],
        "properties": {
          "payloadType": {
            "type": "string",
            "enum": [
              "application/vnd.masterdb.seal.v2+json",
              "application/vnd.masterdb.seal.v1+json"
            ]
          },
          "payload": {
            "type": "string",
            "contentEncoding": "base64",
            "contentMediaType": "application/json",
            "contentSchema": {
              "$ref": "#/components/schemas/SealPayload"
            }
          },
          "signatures": {
            "$ref": "#/components/schemas/Signatures"
          }
        }
      },
      "BatchRecordSeal": {
        "type": "object",
        "description": "What a Path A record's seal holds: the batch envelope, the record's leaf index\nand its inclusion proof (RFC 6962 hashing, `0x00` leaf and `0x01` node prefixes; the\nleaf is the record's raw bytes), so the record verifies on its own.\n",
        "additionalProperties": false,
        "required": [
          "envelope",
          "leaf_index",
          "proof"
        ],
        "properties": {
          "envelope": {
            "$ref": "#/components/schemas/BatchSealEnvelope"
          },
          "leaf_index": {
            "type": "integer",
            "minimum": 0
          },
          "proof": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Sha256"
            }
          }
        }
      },
      "RecordSeal": {
        "description": "A record's seal as stored and served — a Path B seal envelope or a Path A batch member.",
        "oneOf": [
          {
            "$ref": "#/components/schemas/SealEnvelope"
          },
          {
            "$ref": "#/components/schemas/BatchRecordSeal"
          }
        ]
      },
      "Envelope": {
        "type": "object",
        "description": "A DSSE envelope. One or two signatures: the classical one and, for long-lived\nartefacts, the ML-DSA-65 one in the second slot. A verifier always states\nwhich `payloadType` it expects.\n",
        "additionalProperties": false,
        "required": [
          "payloadType",
          "payload",
          "signatures"
        ],
        "properties": {
          "payloadType": {
            "type": "string",
            "pattern": "^[\\x21-\\x7e]{1,256}$"
          },
          "payload": {
            "type": "string",
            "contentEncoding": "base64"
          },
          "signatures": {
            "$ref": "#/components/schemas/Signatures"
          }
        }
      },
      "Uuid": {
        "type": "string",
        "description": "A lower-case UUIDv4.",
        "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
      },
      "Country": {
        "type": "string",
        "description": "ISO 3166-1 alpha-2, from the platform vocabulary.",
        "pattern": "^[A-Z]{2}$"
      },
      "Money": {
        "type": "string",
        "description": "A decimal string, never a float: at most 15 integer digits and 6 decimal places.",
        "pattern": "^(?:0|[1-9][0-9]{0,14})(?:\\.[0-9]{1,6})?$"
      },
      "UsdAmount": {
        "type": "object",
        "description": "An amount in US dollars — MasterDB's own billing is USD only.",
        "required": [
          "amount",
          "currency"
        ],
        "properties": {
          "amount": {
            "$ref": "#/components/schemas/Money"
          },
          "currency": {
            "const": "USD"
          }
        }
      }
    },
    "headers": {
      "RequestId": {
        "description": "The request's id in MasterDB's logs (the `retrieval_id` on the retrieval API). Quote it to support.",
        "schema": {
          "type": "string"
        }
      },
      "RetryAfter": {
        "description": "Seconds until the request may succeed (RFC 9110); the same number as the problem's `retry_after_seconds`.",
        "schema": {
          "type": "integer",
          "minimum": 1
        }
      }
    }
  }
}