Skip to content

Claude Message Batches

Use Anthropic-compatible Message Batches while Model Gate executes every item through its durable internal queue.

Existing Batch read/control operations remain available at zero balance for a valid active key. Creating a batch with POST /v1/messages/batches requires a positive balance and available spending allowance. Individual items must still satisfy the current limits when execution starts; insufficient funds can leave them queued. Active-job and queued-item quotas are independent limits, not evidence of an account charge.

Model Gate implements an Anthropic-compatible Message Batches API on https://api.model-gate.com. It is a compatibility layer: Model Gate stores the batch durably and executes each item through the normal Model Gate /v1/messages path. It does not submit a provider-native Anthropic batch upstream.

Use a normal Model API key (mg_live_...). Every item is accounted as an individual request with request_mode=batch, batch_protocol=claude, the batch ID, and its custom_id.

Streaming is not supported inside a batch. Model aliases are resolved before the item is queued.

Create a message batch

Request

curl https://api.model-gate.com/v1/messages/batches \
  -H "x-api-key: mg_live_..." \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "requests": [
      {
        "custom_id": "summary-1",
        "params": {
          "model": "ch-47",
          "max_tokens": 256,
          "messages": [{"role":"user","content":"Summarize this text."}]
        }
      }
    ]
  }'

Response — 200

{
  "id": "msgbatch_01K...",
  "type": "message_batch",
  "processing_status": "in_progress",
  "request_counts": {
    "processing": 1,
    "succeeded": 0,
    "errored": 0,
    "canceled": 0,
    "expired": 0
  },
  "ended_at": null,
  "created_at": "2026-08-13T08:30:00Z",
  "expires_at": "2026-08-14T08:30:00Z",
  "cancel_initiated_at": null,
  "results_url": null
}

Retrieve a batch

Request

curl https://api.model-gate.com/v1/messages/batches/msgbatch_01K... \
  -H "x-api-key: mg_live_..."

Response — ended

{
  "id": "msgbatch_01K...",
  "type": "message_batch",
  "processing_status": "ended",
  "request_counts": {
    "processing": 0,
    "succeeded": 1,
    "errored": 0,
    "canceled": 0,
    "expired": 0
  },
  "ended_at": "2026-08-13T08:30:04Z",
  "results_url": "https://api.model-gate.com/v1/messages/batches/msgbatch_01K.../results"
}

Read results

Results are returned as JSON Lines. Do not assume that application logic depends on the original input order; match results by custom_id.

Request

curl https://api.model-gate.com/v1/messages/batches/msgbatch_01K.../results \
  -H "x-api-key: mg_live_..."

Response — 200

{"custom_id":"summary-1","result":{"type":"succeeded","message":{"id":"msg_...","type":"message","role":"assistant","content":[{"type":"text","text":"..."}]}}}

List batches

limit defaults to 20 and must be from 1 to 100. Use after_id or before_id for cursor pagination; do not send both in one request.

Request

curl "https://api.model-gate.com/v1/messages/batches?limit=20&after_id=msgbatch_01K..." \
  -H "x-api-key: mg_live_..."

Response — 200

{
  "data": [],
  "has_more": false,
  "first_id": null,
  "last_id": null
}

Cancel a batch

Cancel stops queued items from being claimed. An item already processing may finish.

Request

curl -X POST https://api.model-gate.com/v1/messages/batches/msgbatch_01K.../cancel \
  -H "x-api-key: mg_live_..."

Response — 200

{
  "id": "msgbatch_01K...",
  "type": "message_batch",
  "processing_status": "canceling",
  "request_counts": {
    "processing": 1,
    "succeeded": 0,
    "errored": 0,
    "canceled": 0,
    "expired": 0
  }
}

Delete an ended batch

Delete is accepted only after the batch has reached a terminal state.

Request

curl -X DELETE https://api.model-gate.com/v1/messages/batches/msgbatch_01K... \
  -H "x-api-key: mg_live_..."

Response — 200

{
  "id": "msgbatch_01K...",
  "type": "message_batch_deleted"
}

Recovery semantics

Batch execution is at-least-once, not exactly-once. An interruption can lead to another attempt even when the provider accepted the first request. The Model Gate request ID stays the same, and duplicate-billing protection applies to already-finished requests. External tool actions still need application-level idempotency.

Before an item starts, the account balance and key/group spending allowance must still permit execution. Otherwise-valid items stay queued when funds or allowance are exhausted, without consuming an attempt. A top-up, usage reset or limit increase can make them eligible again. There is no worst-case cost reservation: concurrent accepted items can finish above the remaining balance or limit; only later items are held.

Pricing and accounting

Each batch item uses the same model routing, token accounting, pricing snapshot, usage valuation, API-key/group limits, and settlement logic as a normal Model Gate request. Your account pricing may include a Batch request price coefficient. The default is 1; check your applicable pricing before submission.

For example, with normal Model Gate cost 0.02 and batch coefficient 0.5, the actual account debit is 0.01. The saved official-provider reference amount is not multiplied by this Model Gate batch coefficient. Native requests using "async": true are also not affected.

If the coefficient differs from 1, it is shown on the Model prices page. The minimal /v1/models response no longer includes batch_pricing or batch_cost; the actual billing coefficient and saved request accounting are unchanged.

Errors

Invalid or duplicate custom_id, an unknown model, stream:true, nested async:true, an oversized request, or an invalid body returns a normal Anthropic-style error response.

{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "summary-1: stream=true is not supported inside a batch"
  }
}