Data governance
Open in
Data governance says what each field holds, who answers for it, and whether it is masked, logged, sent to a model, kept or erased.
The Customer decides; the product finds, holds and erases, and every upstream product hears it. Filled: what the person and the Customer see.
What each field is, and who answers for it
A data class on a field changes what every part of the product does with it. Nothing else in the file has to say so.
| Family | What it does |
|---|---|
| Data classes | class on a field: personal, sensitive, payment, health or privileged; Model and records types it, and the one decision reads it |
| Roles for the data | Each Customer is the controller of its own records, you are its processor, and APIs.Dev is yours; you control your own sales record and account data |
| The DPA | A data processing agreement generated per product from the file: the classes it holds, its regions, retention and sub-processors, versioned and accepted like any agreement |
| Sub-processors | APIs.Dev, Stripe, each model provider the router may use, and each upstream product with its own list, generated and printed beside the terms |
| Subject requests | A person asks to find, export, correct or erase what the product holds about them; the Customer decides, and the product does it across every record |
| Retention | Per Noun and per class, deleting on schedule unless a legal hold stops it; history keeps that a value existed, never the value |
| Customer-held keys | On its own isolation, a Customer holds the key to its Namespace in its own key service; revoking it leaves the records unreadable |
| The model path | Per class: allow, redact (tokens in, values restored after) or refuse; only providers that keep nothing, and never training on a Customer's data |
| The audit log | Every change, and every read of a sensitive, health or privileged field, as a projection each Customer queries and streams to its own SIEM |
| The data chain | What each hop of composition carries, under which licence, residency and processor terms; an erasure follows it upstream |
| Class | Masked for | Logs and traces | The model path | Edge cache and export |
|---|---|---|---|---|
personal | Roles without see on its Noun | Redacted | As privacy.models says | Never cached; exported to its Customer |
sensitive | The same, and encrypted per Namespace | Redacted | redact unless the file allows it | Never cached; exported to its Customer |
payment | Everyone: only Stripe holds the number | Never written | refuse | Last four digits only |
health | The same as sensitive, and every read audited | Redacted | refuse unless the provider signs for health data | Never cached; exported with its audit |
privileged | Everyone outside the case's wall | Redacted | Only inside the case, kept in no memory | Exported only by a person with the case's Role |
Example
A contact's email is personal, the notes are sensitive, the product acts as each Customer's processor, and the model router redacts both.
import { define } from 'apis.dev'
/** Deals for each Customer, kicked off when won. */
export default define({
name: 'pipeline', domain: 'pipeline.apis.dev',
Company: { name: 'string', domain: 'url!#', deals: '<-Deal.company' },
Deal: {
title: 'string', amount: 'decimal(12, 2)', company: '->Company.deals',
contact: { type: 'email? ', class: 'personal' },
notes: { type: 'markdown? ', class: 'sensitive' },
stage: { open: [], qualify: 'opened', win: 'qualified', lose: ['opened', 'qualified'] },
},
privacy: {
role: 'processor', keys: 'customer', requests: '30d',
models: { personal: 'redact', sensitive: 'redact' },
},
offer: { Team: { month: 49, seats: 5, seat: 9 }, 'Deal.open': 0.001 },
})A Customer's admin reads a finished erasure: what was found, what a hold kept, and which upstream product erased its copy.
HTTP/1.1 200 OK
Content-Type: application/ json
X-Cost: price= 0, currency= "USD"
X-Request-Id: req_6a0f2d93c18e7b45a9d3
{
"id": "sr_1",
"kind": "erase",
"state": "done",
"subject": { "email": "dana@acme.com" },
"found": { "Deal": 3, "Company": 0, "events": 41 },
"held": [{ "record": "deal_2", "reason": "legal hold" }],
"upstream": [{ "host": "companyfacts.apis.dev", "state": "erased" }],
"due": "2026-11-26T00: 00: 00Z"
}That is GET /subject-requests/, getSubjectRequest over MCP and pipeline subject-requests get sr_1 in the CLI.
Requests, keys and lists, state by state
Every move is a Verb a Customer's admin or its agent makes on the product's own Interfaces.
Your operator reads each request that reaches the product with SubjectRequest.list on the Operator plane.
| Thing | States | What moves it |
|---|---|---|
| A subject request | received, verifying, finding, ready, then done or refused; extended once, with notice | The Customer's admin; the person's identity check; the deadline in privacy.requests |
| An erasure | requested, erasing, then erased and propagated; any record under a hold stays held | The request; every upstream product on the data chain answers with its own state |
| A correction | requested, reviewed, then applied or declined | The Customer decides; an applied correction is a change in history, Stated by the person |
| A customer-held key | active, rotating, then revoked | The Customer's own key service; a revoke makes the Namespace unreadable at once, and a restore of the key reverses it |
| A sub-processor change | announced, objection_window, effective | A deploy that adds a model provider or an upstream product; each Customer gets the notice its DPA names |
| A DPA version | offered, then accepted or objected | A deploy that changes classes, regions, retention or sub-processors; acceptance follows the agreement rules |
What Customers, people and reviewers meet
- A Customer's admin. Its DPA and sub-processor list, every person's request in one queue, its own key if it holds one, and an audit log it queries.
- A person in the records. A request made through the Customer, answered within the deadline, with what was found and what a hold kept.
- A security reviewer. Each field's class, where it goes, which models see it and how, and the chain of products behind this one.
- An agent. Masked fields stay masked in every tool, and a redacted value never reaches its model.
Every field carries its class from the file to the model router, so what is masked, logged, kept and erased follows one declaration.
Your workspace
Your own account with APIs.Dev: plan and take, allowances and spend caps, verification, the Stripe connection, going Live, suspension and client accounts.
Edge, model and tool security
Security past the Keys: the edge in front of every product, untrusted text on an agent's model path, and act classes and signed tool lists that agents trust.