v2.6.0

<bmx-api-explorer>

An OpenAPI console in the page: point it at an API description - OpenAPI 3.0 or 3.1, JSON or YAML, or a Swagger 2.0 file - and it lists every operation by tag, documents each one (parameters, request body, every response and its schema as a field table), and lets the reader try it: fill in the parameters, edit the body (started from the example), authorize once, and send. The response comes back with its status, time, size, headers and pretty-printed body, checked against the documented schema.

15 properties · 5 events · 9 methods · 9 parts

Example

This example runs in mock mode: requests are answered from the description's own examples, so nothing leaves the page. Authorize with any key to get past the 401.

Show markup
<bmx-api-explorer id="ex-ae" mock selected="getOrder" style="--bmx-api-explorer-height: 46rem"></bmx-api-explorer>
<p class="note" id="ex-ae-out" role="status" style="margin: 12px 0 0">This example runs in <code>mock</code> mode: requests are answered from the description's own examples, so nothing leaves the page. Authorize with any key to get past the 401.</p>

<script type="text/yaml" id="ex-ae-spec">
openapi: 3.1.0
info:
  title: Harbour & Pine Orders API
  version: 2.3.0
  description: |
    Create, find and fulfil orders for the Harbour & Pine trade counter.

    - Amounts are in **pence**, as integers.
    - Times are UTC, in ISO 8601.
    - Lists are paged with `limit` and `cursor`.
servers:
  - url: https://sandbox.harbourpine.example/v2
    description: Sandbox
  - url: https://{region}.api.harbourpine.example/v2
    description: Production
    variables:
      region:
        default: eu
        enum: [eu, uk, us]
tags:
  - name: Orders
    description: Orders placed by trade customers.
  - name: Customers
    description: Trade accounts and their credit limits.
security:
  - apiKey: []
  - bearer: []
paths:
  /orders:
    get:
      tags: [Orders]
      operationId: listOrders
      summary: List orders
      description: Newest first. Filter by status, customer or the date they were placed.
      parameters:
        - name: status
          in: query
          description: One or more statuses.
          schema:
            type: array
            items: { type: string, enum: [open, paid, dispatched, cancelled] }
        - name: customerId
          in: query
          schema: { type: string, example: CUS-2041 }
        - name: placedAfter
          in: query
          schema: { type: string, format: date }
        - name: limit
          in: query
          schema: { type: integer, minimum: 1, maximum: 100, default: 25 }
        - name: cursor
          in: query
          description: The `nextCursor` of the previous page.
          schema: { type: string }
      responses:
        '200':
          description: A page of orders
          headers:
            X-RateLimit-Remaining:
              description: Requests left this minute
              schema: { type: integer }
          content:
            application/json:
              schema:
                type: object
                required: [items]
                properties:
                  items:
                    type: array
                    items: { $ref: '#/components/schemas/Order' }
                  nextCursor: { type: [string, 'null'] }
              example:
                items:
                  - id: ORD-10482
                    customerId: CUS-2041
                    status: paid
                    placedAt: 2026-10-14T09:12:00Z
                    currency: GBP
                    lines: [{ sku: OAK-SHELF-90, description: Oak shelf 90 cm, quantity: 4, unitPrice: 4250 }]
                    total: 17000
                nextCursor: eyJwIjoyfQ
        '401': { $ref: '#/components/responses/Unauthorized' }
    post:
      tags: [Orders]
      operationId: createOrder
      summary: Place an order
      description: The order is checked against the customer's credit limit before it is accepted.
      parameters:
        - name: Idempotency-Key
          in: header
          description: Send the same key to retry safely; the order is placed once.
          schema: { type: string, format: uuid }
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/NewOrder' }
            examples:
              shelves:
                summary: Four oak shelves
                value: { customerId: CUS-2041, lines: [{ sku: OAK-SHELF-90, quantity: 4 }] }
              mixed:
                summary: A mixed order with a note
                value: { customerId: CUS-2041, note: Deliver to the side gate, lines: [{ sku: OAK-SHELF-90, quantity: 2 }, { sku: PINE-DESK-140, quantity: 1 }] }
      responses:
        '201':
          description: Placed
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Order' }
              example:
                id: ORD-10483
                customerId: CUS-2041
                status: open
                placedAt: 2026-10-15T08:30:00Z
                currency: GBP
                lines: [{ sku: OAK-SHELF-90, description: Oak shelf 90 cm, quantity: 4, unitPrice: 4250 }]
                total: 17000
        '422':
          description: Over the credit limit, or an unknown product
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Problem' }
        '401': { $ref: '#/components/responses/Unauthorized' }
  /orders/{orderId}:
    parameters:
      - name: orderId
        in: path
        required: true
        schema: { type: string, pattern: '^ORD-[0-9]+$' }
        example: ORD-10482
    get:
      tags: [Orders]
      operationId: getOrder
      summary: Find an order
      responses:
        '200':
          description: The order
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Order' }
              example:
                id: ORD-10482
                customerId: CUS-2041
                status: paid
                placedAt: 2026-10-14T09:12:00Z
                currency: GBP
                lines: [{ sku: OAK-SHELF-90, description: Oak shelf 90 cm, quantity: 4, unitPrice: 4250 }]
                total: 17000
        '404':
          description: No such order
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Problem' }
    delete:
      tags: [Orders]
      operationId: cancelOrder
      summary: Cancel an order
      description: Only an order that has not been dispatched can be cancelled.
      responses:
        '204': { description: Cancelled }
        '409':
          description: Already dispatched
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Problem' }
  /orders/{orderId}/dispatch:
    post:
      tags: [Orders]
      operationId: dispatchOrder
      summary: Mark an order dispatched
      parameters:
        - name: orderId
          in: path
          required: true
          schema: { type: string }
          example: ORD-10482
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                carrier: { type: string, enum: [Parcelpoint, Northline, Collection] }
                tracking: { type: string, maxLength: 40 }
      responses:
        '200':
          description: Dispatched
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Order' }
  /customers/{customerId}:
    get:
      tags: [Customers]
      operationId: getCustomer
      summary: Find a trade customer
      parameters:
        - name: customerId
          in: path
          required: true
          schema: { type: string }
          example: CUS-2041
      responses:
        '200':
          description: The customer
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Customer' }
              example: { id: CUS-2041, name: Fenwick Joinery Ltd, email: accounts@fenwick-joinery.example, creditLimit: 500000, balance: 128400 }
  /health:
    get:
      summary: Health check
      security: []
      responses:
        '204': { description: The API is up }
