Skip to main content
A schema declares the shape of a decision payload: which fields exist, what type each one holds, and which of them carry regulated data. Every ruleset is bound to exactly one (schema, version), and that binding decides how Specter validates the decision request, which field paths rules may reference, and how each value is redacted, retained, and audited. Specter ships one schema and lets you register your own:
This is the same model Guardian uses for generic tokens and their types: a schema declares the shape of a flexible payload, the platform validates against it, and everything downstream keys off the declaration rather than guessing from field names. Specter applies it to decision payloads instead of stored tokens.

How a request finds its schema

The decision request does not name a schema. It names a context, and the context resolves to a schema through the ruleset that is ACTIVE for it:
  • A ruleset declares its binding at creation (schema: {"name": "transaction"} for the built-in, {"name": "refund-request", "version": 2} for a custom schema) and keeps it for life. Rebinding a context means creating a new ruleset with the new binding and activating it.
  • Rules inherit the binding from their ruleset. A field reference that the bound schema does not declare rejects at submission with 422.
  • Every decision records the (schema, version) it was evaluated against and returns it as schema.
Contexts that need different payload shapes are simply different contexts — there is no dispatch on the shape of an incoming body.

The built-in transaction schema

transaction is the card-payment payload: credential, customer, transaction, device, billing, shipping, items, airline, metadata. It is present on every instance, version 1 today, and bound to every ruleset that existed before custom schemas arrived. The decision request reference is this schema rendered field by field, including the type and classification marker of each field. You can also read it through the registry: GET /api/admin/schemas/transaction/versions/1. New fields arrive only additively, through Specter releases — the seven BIN attributes on card credentials are an example. Nothing you send against it today stops validating.

Custom schemas

A custom schema is a JSON Schema document with two Specter keywords on each field: x-specter-type names the field’s type, x-data-classification its scope marker.
The registry endpoints need the admin:schemas:read and admin:schemas:write scopes — see the Schemas API reference.
1

Register

POST /api/admin/schemas with a name and the version-1 document. The document validates on the way in — unresolvable or external $ref, unknown type names, misspelled markers, and documents over the size, field-count, nesting, or $ref caps reject with 422.
2

Bind a ruleset

Create a ruleset with schema: {"name": "refund-request", "version": 1} and a context of your choice, then activate it. Decisions sent with that context now validate against your document.
3

Publish a new version

POST /api/admin/schemas/{name}/versions with the changed document. Versions are immutable and numbered by Specter; every publication is a new version. Rulesets bound to version 1 keep working — move a context over by creating and activating a ruleset bound to version 2.
4

Deprecate the old version

POST /api/admin/schemas/{name}/versions/{version}/deprecate. A deprecated version keeps serving the rulesets already bound to it, but no new ruleset can bind to it and a draft bound to it can no longer be activated.

Velocity counters across versions

When you publish a new version, carry_over (default true) decides whether velocity counters for field paths present in both versions continue counting across the version boundary. Publish with carry_over: false to have rulesets bound to the new version start from zero; earlier versions keep their counters. Blacklist entries are global and unaffected.

Field types

x-specter-type is a closed vocabulary of 23 entries. Each carries a validation rule applied to the decision payload at ingestion, so a rule can trust the value it compares against. Filters in rule conditions are type-checked against these declarations — domain() needs an email, for example — so a mistyped pipe chain rejects when you save the ruleset, not at decision time.

Classification markers

x-data-classification is one of any, pii, pci-pan, or pci-sad (lowercase; omitted means any). A pan-typed field is always pci-pan; a masked-pan field defaults to pii. The marker is what Specter acts on — never the field’s name: A field without a marker is a statement that it carries none of these categories, not that it has yet to be reviewed. The data classification legend describes the markers as they appear on the API reference.

What works with a custom schema

A custom schema changes what a decision is about; it does not change how you request or inspect one. What it cannot do is reach the card-payment machinery that sits behind the transaction schema.

Rulesets

Where the schema binding lives.

Rule engine

Field references, filters, and fingerprints over the bound schema.

Schemas API

Register, version, and deprecate custom schemas.

Guardian types

The same schema-typed model for stored tokens.