> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bayse.markets/llms.txt
> Use this file to discover all available pages before exploring further.

# Batch cancel orders

> Cancel up to 100 CLOB orders across one or more markets in a single round-trip

Cancel up to **100 CLOB orders** in a single request. Order IDs may belong to different markets and events. CLOB-only: any AMM order is rejected per-item with `UNSUPPORTED_ENGINE`. Ownership is enforced upstream — order IDs the caller does not own return `ORDER_NOT_FOUND`.

See the [Batch orders](/concepts/batch-orders) concept page for limits, semantics, and rate-limit behavior.

## Authentication

Write authentication required — `X-Public-Key`, `X-Timestamp`, and `X-Signature` headers. See the [Authentication guide](/authentication).

## Headers

<ParamField header="Idempotency-Key" type="string">
  Optional. 1–255 characters of `[A-Za-z0-9_-]`. Retries within 24 hours that share the same key, body, and route replay the original response with `Idempotent-Replayed: true`. A retry with the same key but a different body is rejected with `422`. A concurrent retry (sent while the first is still in flight) is rejected with `409` — back off briefly and retry once the first call has finished. Transient responses (`5xx`, `429`, `408`) are not cached, so you can recover by retrying.
</ParamField>

## Request body

<ParamField body="orderIds" type="array" required>
  1–100 order UUIDs to cancel. Each ID is processed independently — failures on one ID do not abort the rest of the batch.
</ParamField>

## Example request

