Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Agentic Atlas Links API
description: 'Read-only JSON access to the Agentic Atlas: field-tested patterns for
designing agentic systems — skills, subagents, plugins, and multi-agent
workflows. **No authentication.** Every operation is public and unauthenticated. There
is no key to obtain, no quota to register for, and no account. **Read-only.** Human operations use `GET`; `/api/agent/*` uses `POST` with
JSON arguments to read the same Agent projection as MCP and the public CLI. Nothing here creates, updates, or deletes. Three
consequences worth stating, because they are what a general-purpose client
goes looking for and will not otherwise find:
* No `Idempotency-Key`. A safe `GET` has nothing to replay-protect, so the
header is neither required nor honoured. Retry a failed call directly. * No asynchronous jobs. Every operation answers in one round trip. There is
no job to submit, no status to poll, and no callback to register. * No sandbox. Every operation reads published data with no key, no quota,
and no side effect, so the live surface *is* the safe one to develop
against — a second environment would only serve a second Release. The machine-readable form of all three is `info.x-api-shape`. **One Release at a time.** The Atlas publishes one sealed Release. Every
reading of it carries an `X-Catalog-Revision` header naming it, and a
refusal carries none, so take the revision off an answer and never off a
refusal. Which is which is a property of the response, not of the status: a
response declared with a reading''s schema is a reading whatever its status,
and a response declared as `AtlasError` is a refusal. Today every `200` is a
reading, and so are two `404`s, `readDecision`''s not-found miss and
`readTour`''s unsealed walk, each declared with its own reading''s schema and
this header; every response declared as `AtlasError` carries no revision. Two responses with the same value are guaranteed to describe the same
Atlas. A promotion replaces the active Release wholesale rather than editing
one in place, so a long-running client that sees the header change has
crossed a promotion and should re-read rather than merge. **Versioning.** Addresses are stable and are not prefixed with `/v1/`; the
protocol version travels in a header instead, so an additive change never
moves a URL. Every API response carries `API-Version: 2`, declared on every
response in this document with its one permitted value, and restated in
`info.x-api-version`. The same header may be sent *on* a request to pin the
version a client was written against: pin the version you parse, and a
deployment serving a different one refuses with `400` instead of handing you
a payload you will misread. Omitting it means "whatever is current", so no
existing client has to change. This protocol version is independent of the
content Release named by `X-Catalog-Revision`. Additive changes — a new
operation, a new optional parameter, a new field in a response — stay within
version 1, so parse leniently. A breaking change increments `API-Version` and is
announced first under the policy below. **Deprecation.** A deprecated operation returns `Deprecation: true` and an
HTTP-date `Sunset` header for at least 180 days before removal, and is
marked `deprecated: true` in this document for that whole interval. Both
headers are declared on every operation here so a client can read the
retirement signal without being told where to look; both are absent while an
operation is current. `info.x-deprecation-policy` carries the notice window,
the two header names with their RFCs, and `deprecatedOperations` — the
authoritative list, which is empty. No operation is deprecated today. **Human API pagination.** There is none, and that is the contract rather than a gap. Reads are *bounded*, not paged: an operation that could return many rows
takes a `limit` whose default and maximum are declared on the parameter
itself.'
version: v1.1.0
contact:
name: Agentic Atlas
url: https://agentic-atlas.dev/contact
email: hello@agentic-atlas.dev
license:
name: Source-available; reading and use permitted, republication not
url: https://agentic-atlas.dev/why
x-api-version: '2'
x-version-header: API-Version
x-deprecation-policy:
minimumNoticeDays: 180
deprecationHeader: Deprecation
deprecationHeaderSpecification: RFC 9745
sunsetHeader: Sunset
sunsetHeaderSpecification: RFC 8594
deprecatedOperations: []
versioningScheme: header
versionHeader: API-Version
currentVersion: '2'
versionPinning: Optional and bidirectional. A request may state API-Version to pin the version it was written against; a value other than the current one is refused 400 rather than answered. Omitting it accepts whatever version is current.
breakingChangePolicy: A breaking change increments the API-Version header. Additive changes — a new operation, a new optional parameter, a new response field — retain it, so a client must parse leniently.
x-api-shape:
readOnly: true
methods:
- GET
- POST
writeOperations: []
authentication: none
idempotencyKeys: Not applicable. Every operation only reads published data, so there is nothing to replay-protect; `Idempotency-Key` is neither required nor honoured. Retry a failed call directly.
asynchronousOperations: None. Every operation answers in one round trip — no job to submit, no status to poll, no callback to register.
sandbox: None, and none is needed. Every operation is a public read of published data with no key, no quota, and no side effect, so the live surface is the safe one to develop against.
batchOperations:
readCards: ids
compare: ids
resolveName: name
batchStyle: 'Human batchOperations use repeated query parameters on GET; agentBatchOperations use an ids array in a JSON POST body. Each is atomic: the whole call is refused rather than partially answered, so no caller has to notice a gap in a payload that looks complete. The refusal names the id that spoiled the batch — drop it and re-batch the rest in one call. Falling back to one call per id spends a request per id to learn what the refusal already said.'
agentBatchOperations:
agent_cards: JSON body ids array; atomic
x-pagination:
appliesTo: Human GET operations; Agent POST operations declare x-pagination per operation
style: bounded-read
boundParameter: limit
offsetParameter: null
pageParameter: null
cursorParameter: null
nextLinkField: null
truncationFields:
- total
- returned
- truncated
truncationReportedBy:
- readLinks
- readTermUsages
description: Reads are bounded, not paged. `limit` caps one response; it does not select a window, and there is no offset, page number, or cursor to advance — no continuation state exists to carry. Ordering is the publisher's and is stable within one Release, so a bounded read is a prefix rather than a sample. Where a bound can cut, the payload reports it in-band; the remainder is reached by raising `limit` toward the maximum declared on the parameter, or by narrowing the subject. A client written for cursors should not be pointed here.
x-availability:
healthProbe: /healthz
readinessProbe: /readyz
statusDocumentation: /status
statusPage: null
incidentFeed: null
slaPublished: false
retryableStatuses:
- 503
description: 'Availability is best effort and no service level is promised. /healthz answers whenever the process is running and reads no database; /readyz answers 200 when this deployment can serve and 503 when it cannot, naming every check, the active Release and its Catalog revision. A 503 from an operation is the same condition and the same retry: the address is unchanged and the operation is not retired. There is no external status page, no incident feed and no uptime history — /status states each refusal this API can return with its recovery, and says that too.'
servers:
- url: https://agentic-atlas.dev
description: The origin this API is published at
tags:
- name: Links
paths:
/api/links/{canonical_id}:
get:
summary: Page one Node's relationship occurrences
operationId: readLinks
parameters:
- name: API-Version
in: header
required: false
schema:
type: string
enum:
- '2'
description: The protocol version this client was written against. Omit it to be served whatever version is current; send it to be refused with 400 rather than answered in a version you cannot parse. The value to send is the one every response states in the header of this name.
- name: canonical_id
in: path
required: true
schema:
type: string
title: Canonical Id
description: The subject whose relationships are read.
- name: direction
in: query
required: false
schema:
type: string
default: both
title: Direction
enum:
- both
- in
- out
description: Which side to read. The default carries both in one response and each occurrence states its own direction, so filtering here saves nothing but a field.
- name: limit
in: query
required: false
schema:
type: integer
default: 12
title: Limit
minimum: 1
maximum: 50
description: 'How many occurrences to carry per side. A bound, not a page: when it cuts, the view says so in `total`, `returned` and `truncated`, and the remainder is reached by raising this toward its maximum rather than by a cursor.'
responses:
'200':
description: The requested reading of the active Release.
content:
application/json:
schema:
$ref: '#/components/schemas/LinksRead'
headers:
API-Version:
$ref: '#/components/headers/ApiVersion'
Deprecation:
$ref: '#/components/headers/Deprecation'
Sunset:
$ref: '#/components/headers/Sunset'
RateLimit-Limit:
$ref: '#/components/headers/RateLimitLimit'
RateLimit-Remaining:
$ref: '#/components/headers/RateLimitRemaining'
RateLimit-Reset:
$ref: '#/components/headers/RateLimitReset'
RateLimit:
$ref: '#/components/headers/RateLimit'
RateLimit-Policy:
$ref: '#/components/headers/RateLimitPolicy'
X-Catalog-Revision:
$ref: '#/components/headers/CatalogRevision'
'400':
description: Nothing was read. The request pinned an API-Version this deployment does not serve, a Human query is invalid, or an Agent JSON body is malformed. AtlasError names its cause in `error.type`; AgentError uses `error.code`. For an unsupported version, resend with the version the response header states, or without the header. For an invalid query or JSON body, correct the input before retrying. The direct version refusal spends from the rate-limit window but carries none of its advisory headers; routed query and body refusals do, so this shared 400 response cannot require them.
headers:
API-Version:
$ref: '#/components/headers/ApiVersion'
Deprecation:
$ref: '#/components/headers/Deprecation'
Sunset:
$ref: '#/components/headers/Sunset'
content:
application/json:
schema:
$ref: '#/components/schemas/AtlasError'
'404':
description: 'No such subject in the active Release. The address is an operation and the request parsed; it is the subject that is unknown. An operation that refuses its miss does so in `AtlasError`, and `error.type` names the class it was looked for as. An operation that answers its miss as a reading instead sends the same payload as its 200, declared on this status through the same schema, carrying X-Catalog-Revision and no `error` key: readDecision (`DecisionRead` with `outcome` `not-found` and `decision` null) and readTour (`LearningPathsRead` with `paths` empty). A 404 at an address that names no operation is a different refusal, `UnknownOperation`, and is declared on no operation here because none is published there.'
headers:
API-Version:
$ref: '#/components/headers/ApiVersion'
Deprecation:
$ref: '#/components/headers/Deprecation'
Sunset:
$ref: '#/components/headers/Sunset'
RateLimit-Limit:
$ref: '#/components/headers/RateLimitLimit'
RateLimit-Remaining:
$ref: '#/components/headers/RateLimitRemaining'
RateLimit-Reset:
$ref: '#/components/headers/RateLimitReset'
RateLimit:
$ref: '#/components/headers/RateLimit'
RateLimit-Policy:
$ref: '#/components/headers/RateLimitPolicy'
content:
application/json:
schema:
$ref: '#/components/schemas/AtlasError'
'405':
description: Nothing was read. The address names an operation; the method does not. Resend under one of the methods the `Allow` header names — and note that this API has no write operations at all, which info.x-api-shape states. Agent reads use POST; Human reads use GET and HEAD.
headers:
API-Version:
$ref: '#/components/headers/ApiVersion'
Deprecation:
$ref: '#/components/headers/Deprecation'
Sunset:
$ref: '#/components/headers/Sunset'
RateLimit-Limit:
$ref: '#/components/headers/RateLimitLimit'
RateLimit-Remaining:
$ref: '#/components/headers/RateLimitRemaining'
RateLimit-Reset:
$ref: '#/components/headers/RateLimitReset'
RateLimit:
$ref: '#/components/headers/RateLimit'
RateLimit-Policy:
$ref: '#/components/headers/RateLimitPolicy'
Allow:
$ref: '#/components/headers/Allow'
content:
application/json:
schema:
$ref: '#/components/schemas/AtlasError'
'422':
description: A parameter value is outside its permitted range, or could not be parsed into its declared type. Agent reads also use this status for an unadmitted address or a non-atomic batch, with the reason in AgentError's `error.code` and rejected ids in `error.rejected`. Human reads use AtlasError or framework validation errors; see the declared response schema.
headers:
API-Version:
$ref: '#/components/headers/ApiVersion'
Deprecation:
$ref: '#/components/headers/Deprecation'
Sunset:
$ref: '#/components/headers/Sunset'
RateLimit-Limit:
$ref: '#/components/headers/RateLimitLimit'
RateLimit-Remaining:
$ref: '#/components/headers/RateLimitRemaining'
RateLimit-Reset:
$ref: '#/components/headers/RateLimitReset'
RateLimit:
$ref: '#/components/headers/RateLimit'
RateLimit-Policy:
$ref: '#/components/headers/RateLimitPolicy'
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/AtlasError'
- $ref: '#/components/schemas/RequestValidationError'
'429':
description: Nothing was read. More than the published number of requests came from this address inside one window, and the refusal was composed before the operation ran. Wait the seconds named in `Retry-After` and resend; the request itself is fine. Every response, this one included, states the window in `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset`, so a client can pace itself and never arrive here.
headers:
API-Version:
$ref: '#/components/headers/ApiVersion'
Deprecation:
$ref: '#/components/headers/Deprecation'
Sunset:
$ref: '#/components/headers/Sunset'
RateLimit-Limit:
$ref: '#/components/headers/RateLimitLimit'
RateLimit-Remaining:
$ref: '#/components/headers/RateLimitRemaining'
RateLimit-Reset:
$ref: '#/components/headers/RateLimitReset'
RateLimit:
$ref: '#/components/headers/RateLimit'
RateLimit-Policy:
$ref: '#/components/headers/RateLimitPolicy'
Retry-After:
$ref: '#/components/headers/RetryAfter'
content:
application/json:
schema:
$ref: '#/components/schemas/AtlasError'
'503':
description: The Catalog is unreachable, or no Release is active. The address is fine and the request parsed; retry it. Readiness is reported at /readyz, and /status states this and every other refusal with its recovery.
headers:
API-Version:
$ref: '#/components/headers/ApiVersion'
Deprecation:
$ref: '#/components/headers/Deprecation'
Sunset:
$ref: '#/components/headers/Sunset'
RateLimit-Limit:
$ref: '#/components/headers/RateLimitLimit'
RateLimit-Remaining:
$ref: '#/components/headers/RateLimitRemaining'
RateLimit-Reset:
$ref: '#/components/headers/RateLimitReset'
RateLimit:
$ref: '#/components/headers/RateLimit'
RateLimit-Policy:
$ref: '#/components/headers/RateLimitPolicy'
content:
application/json:
schema:
$ref: '#/components/schemas/AtlasError'
description: 'Every argued relationship touching one subject, inbound and outbound in the same page. There is deliberately no direction filter: each occurrence carries its own direction, so read the side you want off the page you already have rather than spending a second call.'
deprecated: false
tags:
- Links
components:
schemas:
AtlasError:
type: object
title: Atlas error
description: 'The Atlas''s own refusal: a nested `error` object naming what could not be answered. Show `error.message`; branch on the HTTP status, or on `error.type` for a finer split.'
properties:
error:
type: object
properties:
code:
type: integer
description: The HTTP status, repeated in the body. Omitted by readNode, so read the status rather than relying on this.
type:
type: string
description: 'The class of refusal — `NodeNotFound`, `InvalidBound`, `CatalogUnavailable`, and the like. The refusals composed before the operation runs name themselves here too: `UnsupportedApiVersion` on a 400, `RateLimited` on a 429, `MethodNotAllowed` on a 405, and `UnknownOperation` on a 404 at an address that names no operation at all.'
message:
type: string
description: One sentence naming what could not be answered.
required:
- type
- message
required:
- error
ReferenceView:
type: object
title: Bounded reference view
description: 'One side of a bounded read. There is no cursor or offset to fetch the remainder: raise `limit` toward its maximum, or narrow the subject.'
properties:
total:
type: integer
description: How many occurrences exist on this side.
returned:
type: integer
description: How many this response carries.
truncated:
type: boolean
description: True when `total` exceeds `returned` — the bound cut, and what is here is a prefix.
references:
type: array
description: The occurrences themselves, each stating its own direction and class.
items:
type: object
required:
- total
- returned
- truncated
- references
LinksRead:
type: object
title: Bounded relationship read
description: Every argued relationship touching one subject, inbound and outbound in one bounded response.
properties:
catalog_revision:
type: object
description: The active Release's Catalog revision, the same identity the X-Catalog-Revision header carries, with the provenance counts beside it.
properties:
revision:
type: string
description: The revision two responses must share to be comparable.
required:
- revision
subject:
type: object
description: The Node the relationships were read around.
direction:
type: string
enum:
- both
- in
- out
description: The direction filter this read applied.
limit:
type: integer
description: The bound this response was read under — echoed so a caller can tell a defaulted read from one it asked for.
inbound:
$ref: '#/components/schemas/ReferenceView'
outbound:
$ref: '#/components/schemas/ReferenceView'
required:
- catalog_revision
- subject
- direction
- limit
- inbound
- outbound
RequestValidationError:
type: object
title: Request validation error
description: 'The framework''s refusal, raised before the operation runs when a parameter cannot be parsed into its declared type at all — `limit=abc`, say. Distinct from AtlasError: a 422 may carry either, so branch on which key is present.'
properties:
detail:
type: array
description: One entry per parameter that failed.
items:
type: object
properties:
type:
type: string
description: The parse failure's class.
loc:
type: array
description: Where the bad value was, e.g. `["query", "limit"]`.
msg:
type: string
description: The failure in one sentence.
input:
description: The value as it was received.
required:
- type
- loc
- msg
required:
- detail
headers:
Sunset:
description: The HTTP-date after which this operation may be removed (RFC 8594). Accompanies Deprecation and is set at least 180 days ahead. Absent on a current operation, and absent everywhere today.
required: false
schema:
type: string
format: http-date
Deprecation:
description: Present, with the value `true`, only while this operation is inside its retirement notice window (RFC 9745). Absent on a current operation, and absent everywhere today — no operation is deprecated. See info.x-deprecation-policy.deprecatedOperations.
required: false
schema:
type: string
enum:
- 'true'
CatalogRevision:
description: The active Release's Catalog revision. Two responses carrying the same value describe the same Atlas; a changed value means a promotion happened between the calls.
required: true
schema:
type: string
RateLimit:
description: 'The current API window as one advisory field: `limit`, `remaining`, and seconds until `reset`. Present on every API response so a client can pace itself before a refusal. The direct unsupported-version 400 is the one exception.'
required: true
schema:
type: string
example: limit=300, remaining=299, reset=60
Allow:
description: 'The methods this address does answer. Present only on a 405, where it is the whole recovery in the way Retry-After is on a 429: resend the same request under one of these.'
required: true
schema:
type: string
RateLimitRemaining:
description: The requests left in the current API window after this one. Present on every API response except the direct unsupported-version 400.
required: true
schema:
type: integer
minimum: 0
maximum: 300
ApiVersion:
description: The stable API protocol version. Additive changes retain this value; a breaking change increments it. Independent of the content Release named by X-Catalog-Revision. Send this value back as a request header to pin it — see the parameter of the same name on any operation.
required: true
schema:
type: string
enum:
- '2'
RateLimitPolicy:
description: 'The policy that produced this window: the `api` policy name, its request quota (`q`), and its window in seconds (`w`). Present on every API response except the direct unsupported-version 400.'
required: true
schema:
type: string
enum:
- '"api";q=300;w=60'
RetryAfter:
description: 'How many seconds until the rate-limit window reopens. Present only on a 429, where it is the whole recovery: wait this long and resend the same request unchanged.'
required: true
schema:
type: integer
minimum: 1
maximum: 60
RateLimitLimit:
description: The maximum requests admitted in the current API window. Present on every API response except the direct unsupported-version 400.
required: true
schema:
type: integer
enum:
- 300
RateLimitReset:
description: Seconds until the current API window resets, clamped to at least one. Present on every API response except the direct unsupported-version 400.
required: true
schema:
type: integer
minimum: 1
maximum: 60
externalDocs:
description: Agent manifest, MCP endpoint, and call contract
url: https://agentic-atlas.dev/llms.txt