Vercel Queues API reference
The Vercel Queues API is a REST API for publishing, consuming, and managing messages. Endpoints are accessed through region-specific domains in the format https://{region}.vercel-queue.com/api/v3, where {region} is a Vercel region code (for example, iad1, fra1, sfo1).
All endpoints require a Vercel OIDC token in the Authorization header:
Authorization: Bearer <vercel-oidc-token>The token is a JWT verified against Vercel's JWKS endpoint. It contains claims for your team, project, and environment, which are used to scope all requests.
The following headers are used across multiple endpoints:
| Header | Type | Required | Default | Description |
|---|---|---|---|---|
Authorization | string | Yes | - | Bearer <vercel-oidc-token> |
Vqs-Deployment-Id | string | No | - | Deployment ID for per-deployment isolation. When omitted, requests operate in deploymentless mode |
Topic names and consumer group names must match the pattern ^[A-Za-z0-9_\-]+$ (alphanumeric characters, hyphens, and underscores only).
Each region has its own domain. Use the region code as a subdomain to route requests to a specific region:
POST https://fra1.vercel-queue.com/api/v3/topic/ordersMessages sent to one region cannot be consumed from another. For example, a message published to iad1 can only be read by consumers in iad1. See the regions documentation for the full list of available region codes.
POST /api/v3/topic/{topic}
Publishes a message to a topic. The request body is the raw message payload.
| Header | Type | Required | Default | Description |
|---|---|---|---|---|
Content-Type | string | No | - | MIME type of the message payload. Preserved and returned to consumers |
Vqs-Retention-Seconds | integer | No | 24 hours | Message TTL. Minimum 60 seconds, maximum 24 hours (86,400 seconds) |
Vqs-Delay-Seconds | integer | No | Zero seconds | Delay before message becomes visible. Cannot exceed Vqs-Retention-Seconds |
Vqs-Idempotency-Key | string | No | - | Deduplication key. Duplicate messages are silently dropped out-of-band |
Raw binary payload. The entire request body is stored as the message content.
201 Created — Message stored and delivered to consumers:
{
"messageId": "msg_abc123..."
}The Vqs-Message-Id response header also contains the assigned message ID.
202 Accepted — Message stored but delivery is deferred. This happens during regional failover, when the message is temporarily stored in a neighboring region and will be relocated and delivered once the target region recovers:
{
"deferred": true
}Message IDs are opaque strings. Do not assume a specific length, format, or structure. The values shown in this documentation are illustrative.
When you provide Vqs-Idempotency-Key, Vercel deduplicates based on a hash of the key. Deduplication is handled out-of-band, so SendMessage always returns successfully. The duplicate message is silently dropped before it reaches any consumer. The original message continues to be delivered with at-least-once semantics.
If you use ReceiveMessageById to fetch a duplicate by its ID, the endpoint returns 409 with the originalMessageId, allowing you to follow the redirect to the original message.
The deduplication window lasts for the entire lifetime of the original message (up to its TTL), so you're protected from duplicates for the full retention period.
| Status | Description |
|---|---|
400 | Invalid topic name, retention, or delay value |
401 | Missing or invalid authentication token |
429 | Rate limited |
POST /api/v3/topic/{topic}/consumer/{consumer}
Receives available messages from the topic for the specified consumer group. Returns immediately with available messages, or 204 No Content if the topic is empty.
| Header | Type | Required | Default | Description |
|---|---|---|---|---|
Accept | string | Yes | - | Response format: multipart/mixed or application/x-ndjson |
Vqs-Max-Messages | integer | No | 1 | Maximum messages to return. Min: 1, max: 10 |
Vqs-Visibility-Timeout-Seconds | integer | No | 60 seconds | Duration that received messages are hidden from other consumers. Set to zero seconds to peek without leasing |
Vqs-Max-Concurrency | integer | No | Unlimited | Maximum messages in-flight simultaneously for this consumer group. Returns 429 when exceeded |
The Accept header controls the response format. multipart/mixed is recommended for best performance as it supports true streaming of binary payloads without encoding overhead. application/x-ndjson is provided for compatibility with clients that cannot parse multipart responses. When both formats are specified, multipart/mixed takes precedence.
multipart/mixed (recommended)
Each message is a separate MIME part with the following headers:
| Header | Type | Description |
|---|---|---|
Content-Type | string | Original MIME type of the message payload |
Vqs-Message-Id | string | Unique message identifier |
Vqs-Receipt-Handle | string | Opaque handle for acknowledging or extending the lease |
Vqs-Delivery-Count | integer | Number of times this message has been delivered (starts at 1) |
Vqs-Timestamp | string | ISO 8601 timestamp of when the message was sent |
Vqs-Expires-At | string | ISO 8601 timestamp of when the message expires |
Example response:
--vqs-boundary-550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json
Vqs-Message-Id: msg_abc123...
Vqs-Receipt-Handle: rh_xyz789...
Vqs-Delivery-Count: 1
Vqs-Timestamp: 2026-01-13T12:00:00.000Z
Vqs-Expires-At: 2026-01-14T12:00:00.000Z
{"order": "12345", "action": "process"}
--vqs-boundary-550e8400-e29b-41d4-a716-446655440000--application/x-ndjson (compatibility)
Provided for clients that cannot parse multipart responses. Payloads are base64-encoded, which adds overhead compared to multipart/mixed. One JSON object per line:
{"messageId":"msg_abc123...","receiptHandle":"rh_xyz789...","deliveryCount":1,"timestamp":"2026-01-13T12:00:00.000Z","expiresAt":"2026-01-14T12:00:00.000Z","contentType":"application/json","body":"eyJvcmRlciI6ICIxMjM0NSJ9"}| Field | Type | Description |
|---|---|---|
messageId | string | Unique message identifier |
receiptHandle | string | Opaque handle for acknowledging or extending the lease |
deliveryCount | integer | Number of times this message has been delivered |
timestamp | string | ISO 8601 timestamp of when the message was sent |
expiresAt | string | ISO 8601 timestamp of when the message expires |
contentType | string | Original MIME type of the message payload |
body | string | Base64-encoded message payload |
204 No Content is returned when no messages are available.
| Status | Description |
|---|---|
400 | Missing or unsupported Accept header, invalid parameters |
401 | Missing or invalid authentication token |
429 | Concurrency limit exceeded or rate limited |
POST /api/v3/topic/{topic}/consumer/{consumer}/id/{messageId}
Receives a specific message by its ID and claims it for the consumer group. Useful for callback-driven processing where the message ID is known in advance.
| Header | Type | Required | Default | Description |
|---|---|---|---|---|
Accept | string | Yes | - | Response format: multipart/mixed or application/x-ndjson |
Vqs-Visibility-Timeout-Seconds | integer | No | 60 seconds | Lease duration. Minimum zero seconds, maximum 60 minutes (3,600 seconds) |
Vqs-Max-Concurrency | integer | No | Unlimited | Maximum concurrent in-flight messages for this consumer group |
200 OK with the same format as ReceiveMessages, containing one message.
| Status | Description |
|---|---|
400 | Invalid parameters or topic name |
401 | Missing or invalid authentication token |
404 | Message not found |
409 | Message locked by another consumer, or duplicate message (returns originalMessageId) |
410 | Message already acknowledged |
429 | Concurrency limit exceeded or rate limited |
DELETE /api/v3/topic/{topic}/consumer/{consumer}/lease/{receiptHandle}
Acknowledges successful processing of a message. The message is permanently removed from the consumer group's view.
The receiptHandle must be URL-encoded in the path.
None.
204 No Content
| Status | Description |
|---|---|
400 | Invalid topic name or receipt handle format |
401 | Missing or invalid authentication token |
404 | Message not found or already acknowledged |
409 | Lease expired or receipt handle mismatch |
429 | Rate limited |
PATCH /api/v3/topic/{topic}/consumer/{consumer}/lease/{receiptHandle}
Extends the visibility timeout on a currently leased message. Use this to request more processing time before the lease expires.
An alternate URL for the same operation is also available:
PATCH /api/v3/topic/{topic}/consumer/{consumer}/lease/{receiptHandle}/visibility
The receiptHandle must be URL-encoded in the path.
{
"visibilityTimeoutSeconds": 120
}| Field | Type | Required | Description |
|---|---|---|---|
visibilityTimeoutSeconds | integer | Yes | New visibility timeout from now. Minimum zero seconds, maximum 60 minutes (3,600 seconds). Set to zero seconds to release the message immediately |
The visibility timeout cannot extend beyond the message's expiration time. If it would, the request returns 400 with the message's expiration timestamp.
200 OK
{
"success": true
}| Status | Description |
|---|---|
400 | Invalid visibility timeout, exceeds max, or would extend beyond message expiration |
401 | Missing or invalid authentication token |
404 | Message not found or already acknowledged |
409 | Lease expired or receipt handle mismatch |
429 | Rate limited |
| Limit | Min | Max | Default |
|---|---|---|---|
| Message retention (TTL) | 60 seconds | 24 hours | 24 hours |
| Delay before visible | Zero seconds | Retention value | Zero seconds |
| Visibility timeout | Zero seconds | 60 minutes | 60 seconds |
| Messages per receive | 1 | 10 | 1 |
| Max concurrency | 1 | Unlimited | Unlimited |
Was this helpful?