The published OpenAPI document

/v1/openapi.json — the per-tenant merged contract your capabilities land in, and the single source the generated SDKs, the API Explorer and the MCP server all read from.

Your tenant's API is published as one OpenAPI document:

Request
curl -s https://api.revenexx.com/v1/openapi.json \
  -H "X-Revenexx-Tenant: <TENANT_SLUG>" \
  -H "X-Revenexx-Api-Key: rvxk_..."

It is generated from the capabilities of the apps that tenant has installed — the platform's commerce apps and yours, merged into one surface under one /v1 prefix. Install another app and the document grows. Install nothing and there is nothing to call.

text
manifest.capabilities.json (every installed app)
        │
        ▼
/v1/openapi.json ──► generated SDKs
                 ──► API Explorer
                 ──► MCP server

What lands in it

Everything you declared, and only that:

Your declarationBecomes
routeThe path and method under /v1
capabilityThe operationId — and therefore the generated SDK method name
summaryThe operation summary: the line in the Explorer's list, the doc comment on the SDK method
descriptionThe operation description
parametersThe documented query, path and header parameters — and the only ones the gateway forwards
request / responseThe request and response schemas; a title hoists it into components.schemas as a named type
responsesThe documented statuses, merged with the gateway's standard ones
tag and manifest.tagsThe section the operation is grouped under

Nothing else. There is no supplementary description field, no separate documentation site, and no way to annotate an operation after the fact.

There is no second place to correct a wrong description

This is the sentence worth taking literally.

A vague summary is a vague line in the API Explorer, a vague doc comment in the TypeScript SDK, a vague tool description the MCP server offers a model, and a vague answer to the partner who has to integrate with you. A field with no description is a field nobody can guess the meaning of, in every one of those places at once.

The fix is always the same shape, and it is never quick:

  1. Edit the declaration.
  2. Bump version in manifest.json.
  3. revenexx deploy app.

There is no cache to clear, no doc build to trigger, and no override to apply in a console. Which is a good property — one source, no drift — but it does mean the cheapest time to write a good summary is while you are writing the capability.

Two habits follow:

  • Write summaries and field descriptions for a stranger, because a stranger is who reads them.
  • Review the published document, not your source file, before you tell anybody the API is ready. Your manifest is what you meant; the document is what they get.

What reads it

The generated SDKs. Every API client the platform publishes is generated from this document, which is how a new language gets added without anybody hand-writing your methods. Your capability key becomes the method name; your titled schemas become named types. As a partner you install the published package — you do not run the generator. See SDKs.

The API Explorer. The browsable, callable reference. It renders your parameters, your schemas, your example values and your declared statuses.

The MCP server. Each capability is offered as a tool, described by your summary and description, with your request schema as its input schema. A model calling your app reads exactly the prose you wrote.

Checking that your capability made it

After a deploy, confirm the operation is really published rather than assuming the build implies it:

Verify
curl -s https://api.revenexx.com/v1/openapi.json \
  -H "X-Revenexx-Api-Key: $REVENEXX_API_KEY" \
  -H "X-Revenexx-Tenant: $REVENEXX_TENANT" \
  | grep -o '"/serials[^"]*"'

If the path is missing, the app is not installed on this tenant, or the install step did not run — routes are written at install time, and a build alone publishes nothing.

Worth checking in the same pass, because each is a common miss:

  • Your pagination parameters are present on the list operation. Absent means every caller is stuck on page one.
  • Your 201 is there on a create, and the 200 it replaced is gone.
  • Your schemas have names, not inline_response_200. That means you forgot a title.
  • Your operationId is the capability key you expected, because that is the SDK method a partner will call by name.

It is per tenant

Two tenants with different apps installed have different documents, and that is by design — a tenant's contract describes what that tenant can actually call.

So when you generate a client, generate it against a tenant that has the apps you depend on installed. And when a partner reports an endpoint missing, the first question is which tenant they fetched the document for.

Next steps

Was this page helpful?