Skip to content

Quickstart for AI companies

  1. Make a key. An Ed25519 key pair, made where it will live. The private half never leaves your systems; MasterDB only ever sees the public half.

    Terminal window
    openssl genpkey -algorithm ed25519 -out retrieval-key.pem
    openssl pkey -in retrieval-key.pem -pubout -out retrieval-key.pub.pem
  2. Take a sandbox key in the AI Portal. Someone with the owner, admin or integration_manager role, signed in with a passkey, registers the public half of the key as a JWK, with a label. A sandbox key needs no verification and no AI-company Terms. See The sandbox for what the portal needs, and Keys.

    Terminal window
    node -e "const c=require('node:crypto'),f=require('node:fs');console.log(JSON.stringify(c.createPublicKey(f.readFileSync('retrieval-key.pub.pem')).export({format:'jwk'})))"

    The answer names the key’s id (the RFC 7638 thumbprint of the public JWK) and carries a sandbox_key_grant (mdb_sbxk1.…). Keep the grant: the sandbox does not know your key until a request carries it in the MDB-Sandbox-Key header. The grant holds no secret, and the list of your sandbox keys returns it again.

  3. Install the SDK and the verifier.

    Terminal window
    npm install @masterdb/client @masterdb/verifier # TypeScript, Node 24 or later
    pip install httpx masterdb-verifier # Python 3.10 or later

    In Python, requests are signed by one small file, masterdb_signing.py, which the Python samples import. See Signing requests.

  4. Search, then fetch. Every request is signed; every search names one collection, exactly one country, and a sort.

    samples/typescript/quickstart.ts
    // Quickstart: one signed search and one fetch against the sandbox.
    //
    // MASTERDB_KEY_FILE your retrieval key's private half (PKCS #8 PEM); its public half is the sandbox key you took in the AI Portal
    // MASTERDB_SANDBOX_KEY_GRANT optional; that key's sandbox_key_grant (mdb_sbxk1.…), needed until the sandbox has seen the key once
    // MASTERDB_API_URL optional; the sandbox by default
    import assert from 'node:assert/strict';
    import { createPrivateKey } from 'node:crypto';
    import { readFileSync } from 'node:fs';
    import { SANDBOX, createEd25519Signer, createRetrievalClient } from '@masterdb/client';
    const signer = createEd25519Signer(createPrivateKey(readFileSync(process.env.MASTERDB_KEY_FILE as string)));
    const sandboxKeyGrant = process.env.MASTERDB_SANDBOX_KEY_GRANT;
    const client = createRetrievalClient({ baseUrl: process.env.MASTERDB_API_URL ?? SANDBOX.retrieval, signer, ...(sandboxKeyGrant ? { sandboxKeyGrant } : {}) });
    // One collection, exactly one country, and a sort you choose: MasterDB never picks an order for you.
    const search = await client.POST('/v1/search', {
    body: {
    collection: 'products',
    q: 'rook',
    query_by: ['product_name'],
    filter: { all: [{ country: 'US' }, { availability: 'available' }] },
    sort_by: 'price_amount:asc',
    limit: 5,
    },
    });
    if (search.error) throw new Error(`search refused: ${search.error.code} ${search.error.detail ?? ''}`);
    for (const row of search.data.rows) {
    console.log(row.record_id, row['product_name'], row['price_US'], row['price_currency_US']);
    }
    assert.ok(search.data.rows.length > 0, 'the sandbox corpus has products in the US');
    assert.ok(search.data.receipt, 'every search carries a signed receipt');
    // Fetch the first row's full record: the bytes exactly as the business sealed them, the seal, and its AI policy in force.
    const first = search.data.rows[0] as (typeof search.data.rows)[number];
    const fetched = await client.GET('/v1/records/{record_id}', { params: { path: { record_id: first.record_id } } });
    if (fetched.error) throw new Error(`fetch refused: ${fetched.error.code}`);
    console.log(fetched.data.type, fetched.data.record['product_name'], 'AI policy version', fetched.data.ai_policy.version);
    assert.equal(fetched.data.record_id, first.record_id);

    Run it with MASTERDB_KEY_FILE=retrieval-key.pem and MASTERDB_SANDBOX_KEY_GRANT set to the grant from step 2. The first request that carries the grant registers your key in the sandbox; without it that request is refused 401 key_unknown. The TypeScript SDK sends the grant for you (sandboxKeyGrant), and so does the Python signing helper (MasterDBAuth(key, sandbox_key_grant=…)). Once the key is registered in the sandbox the grant is no longer needed.

A search answers at most 50 rows and a receipt. A row is a short, signed projection of one record: its id, its business, its origin hash, the fields of its collection (for a product, a price for each country it is published in, such as price_US and price_currency_US), and ai_policy_bits — the bits saying what that business permits and the contexts it blocks. The receipt is MasterDB’s signed statement of what it served you.

A fetch answers the record exactly as the business sealed it, the seal, MasterDB’s signed sidecar, the business’s sealed AI policy in force, provenance (where to find its certificate, which projection made its rows, its log leaf) and a receipt.

  • Search: queries, filters, sorts, the five collections.
  • Verify: check a record, a row and a receipt without trusting the response.
  • AI policy: what each business permits and the contexts it blocks, and how to honour it.
  • Rate limits and errors.