Spec configuration
Barbacane extends OpenAPI and AsyncAPI specs with custom x-barbacane-* extensions. These tell the gateway how to route requests, apply middleware, and connect to backends.
Extension Overview
| Extension | Location | Purpose |
|---|---|---|
x-barbacane-dispatch | Operation | Route request to a dispatcher (required) |
x-barbacane-middlewares | Root or Operation | Apply middleware chain |
Path Parameters
Regular Parameters
Use {paramName} for single-segment parameters — the parameter captures exactly one path segment:
paths:
/users/{id}/orders/{orderId}:
get:
parameters:
- name: id
in: path
required: true
schema:
type: string
- name: orderId
in: path
required: true
schema:
type: string
Wildcard Parameters
Use {paramName+} to capture all remaining path segments as a single value, including any / characters:
paths:
/files/{bucket}/{key+}:
get:
parameters:
- name: bucket
in: path
required: true
schema:
type: string
- name: key
in: path
required: true
allowReserved: true # tells client tooling not to percent-encode '/'
schema:
type: string
A GET /files/my-bucket/docs/2024/report.pdf request captures bucket=my-bucket and key=docs/2024/report.pdf.
Rules:
- The wildcard parameter must be the last segment of the path
- At most one wildcard parameter per path
- Parameter names use the same characters as regular params (alphanumeric and
_)
allowReserved note: This is advisory metadata for client generators and documentation tools — it signals that the value may contain unencoded / characters. Barbacane does not parse or enforce it, but including it produces correct client SDKs.
Project Manifest (barbacane.yaml)
The manifest declares the specs folder and plugins available to the gateway:
specs: ./specs/
plugins:
mock:
path: ./plugins/mock.wasm
http-upstream:
path: ./plugins/http-upstream.wasm
jwt-auth:
url: https://github.com/barbacane-dev/barbacane/releases/download/v0.7.0/jwt-auth.wasm
sha256: abc123...
specs (optional)
Path to a folder containing spec files (relative to the manifest). All *.yaml, *.yml, and *.json files in this folder are discovered as specs.
Used by:
barbacane dev— auto-discovers specs for compilation and file watchingbarbacane compile— falls back to this folder when--specis not provided
Drop-in spec fragments. Multi-file discovery means you can ship operator-facing fragments alongside the gateway and pull them in with a copy. The repository’s
schemas/ai-gateway.yamlis the canonical example — copy it intospecs/to bring up the full OpenAI-compatible AI gateway (/v1/chat/completions,/v1/responses,/v1/models) with oneai-proxyconfig shared via a YAML anchor. See AI Gateway for the walkthrough.
plugins (required)
Declares all WASM plugins used by your specs. Each plugin maps a name to a source:
- Local path:
path: ./plugins/name.wasm— relative to the manifest directory - Remote URL:
url: https://...— downloaded at compile time, cached in~/.barbacane/cache/plugins/ - Checksum (optional):
sha256: ...— integrity verification for remote plugins
Dispatchers
Every operation needs an x-barbacane-dispatch to tell Barbacane how to handle it:
paths:
/users:
get:
x-barbacane-dispatch:
name: http-upstream
config:
url: "https://api.example.com"
path: /api/v2/users
Dispatch Properties
| Property | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Dispatcher plugin name |
config | object | No | Plugin-specific configuration |
Built-in dispatchers: mock, http-upstream, lambda, kafka, nats, s3. See Dispatchers for configuration details.
Config values support secret references: env://VAR_NAME (environment variable) or file:///path/to/secret (file). See Secrets.
Middlewares
Middlewares process requests before dispatching and responses after.
Global Middlewares
Apply to all operations:
openapi: "3.1.0"
info:
title: My API
version: "1.0.0"
x-barbacane-middlewares:
- name: rate-limit
config:
quota: 100
window: 60
- name: cors
config:
allowed_origins: ["https://app.example.com"]
paths:
# ... all operations get these middlewares
Operation Middlewares
Apply to a specific operation (runs after global middlewares):
paths:
/admin/users:
get:
security:
- bearerAuth: []
x-barbacane-middlewares:
- name: oidc-auth
config:
issuer_url: "https://auth.example.com"
audience: "my-api"
required_scopes: "admin:read"
x-barbacane-dispatch:
name: http-upstream
config:
url: "https://api.example.com"
An operation that runs an authentication middleware needs a security requirement naming a scheme from components.securitySchemes; without one the compiler stops with E1057. The complete example below declares bearerAuth.
Middleware Merging
Operation middlewares are merged with global ones. If an operation middleware has the same name as a global one, the operation config overrides it. Non-overridden globals are preserved.
# Global: rate limit 100/min + cors
x-barbacane-middlewares:
- name: rate-limit
config:
quota: 100
window: 60
- name: cors
config:
allow_origin: "*"
paths:
/public/stats:
get:
# Override rate-limit; cors still applies from globals
x-barbacane-middlewares:
- name: rate-limit
config:
quota: 1000
window: 60
# Resolved chain: cors (global) → rate-limit (operation override)
Use an empty array to explicitly disable all middlewares for an operation:
x-barbacane-middlewares: [] # No middlewares at all
Middleware Chain Order
- Global middlewares (in order defined)
- Operation middlewares (in order defined)
- Dispatch
- Response middlewares (reverse order)
Complete Example
openapi: "3.1.0"
info:
title: E-Commerce API
version: "2.0.0"
# Global middlewares
x-barbacane-middlewares:
- name: correlation-id
config:
header_name: X-Request-ID
- name: cors
config:
allowed_origins: ["https://shop.example.com"]
- name: rate-limit
config:
quota: 200
window: 60
paths:
/health:
get:
operationId: healthCheck
x-barbacane-dispatch:
name: mock
config:
status: 200
body: '{"status":"healthy"}'
responses:
"200":
description: OK
/products:
get:
operationId: listProducts
x-barbacane-middlewares:
- name: cache
config:
ttl: 300
x-barbacane-dispatch:
name: http-upstream
config:
url: "https://api.shop.example.com"
path: /api/products
responses:
"200":
description: Product list
/orders:
post:
operationId: createOrder
security:
- bearerAuth: []
x-barbacane-middlewares:
- name: oidc-auth
config:
issuer_url: "https://auth.shop.example.com"
audience: "shop-api"
x-barbacane-dispatch:
name: http-upstream
config:
url: "https://api.shop.example.com"
path: /api/orders
responses:
"201":
description: Order created
/orders/{orderId}/pay:
post:
operationId: payOrder
security:
- bearerAuth: []
x-barbacane-middlewares:
- name: oidc-auth
config:
issuer_url: "https://auth.shop.example.com"
audience: "shop-api"
required_scopes: "orders:pay"
x-barbacane-dispatch:
name: http-upstream
config:
url: "https://payments.example.com" # Different backend!
path: /process/{orderId}
timeout: 45.0
responses:
"200":
description: Payment processed
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
AsyncAPI Support
Barbacane supports AsyncAPI 3.x for event-driven APIs. AsyncAPI specs work similarly to OpenAPI, with channels and operations instead of paths and methods.
Sync-to-Async Bridge Pattern
AsyncAPI send operations are accessible via HTTP POST requests. This enables clients to publish messages to Kafka or NATS through the gateway:
- Client sends HTTP POST to the channel address
- Gateway validates the message against the schema
- Dispatcher publishes to Kafka/NATS
- Gateway returns 202 Accepted
Basic AsyncAPI Example
asyncapi: "3.0.0"
info:
title: User Events API
version: "1.0.0"
channels:
userEvents:
address: /events/users
messages:
UserCreated:
contentType: application/json
payload:
type: object
required:
- userId
- email
properties:
userId:
type: string
format: uuid
email:
type: string
format: email
operations:
publishUserCreated:
action: send
channel:
$ref: '#/channels/userEvents'
x-barbacane-dispatch:
name: kafka
config:
brokers: "kafka.internal:9092"
topic: "user-events"
Channel Parameters
AsyncAPI channels can have parameters (like path params in OpenAPI):
channels:
orderEvents:
address: /events/orders/{orderId}
parameters:
orderId:
schema:
type: string
format: uuid
messages:
OrderPlaced:
payload:
type: object
Message Validation
Message payloads are validated against the schema before dispatch. Invalid messages receive a 400 response with validation details.
HTTP Method Mapping
| AsyncAPI Action | HTTP Method |
|---|---|
send | POST |
receive | GET |
Middlewares
AsyncAPI operations support the same middleware extensions as OpenAPI:
operations:
publishEvent:
action: send
channel:
$ref: '#/channels/events'
# Authenticated through the security scheme the server declares.
x-barbacane-middlewares:
- name: oidc-auth
config:
issuer_url: "https://auth.example.com"
audience: "events-api"
x-barbacane-dispatch:
name: kafka
config:
brokers: "kafka.internal:9092"
topic: "events"
API Lifecycle
Barbacane supports API lifecycle management through standard OpenAPI deprecation and the x-sunset extension.
Marking Operations as Deprecated
Use the standard OpenAPI deprecated field:
paths:
/v1/users:
get:
deprecated: true
summary: List users (deprecated, use /v2/users)
x-barbacane-dispatch:
name: http-upstream
config:
url: "https://api.example.com"
When a client calls a deprecated endpoint, the response includes a Deprecation: true header per draft-ietf-httpapi-deprecation-header.
Setting a Sunset Date
Use x-sunset to specify when an endpoint will be removed (per RFC 8594):
paths:
/v1/users:
get:
deprecated: true
x-sunset: "Sat, 31 Dec 2025 23:59:59 GMT"
x-barbacane-dispatch:
name: http-upstream
config:
url: "https://api.example.com"
The sunset date must be in HTTP-date format (RFC 9110). When set, the response includes a Sunset header per RFC 8594.
Example Response Headers
HTTP/1.1 200 OK
Deprecation: true
Sunset: Sat, 31 Dec 2025 23:59:59 GMT
Content-Type: application/json
Best Practices
- Mark deprecated first: Set
deprecated: truebefore setting a sunset date - Give advance notice: Set the sunset date at least 6 months in advance
- Update API docs: Include migration instructions in the operation summary or description
- Monitor usage: Track calls to deprecated endpoints via metrics
Validation
The compiler validates your spec:
barbacane validate --spec api.yaml
Errors you might see:
| Error Code | Meaning |
|---|---|
| E1010 | Routing conflict (same path+method in multiple specs) |
| E1020 | Missing x-barbacane-dispatch on operation |
| E1031 | Plaintext http:// upstream URL (use HTTPS or --allow-plaintext at compile time) |
| E1054 | Invalid path template (unbalanced braces, empty param name, duplicate param, {param+} not last segment, multiple wildcards) |
Next Steps
- Dispatchers - All dispatcher types and options
- Middlewares - Available middleware plugins
- CLI Reference - Full command options