Skip to content

APIs

A captured API entry vendors one OpenAPI document and names exactly the operations the realm may call.

apis: {
statuspage: {
url: "statuspage.json", // a file under apis/, vendored
name: "statuspage", // the gateway namespace
type: "openapi",
auth: "api-key",
credential: "statuspage-key",
headers: { "X-Client": "realm-oncall-radar" },
operationIds: ["listUnresolvedIncidents", "listIncidents"],
writeOperationIds: ["acknowledgeIncident"],
},
},

The generated gateway has one method per listed operation under ctx.gateway.<name>. A read takes an untyped arguments object: ctx.gateway.statuspage.listIncidents({ services }). A write takes an arguments interface built from the vendored document, holding its path and query parameters and its request body under the reserved body argument, and a field the operation does not declare is a compile error:

await ctx.gateway.statuspage.acknowledgeIncident({
incidentId: input.incidentId,
body: { note: "Seen by the on-call radar" },
});

A write whose parameters or body synth cannot read from the document falls back to the untyped arguments object, with a comment in the generated file saying why. An operation may not declare a parameter named body. Every call resolves to unknown: the response comes back as the parsed JSON body with no envelope, so narrow it before use.

What synth checks, which is also what the host refuses at install:

  • At most 32 entries and 128 operations across them. The entry’s key is a JavaScript identifier. name is [A-Za-z_][A-Za-z0-9_-]{0,63} and unique. Two operations may share an id in different namespaces, and are refused when their qualified names collide (<name>.<id>, <name>_<id>, or the two camel-cased and joined with _).
  • url is a bare filename, [A-Za-z0-9_-]+\.json, under apis/, at most 1 MiB, OpenAPI 3.x, with every $ref pointing under #/components/, at most 256 paths, and each operation id declared once. apis/apis.yml is at most 64 KiB.
  • Exactly one of credential or tokenEnv, and a credential must be declared in credentials. tokenEnv is deprecated in favour of a declared credential: it matches [A-Za-z_][A-Za-z0-9_]{0,127}, may not start with __embabel_sql_v1__, and becomes an implicit credential, with a warning. The implicit credential’s id is the variable name spelled as written, which the declared-id pattern does not cover; the host reads a credential id in either spelling (see credentials and databases). Two entries reading one tokenEnv must declare the same auth. apis.yml always carries credential:, and token-env: beside it on the deprecated path. An auth: "path" entry cannot use tokenEnv.
  • operationIds lists 1 to 128 reads, each a GET with no request body. writeOperationIds lists up to 64 writes, each a POST, PUT, PATCH or DELETE. An operation is in one list, never both, and every listed id must exist in the document.
  • The document has exactly one https server on port 443, with no user info, query, fragment, server variables, percent-encoded path, . or .. segment or { placeholder (other than {credential} under auth: "path"), and no per-path or per-operation server override.
  • An operation path matches ^/[A-Za-z0-9_~./{}-]*$ with no . or .. segment. Parameters are declared inline, in query or path, with a string, integer, number or boolean schema: at most 64 per operation, named [A-Za-z_][A-Za-z0-9_-]{0,63}, none repeated across the path item and the operation. A path parameter is required, and the path’s placeholders and its path parameters match exactly. An enum holds at most 128 non-null scalars, and minLength and maxLength are whole numbers from 0 to 2048.
  • A request body holds only content, with one media type, application/json, whose schema is an object.
  • Security is exactly one requirement naming one scheme, with no scopes. For bearer it is an http scheme whose word matches the credential’s scheme. For api-key it is an apiKey scheme in a header or the query, named [A-Za-z][A-Za-z0-9-]{0,127}, and the header may not be one the host owns (Authorization, Cookie, Host, Content-Type and the like). The field the credential travels in may not also be a fixed header or a parameter.
  • auth: "path" puts the credential in the URL and needs credential. The document writes {credential} in the server URL or in the path of a declared operation, so that each declared operation’s full URL carries it exactly once, in the path, never in a query string. security is absent or empty, and no operation takes a credential parameter. The generated client takes no argument for it.
  • Up to 16 fixed headers, each named X-... and holding at most 1,024 printable ASCII characters, with no ${ substitution. Two header names that differ only in case are refused.

Each operation is approved by the owner on its own, reads and writes under separate grants; see captured API operations for what the host does on every call.