<CodeGroup>
  ```bash cURL theme={null}
  PUBLIC_KEY="pk_live_abcdef123456"
  SECRET_KEY="sk_live_secret789xyz"
  TIMESTAMP=$(date +%s)
  METHOD="DELETE"
  URL_PATH="/v1/pm/orders/batch"
  BODY='{"orderIds":["f6a7b8c9-d0e1-2345-fabc-678901234567","a1b2c3d4-e5f6-7890-abcd-ef1234567890"]}'

  BODY_HASH=$(printf '%s' "$BODY" | openssl dgst -sha256 -hex 2>/dev/null | sed 's/.*= //')
  PAYLOAD="${TIMESTAMP}.${METHOD}.${URL_PATH}.${BODY_HASH}"
  SIGNATURE=$(printf '%s' "$PAYLOAD" | openssl dgst -sha256 -hmac "$SECRET_KEY" -binary | base64)

  curl -X DELETE "https://relay.bayse.markets${URL_PATH}" \
    -H "X-Public-Key: ${PUBLIC_KEY}" \
    -H "X-Timestamp: ${TIMESTAMP}" \
    -H "X-Signature: ${SIGNATURE}" \
    -H "Idempotency-Key: 9d3f2c0e-7b1a-4e5d-9f80-3a8b1c2d4e5f" \
    -H "Content-Type: application/json" \
    -d "$BODY"
  ```

  ```javascript Node.js theme={null}
  import crypto from 'crypto';

  const publicKey = 'pk_live_abcdef123456';
  const secretKey = 'sk_live_secret789xyz';
  const timestamp = Math.floor(Date.now() / 1000);
  const method = 'DELETE';
  const path = '/v1/pm/orders/batch';
  const body = JSON.stringify({
    orderIds: [
      'f6a7b8c9-d0e1-2345-fabc-678901234567',
      'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
    ],
  });

  const bodyHash = crypto.createHash('sha256').update(body).digest('hex');
  const payload = `${timestamp}.${method}.${path}.${bodyHash}`;
  const signature = crypto
    .createHmac('sha256', secretKey)
    .update(payload)
    .digest('base64');

  const response = await fetch(`https://relay.bayse.markets${path}`, {
    method,
    headers: {
      'X-Public-Key': publicKey,
      'X-Timestamp': timestamp.toString(),
      'X-Signature': signature,
      'Idempotency-Key': crypto.randomUUID(),
      'Content-Type': 'application/json',
    },
    body,
  });
  const result = await response.json();
  ```

  ```python Python theme={null}
  import hmac, hashlib, base64, json, time, uuid, requests

  public_key = 'pk_live_abcdef123456'
  secret_key = 'sk_live_secret789xyz'
  timestamp = int(time.time())
  method = 'DELETE'
  path = '/v1/pm/orders/batch'
  body = json.dumps({
      'orderIds': [
          'f6a7b8c9-d0e1-2345-fabc-678901234567',
          'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
      ],
  })

  body_hash = hashlib.sha256(body.encode()).hexdigest()
  payload = f'{timestamp}.{method}.{path}.{body_hash}'
  signature = base64.b64encode(
      hmac.new(secret_key.encode(), payload.encode(), hashlib.sha256).digest()
  ).decode()

  resp = requests.delete(
      f'https://relay.bayse.markets{path}',
      headers={
          'X-Public-Key': public_key,
          'X-Timestamp': str(timestamp),
          'X-Signature': signature,
          'Idempotency-Key': str(uuid.uuid4()),
          'Content-Type': 'application/json',
      },
      data=body,
  )
  result = resp.json()
  ```

  ```go Go theme={null}
  import (
      "crypto/hmac"
      "crypto/sha256"
      "encoding/base64"
      "encoding/hex"
      "fmt"
      "strconv"
      "strings"
      "time"
  )

  timestamp := time.Now().Unix()
  method := "DELETE"
  urlPath := "/v1/pm/orders/batch"
  body := []byte(`{"orderIds":["f6a7b8c9-d0e1-2345-fabc-678901234567","a1b2c3d4-e5f6-7890-abcd-ef1234567890"]}`)

  bodySum := sha256.Sum256(body)
  bodyHash := hex.EncodeToString(bodySum[:])
  payload := fmt.Sprintf("%d.%s.%s.%s", timestamp, method, urlPath, bodyHash)
  mac := hmac.New(sha256.New, []byte("sk_live_secret789xyz"))
  mac.Write([]byte(payload))
  signature := base64.StdEncoding.EncodeToString(mac.Sum(nil))

  req, _ := http.NewRequest("DELETE", "https://relay.bayse.markets"+urlPath, strings.NewReader(string(body)))
  req.Header.Set("X-Public-Key", "pk_live_abcdef123456")
  req.Header.Set("X-Timestamp", strconv.FormatInt(timestamp, 10))
  req.Header.Set("X-Signature", signature)
  req.Header.Set("Idempotency-Key", "9d3f2c0e-7b1a-4e5d-9f80-3a8b1c2d4e5f")
  req.Header.Set("Content-Type", "application/json")
  resp, _ := http.DefaultClient.Do(req)
  ```
</CodeGroup>

<Note>
  This DELETE carries a JSON body, so the signing payload's `bodyHash` is the SHA-256 hash of the body — not the empty hash used for body-less DELETEs like [Cancel order](/api-reference/pm/cancel-order).
</Note>

## Response

<ResponseField name="engine" type="string">
  Always `CLOB` for batch endpoints today.
</ResponseField>

<ResponseField name="results" type="array">
  Per-order outcomes, in the same order as the request.

  <Expandable title="Result fields">
    <ResponseField name="orderId" type="string">
      The order UUID submitted in the request.
    </ResponseField>

    <ResponseField name="success" type="boolean">
      `true` if the cancel was accepted upstream, `false` if it failed.
    </ResponseField>

    <ResponseField name="error" type="object">
      Present when `success` is `false`.

      <Expandable title="Error fields">
        <ResponseField name="code" type="string">
          Machine-readable code (e.g. `ORDER_NOT_FOUND`, `ORDER_NOT_CANCELLABLE`, `UNSUPPORTED_ENGINE`).
        </ResponseField>

        <ResponseField name="message" type="string">
          Human-readable description.
        </ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="summary" type="object">
  <Expandable title="Summary fields">
    <ResponseField name="total" type="integer">Total IDs submitted.</ResponseField>
    <ResponseField name="succeeded" type="integer">IDs cancelled successfully.</ResponseField>
    <ResponseField name="failed" type="integer">IDs that failed to cancel.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "engine": "CLOB",
    "results": [
      { "orderId": "f6a7b8c9-d0e1-2345-fabc-678901234567", "success": true },
      {
        "orderId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "success": false,
        "error": {
          "code": "ORDER_NOT_FOUND",
          "message": "Order not found"
        }
      }
    ],
    "summary": { "total": 2, "succeeded": 1, "failed": 1 }
  }
  ```

  ```json 400 Bad Request theme={null}
  {
    "error": "bad_request",
    "message": "invalid request body: orderIds[] required (1..100 UUIDs)",
    "statusCode": 400
  }
  ```

  ```json 409 Conflict theme={null}
  {
    "error": "conflict",
    "message": "A request with this Idempotency-Key is already in flight; retry shortly.",
    "statusCode": 409
  }
  ```

  ```json 422 Unprocessable Entity theme={null}
  {
    "error": "unprocessable_entity",
    "message": "Idempotency-Key reused with a different request body",
    "statusCode": 422
  }
  ```

  ```json 429 Too Many Requests theme={null}
  {
    "message": "Rate limit exceeded for batch payload size. Please reduce the batch or try again later.",
    "retryAfter": 2
  }
  ```
</ResponseExample>

<Note>
  Only CLOB orders with status `open` or `partial_filled` can be cancelled. AMM orders execute instantly and cannot be cancelled — sell your shares to exit instead. Batch cancel charges **one rate-limit token per ID**.
</Note>
