Anatomy
$id— the canonical URL identifying this protocol. Backends reference the protocol by this URL, and it is the join key between a protocol and the backends that implement it.name/version— human-readable identity and a version string.actions— the operations the protocol exposes (see below).components— optional reusable schema definitions referenced across actions.
Actions
An action is a named operation — for exampleassess. Each action declares:
- A method — one of
POST,GET,PUT,PATCH,DELETE. Callers must invoke the action with this method. - A description — a human-readable summary.
- A request schema — the input the caller sends.
- A set of responses — keyed by HTTP status code, each with an output schema.
notify.authorization,
notify.chargeback, notify.fraud_report. For the exact field-by-field definition, see the
Protocol schema reference.
Variants and discriminators
An action’s request can be either:- Monomorphic — a single request schema, or
- Polymorphic — a discriminated union. A discriminator field in the request selects which variant applies.
assess action might discriminate on credential.type: a request with credential.type: "pan"
resolves to the assess.pan variant, while credential.type: "token" resolves to assess.token. Backends
implement variants by their full key (assess.pan), and Link rejects a backend that misses a required action or
variant.
Versioning
The protocolversion and its $id together identify a contract. A new version is a new protocol document with
its own $id — existing backends keep targeting the version they were bound to, so contract changes never
silently alter live behavior.
A publisher can also update the document at the same $id, for example to add an optional field. Link picks
up such an update only when you refresh the protocol.
Refresh a protocol
A refresh fetches the protocol again from the URL it was imported from (its$id) and stores the fetched
document as the protocol’s next revision. It requires the admin:protocols:write scope. Start with a dry
run: it runs every check and writes nothing.
{"dry_run": false}, to store the update. status is one of:
A refresh runs the same checks as an import (meta-schema,
$ref resolution, required variants, schema
compilation). It also checks every backend that references the protocol against the new document: the
connections and response mappings of every backend, and the required actions and variants of enabled backends.
If any check fails, nothing changes.
Protocol summaries, in the protocol list and in the import and refresh responses, carry revision and
updated_at. revision starts at 1 and grows by one with every refresh that stores a new document.
Refresh errors
GraphQL
Link’s GraphQL API at/api/graphql offers the same operation as the refreshProtocol mutation, with the same
scope, checks, and classifiers. It returns status in upper case, and errors in the errors array.
Specter protocol at startup
By default, when an instance starts and has no Specter protocol stored yet, Link imports it. Link refreshes a Specter protocol that is already stored at startup only when the instance settingSPECTER_AUTO_REFRESH_ENABLED is on.
The setting is off by default, so a stored Specter protocol changes only when you refresh it. A startup refresh
runs the checks described above and fetches from the same source URL.
Meta-schema
Every protocol is validated against the Link protocol meta-schema (link-protocol-v1) at import time. A protocol
that does not conform is rejected. The meta-schema is served by each instance:
On a Bundled instance, imports are restricted to the protocols that serve
its Specter instance. To author and import your own protocols, you need a
Standalone instance; see the
Protocol schema reference.
Generated OpenAPI
Because a protocol fully describes its actions and schemas, Link generates an OpenAPI 3.1 specification for each imported protocol. This is the contract a consumer of the protocol integrates against — the invoke surface for that specific protocol — and is retrieved per protocol:Link operates at the protocol level: the invoke API is defined by whichever protocol you import, not by a
single fixed Link API. To document the endpoints your callers use, generate the OpenAPI for that protocol.
Next steps
Backends
Bind a protocol to a real provider with credentials, authentication, and mapping rules.
Invocation
Call a protocol action and handle the result.