components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-Api-Key
      description: Your key from the trade portal's Developer page.
    bearer:
      type: http
      scheme: bearer
      bearerFormat: JWT
  responses:
    Unauthorized:
      description: No key, or a key that has been revoked
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Problem' }
  schemas:
    NewOrder:
      type: object
      required: [customerId, lines]
      properties:
        customerId: { type: string, example: CUS-2041 }
        note: { type: string, maxLength: 200, description: Shown on the delivery note }
        lines:
          type: array
          minItems: 1
          items:
            type: object
            required: [sku, quantity]
            properties:
              sku: { type: string, example: OAK-SHELF-90 }
              quantity: { type: integer, minimum: 1, maximum: 999 }
    Order:
      type: object
      required: [id, customerId, status, placedAt, lines, total]
      properties:
        id: { type: string, readOnly: true, example: ORD-10482 }
        customerId: { type: string }
        status: { type: string, enum: [open, paid, dispatched, cancelled] }
        placedAt: { type: string, format: date-time }
        currency: { type: string, default: GBP }
        lines:
          type: array
          items:
            type: object
            properties:
              sku: { type: string }
              description: { type: string }
              quantity: { type: integer }
              unitPrice: { type: integer, description: In pence }
        total: { type: integer, description: 'In pence, including VAT' }
    Customer:
      type: object
      properties:
        id: { type: string }
        name: { type: string }
        email: { type: string, format: email }
        creditLimit: { type: integer, description: In pence }
        balance: { type: integer, description: 'Owed now, in pence' }
    Problem:
      type: object
      properties:
        title: { type: string }
        detail: { type: string }
</script>

<script type="module">
  await customElements.whenDefined('bmx-api-explorer');
  const explorer = document.getElementById('ex-ae');
  const out = document.getElementById('ex-ae-out');
  explorer.spec = document.getElementById('ex-ae-spec').textContent;
  explorer.addEventListener('bmxResponse', e => {
    const { operation, response, problems, error } = e.detail;
    out.textContent = error ? `bmxResponse: ${error}` : `bmxResponse: ${operation.key} answered ${response.status} in ${response.duration} ms${problems.length ? `, ${problems.length} differences from the schema` : ''}.`;
  });
</script>
<bmx-api-explorer spec-url="/openapi.yaml"></bmx-api-explorer>

