Skip to main content

API Blocks

6 min readStableIntermediate

ApiBlock documents one REST endpoint in a single card from one typed operation object: a color-coded method badge, the path, an auth indicator, request parameters and body, a cURL command built from those values, and one or more response tabs. Reach for Parameter Fields and Response Fields when a field needs its own row with a type and a default.

Quick Start

A GET endpoint with a summary and one response body.

GET/api/v1/status

Check the service health status.

Request Example
curl -X GET "/api/v1/status"
Response200
{ "status": "healthy", "uptime": 99.97, "version": "1.0.0" }
app/features/api/api-blocks.mdx
MDX
<ApiBlock
  operation={{
    method: 'GET',
    path: '/api/v1/status',
    summary: 'Check the service health status.',
    responses: [
      {
        statusCode: '200',
        exampleBody: '{"status":"healthy","uptime":99.97,"version":"1.0.0"}',
      },
    ],
  }}
/>

Adding Options

Query and header parameters, a request body, bearer auth, and a rate limit with a note. Watch the cURL command: the query parameter becomes ?expand=scope, the header parameter becomes a -H flag, the bearer scheme adds an Authorization header, and the JSON media types add Content-Type and Accept.

POST/api/v1/tokensBearer Token

Generate an access token with a scope and expiration.

Rate limit: 60 requests / minute (per token)
Parameters
X-Idempotency-Keystringheaderrequired
Replay guard. Reuse the key to retry safely.
expandstringqueryDefault: scope
Extra fields to inline in the response.
Request Body
[ { "name": "scope", "type": "string", "location": "body", "required": true }, { "name": "expiresIn", "type": "string", "location": "body", "required": false, "defaultValue": "30d" } ]
Request Example
curl -X POST "/api/v1/tokens?expand=scope" \ -H "Authorization: Bearer <token>" \ -H "X-Idempotency-Key: <X-Idempotency-Key>" \ -H "Accept: application/json" \ -H "Content-Type: application/json" \ -d '{"scope":"<string>","expiresIn":"30d"}'
Response201
{ "token": "eyJhbGciOi...", "expiresAt": "2026-04-23T12:00:00Z" }
app/features/api/api-blocks.mdx
MDX
<ApiBlock
  operation={{
    method: 'POST',
    path: '/api/v1/tokens',
    summary: 'Generate an access token with a scope and expiration.',
    parameters: [
      {
        name: 'X-Idempotency-Key',
        type: 'string',
        location: 'header',
        required: true,
        description: 'Replay guard. Reuse the key to retry safely.',
      },
      {
        name: 'expand',
        type: 'string',
        location: 'query',
        defaultValue: 'scope',
        description: 'Extra fields to inline in the response.',
      },
    ],
    requestBody: {
      mediaType: 'application/json',
      fields: [
        { name: 'scope', type: 'string', location: 'body', required: true },
        {
          name: 'expiresIn',
          type: 'string',
          location: 'body',
          required: false,
          defaultValue: '30d',
        },
      ],
    },
    responses: [
      {
        statusCode: '201',
        mediaType: 'application/json',
        exampleBody:
          '{"token":"eyJhbGciOi...","expiresAt":"2026-04-23T12:00:00Z"}',
      },
    ],
    auth: { scheme: 'bearer' },
  }}
  rateLimit={{ requests: 60, window: 'minute', note: 'per token' }}
/>

Advanced

Two blocks cover the rest of the surface. The first pairs a deprecation warning with switchable response tabs, a base URL folded into the generated cURL, an auth label that overrides the scheme's default text, and a hand-written Python example that sits beside the generated cURL tab.

The second one drops summary so the card falls back to description, hides the parameter panel with showParameters={false}, and marks the endpoint as open with scheme: 'none', the one scheme that draws an open padlock instead of a closed one. Its query and header parameters still reach the cURL command even though no panel lists them, and the path parameter stays literal in the URL. The 204 response has no exampleBody, so only the status chip renders.

DeprecatedGEThttps://api.example.com/api/v1/docsAdmin token
Use GET /api/v1/documents instead.

Retrieve documents using the legacy endpoint.

Request Example
curl -X GET "https://api.example.com/api/v1/docs" \ -H "Authorization: Bearer <token>" \ -H "Accept: application/json"
Response
{ "items": [] }
DELETE/api/v1/sessions/{sessionId}No auth required

Revoke one session. This line comes from description, because the operation has no summary.

Request Example
curl -X DELETE "/api/v1/sessions/{sessionId}?reason=user_logout" \ -H "X-Request-Id: <X-Request-Id>"
Response204
app/features/api/api-blocks.mdx
MDX
<ApiBlock
  operation={{
    method: 'GET',
    path: '/api/v1/docs',
    summary: 'Retrieve documents using the legacy endpoint.',
    responses: [
      {
        statusCode: '200',
        label: 'OK',
        mediaType: 'application/json',
        exampleBody: '{"items":[]}',
      },
      {
        statusCode: '401',
        label: 'Unauthorized',
        exampleBody: '{"error":"invalid token"}',
      },
    ],
    auth: { scheme: 'bearer', label: 'Admin token' },
    deprecated: true,
    deprecationNote: 'Use GET /api/v1/documents instead.',
  }}
  baseUrl="https://api.example.com"
  codeExamples={[
    {
      language: 'python',
      label: 'Python',
      code: 'import requests\n\nresponse = requests.get(\n    "https://api.example.com/api/v1/docs",\n    headers={"Authorization": "Bearer <token>"},\n)',
    },
  ]}