Every request also appears as code - cURL, JavaScript, C# and Python - with the credentials replaced by placeholders, so a sample can be pasted into a ticket without a live key. mock answers from the description's own examples instead of a server (400 for bad input, 401 without credentials), for a developer portal before the API is live, or for a demonstration. fetcher sends through the page's own code (a proxy, a test double), and bmxRequest can be cancelled to send the request yourself.

Nothing is stored and nothing is sent anywhere but to the API: credentials live in memory until the page is closed (bmxAuthChange hands them over if the page wants to keep them, which it must do safely). A request goes straight from the reader's browser, so the API must allow it (CORS).

The list of operations is a navigation landmark with one tab stop (arrow keys move, Enter opens); every field is a labelled form control, mistakes are marked on the field and announced, Ctrl+Enter (Command+Enter) sends, and the response status is announced when it arrives.

Properties

PropertyAttributeTypeDefaultDescription
credentials property only BmxApiCredentials {} Credentials to start with, by security scheme id (from script). Mutable: the reader's changes are written back.
fetcher property only BmxApiFetcher — Sends requests instead of fetch (from script).
headingLevel heading-level number 2 The level of the operation's heading (1 to 5); sections are one below.
label label string — The element's accessible name. Default: the API's title.
languages languages BmxApiLanguage[] | string [...LANGUAGES] The code sample languages offered, in order: curl, javascript, csharp, python.
mock mock boolean false Answer from the description's examples instead of sending anything.
requestHeaders request-headers Record<string, string> | string — Headers every request carries, as an object or JSON (a tenant id, a trace header).
revealSecrets reveal-secrets boolean false Show credentials in code samples instead of placeholders.
selected selected string '' The chosen operation: GET /orders/{id} or an operationId. Empty shows the overview. Mutable.
server server string '' The chosen server (its URL as the description writes it, or its index). Mutable.
spec spec Record<string, unknown> | string — The API description: an object, or JSON or YAML text.
specUrl spec-url string — Where to fetch the description from (JSON or YAML), when spec is not set.
strings strings Partial<BmxApiExplorerStrings> | string — Words to show instead of the English ones, as an object or JSON.
timeout timeout number 30000 Milliseconds before a request is given up.
tryIt try-it boolean true Show the Send button and the editable fields. False makes it read-only documentation.

Events

EventDetailDescription
bmxAuthChange BmxApiAuthDetail Fired when the reader changes the credentials.
bmxLoad BmxApiLoadDetail Fired when the description has been read.
bmxRequest BmxApiRequestDetail Fired before a request is sent. Cancel it to send the request yourself.
bmxResponse BmxApiResponseDetail Fired when a response arrives, or the request fails.
bmxSelect BmxApiSelectDetail Fired when the reader chooses an operation.

Methods

MethodSignatureDescription
clearCredentials clearCredentials() => Promise<void> Forgets every credential.
getRequest getRequest() => Promise<BmxApiRequest | undefined> The request the chosen operation would send now.
getSnippet getSnippet(language?: BmxApiLanguage) => Promise<string> A code sample of the chosen operation's request (credentials as placeholders unless reveal-secrets).
getSpec getSpec() => Promise<BmxApiSpec | null> The description as read (null until it is).
selectOperation selectOperation(id: string) => Promise<boolean> Chooses an operation by key or operationId; empty shows the overview. Resolves whether it was found.
send send() => Promise<BmxApiResponseData | undefined> Sends the chosen operation's request as filled in. Resolves with the response (undefined when it failed or was cancelled).
setCredentials setCredentials(credentials: BmxApiCredentials) => Promise<void> Sets the credentials (merged with those set).
setFocus setFocus() => Promise<void> Focuses the list of operations.
setValue setValue(param: string, value: string, operation?: string) => Promise<void> Sets a parameter's value for an operation (default: the chosen one), by in:name (query:limit).

CSS shadow parts

PartDescription
code A code sample.
detail The chosen operation, or the overview.
method A method badge (GET, POST...).
nav The list of operations.
operation One operation in the list; also operation-selected.
response The response panel.
section A section of the detail (parameters, body, responses, code).
send The Send button.
sidebar The column with the server, authorization and operations.

CSS custom properties

PropertyDescription
--bmx-api-explorer-background The detail pane's background.
--bmx-api-explorer-code-background The background of code samples and response bodies.
--bmx-api-explorer-code-font-size The font size of code.
--bmx-api-explorer-height The element's height (each column scrolls inside it); auto lets it grow with the page.
--bmx-api-explorer-radius Corner radius of the element and its panels.
--bmx-api-explorer-sidebar-background The operations column's background.
--bmx-api-explorer-sidebar-width The operations column's width.