/>
 
<ApiBlock
  operation={{
    method: 'DELETE',
    path: '/api/v1/sessions/{sessionId}',
    description:
      'Revoke one session. This line comes from description, because the operation has no summary.',
    parameters: [
      { name: 'sessionId', type: 'string', location: 'path', required: true },
      {
        name: 'reason',
        type: 'string',
        location: 'query',
        defaultValue: 'user_logout',
      },
      { name: 'X-Request-Id', type: 'string', location: 'header' },
    ],
    responses: [{ statusCode: '204' }],
    auth: { scheme: 'none' },
  }}
  showParameters={false}
/>

Options

Props are validated with Zod at render time. An invalid shape throws with the exact field path in the message rather than rendering an empty card.

Component props

operationobjectrequired

The endpoint's data as one object — a subset of the EndpointOperation type from lib/openapi-import/types.ts, so anything the OpenAPI importer produces can be passed straight through.

baseUrlstring

Prefix shown in muted text before the path and prepended to the cURL URL.

rateLimitobject

Rate-limit line under the summary, with a clock icon.

codeExamplesarray

Extra request examples. They appear as tabs after the generated cURL tab, which is always first and can't be removed.

showParametersbooleanDefault: true

Set false when the surrounding page renders its own parameter documentation, as components/OpenApiEmbed.tsx does. Hiding the panel does not change the generated cURL.

operation

operation.methodstringrequired

GET, POST, PUT, PATCH, or DELETE. Sets the badge color and the left border color: blue, green, amber, purple, red.

operation.pathstringrequired

The URL path shown next to the badge and used in the cURL command. Must be at least one character. Path placeholders are copied through as written.

operation.summarystring

Text shown below the header explaining what the endpoint does. Wins over operation.description when both are set.

operation.descriptionstring

Fallback body text used when operation.summary is absent. Rendered as plain text, so Markdown in it stays literal.

operation.parametersarrayDefault: []

Request parameters. Query and header entries render as ParamField rows and feed the cURL query string and -H flags. Path and body entries are accepted for importer parity but render nothing and don't rewrite the URL.

operation.requestBodyobject

The request payload description and the source of the cURL -d flag.

operation.responsesarrayDefault: []

One entry per documented status code. Two or more render as clickable tabs.

operation.authobjectDefault: {}

Auth indicator in the top-right corner of the header.

operation.deprecatedbooleanDefault: false

Adds a red "Deprecated" chip and fades the card to 75% opacity.

operation.deprecationNotestring

Migration guidance shown in a red warning box above the summary. It renders on its own, so a note without deprecated: true still shows the box.

operation.parameters entries

namestringrequired

Parameter name. Header parameters use this as the literal header name in the generated cURL.

typestring

Type label shown in the chip next to the name.

locationstringrequired

One of path, query, header, or body.

requiredbooleanDefault: false

Adds the red "required" label to the row.

defaultValuestring

Shown as Default: on the row and used as the sample value in the cURL command. Without it, the cURL falls back to <name>.

deprecatedboolean

Strikes through the parameter name and dims the row.

descriptionstring

Row description, rendered as inline Markdown. Rows without one read "No description provided."

operation.requestBody

mediaTypestringDefault: application/json

Value sent as the Content-Type header in the generated cURL.

examplestring

Literal payload for the cURL -d flag. Without it, the flag gets a skeleton built from fields.

descriptionstring

Accepted for importer parity. The card does not render it today.

fieldsarrayDefault: []

Body fields, using the same shape as operation.parameters. The Request Body panel prefers example when it's set; with no example, it falls back to pretty-printing fields as JSON, and shows nothing at all if both are empty.

operation.responses entries

statusCodestringrequired

Drives the chip color: green for 2xx, blue for 3xx, amber for 4xx, red for everything else.

labelstring

Extra text on the tab button, such as Unauthorized. Only visible when the operation has two or more responses.

descriptionstring

Accepted for importer parity. The card does not render it today.

mediaTypestring

When any response media type contains json, the generated cURL gains an Accept: application/json header.

exampleBodystring

JSON-encoded response body. It's re-indented before highlighting, and invalid JSON is printed as-is. Leave it out and only the status chip renders.

fieldsarrayDefault: []

Accepted so importer output passes through unchanged. Document response shapes with Response Fields instead.

headersarrayDefault: []

Response headers as { name, type, description }. Accepted for importer parity; the card does not render them today.

operation.auth

schemestring

bearer, apiKey, basic, oauth2, or none. The first four add the matching placeholder header to the cURL command and a closed padlock; none shows an open padlock and adds no header.

labelstring

Overrides the default text — "Bearer Token", "API Key", "Basic Auth", "OAuth 2.0", or "No auth required".

descriptionstring

Accepted for importer parity. The card does not render it today.

rateLimit

requestsnumberrequired

The request count, printed before the slash.

windowstringrequired

The window the count applies to, printed after the slash: minute, hour, 10 seconds.

notestring

Qualifier appended in parentheses, such as "per token".

codeExamples entries

languagestringrequired

Highlighting grammar. bash and python are loaded; any other value falls back to the JSON grammar.

labelstringrequired

Tab label.

codestringrequired

Example source. The copy button copies whichever tab is active.

Was this page helpful?