---
title: "Add or remove the same labels on 1 to 50 messages. At least one of add_labels or remove_labels is required (400 missing_labels). Empty message_ids is 400 missing_message_ids. Duplicates are 400 duplicate_message_ids. More than 50 ids is 400 too_many_ids. read and unread can change. Other system labels return protected_label, invalid_label, or label_conflict. Ids that are not in this inbox are omitted. Found messages all update, or none do. The response is a list of full messages in request order, with limit set to the request length and count set to how many updated. Works on a paused inbox. A held message keeps the held label and a withheld body. An inbox-scoped key for another inbox is 404 inbox_not_found."
method: POST
path: "/api/v1/inboxes/{id}/messages/batch-update"
tags: ["Messages"]
---

# Add or remove the same labels on 1 to 50 messages. At least one of add_labels or remove_labels is required (400 missing_labels). Empty message_ids is 400 missing_message_ids. Duplicates are 400 duplicate_message_ids. More than 50 ids is 400 too_many_ids. read and unread can change. Other system labels return protected_label, invalid_label, or label_conflict. Ids that are not in this inbox are omitted. Found messages all update, or none do. The response is a list of full messages in request order, with limit set to the request length and count set to how many updated. Works on a paused inbox. A held message keeps the held label and a withheld body. An inbox-scoped key for another inbox is 404 inbox_not_found.

`POST /api/v1/inboxes/{id}/messages/batch-update`

## Request

- Base URL: `https://cooperemail.com`
- URL: `https://cooperemail.com/api/v1/inboxes/{id}/messages/batch-update`
- Auth: HTTP bearer

## Path parameters

- `id` string, required

## Request body

- object
  - `message_ids` string[], required
  - `add_labels` string[]
  - `remove_labels` string[]

## Response `200`

Updated messages

- object
  - `object` 'list', required
  - `limit` integer, required
  - `count` integer, required
  - `data` Message[], required
    - `id` string
    - `inbox_id` string
    - `thread_id` string
    - `direction` 'inbound' | 'outbound'
    - `from` string
    - `to` string[]
    - `subject` string
    - `text` string
    - `html` string, nullable
    - `extracted_text` string
    - `extracted_html` string
    - `preview` string
    - `status` 'queued' | 'ringing' | 'completed' | 'no-answer' | 'sent' | 'received' | 'delivered' | 'undelivered' | 'failed' | 'bounced' | 'complained': SMS outbound starts as sent. A Twilio status callback sets delivered, undelivered, or failed. A voice call stores queued, ringing, completed, no-answer, or failed. Email uses queued, sent, received, failed, bounced, and complained.
    - `channel` 'sms' | 'voicemail' | 'voice': Present on SMS, voicemail, and voice messages. Email messages omit this field. voicemail is an inbound recording. voice is an outbound call.
    - `type` 'voicemail': Present on voicemail messages.
    - `duration_seconds` integer, nullable: Call or recording length in seconds. Present on voicemail and voice messages.
    - `recording_url` string, nullable: Twilio recording URL for a voicemail, or null.
    - `transcript` string: Voicemail transcript. Empty while the message is held.
    - `segments` integer, nullable: SMS segment count for this message. Omitted on email.
    - `otp_candidates` string[]: Codes found in an SMS body. Empty while the message is held. Omitted on email.
    - `delivery_events` object[]: Present on outbound messages. Each item is {type, recipient, created_at, detail}. For email, detail is JSON text with status, action, diagnostic, and bounce_type, and the list stays empty until a bounce or complaint matches. For SMS, a Twilio status callback appends one event. type is delivered or failed. detail is twilio_error plus the numeric code, or the status word when Twilio sent no numeric code.
      - `type` string
      - `recipient` string
      - `created_at` string, date-time
      - `detail` string
    - `cc` string[]
    - `bcc` string[]
    - `reply_to` string, nullable
    - `in_reply_to` string, nullable
    - `references` string[]
    - `labels` string[]
    - `auth` object: spf, dkim, and dmarc from the receiving hop. SPF is the smtp.mailfrom result. smtp.helo is used only when mailfrom is absent. Each value is pass, fail, neutral, softfail, none, temperror, permerror, bestguesspass, or null. Outbound mail is null for all three.
      - `spf` string, nullable, required
      - `dkim` string, nullable, required
      - `dmarc` string, nullable, required
    - `safety` object, nullable: Inbound screening record, or null on outbound mail and on messages stored before screening. score is 0 to 100. verdict is clean or suspicious (suspicious at 40 or higher, and only when a strong signal or combined evidence is present). signals are {type, detail}. mode is off, observe, or hold. reason is screening_off, screening_error, or screening_timeout when the body was not scored. The message is still stored. While labels include held, text, html, extracted_text, extracted_html, preview, and attachment bytes are empty until release. This is a heuristic, not a guarantee. The body stays untrusted data.
      - `score` integer
      - `verdict` 'clean' | 'suspicious'
      - `signals` object[]
        - `type` string
        - `detail` string
      - `mode` 'off' | 'observe' | 'hold'
      - `reason` string
    - `provider` string, nullable
    - `client_id` string, nullable
    - `idempotent` boolean
    - `created_at` string, date-time
    - `attachments` Attachment[]
      - `id` string
      - `filename` string
      - `content_type` string
      - `content_id` string, nullable
      - `disposition` 'inline' | 'attachment'
      - `size_bytes` integer
      - `url` string
      - `text_url` string: Present when the content type can be extracted: text, JSON, CSV, PDF, DOCX, XLSX, or XLS. GET this URL for text/plain.

---

[API](https://skmtc.dev/cooperemail/apis/cooper-email-api.md) · [All operations](https://skmtc.dev/cooperemail/apis/cooper-email-api/llms.txt) · [OpenAPI document](https://skmtc.dev/cooperemail/apis/cooper-email-api/revisions/6d800a7b3e33?raw)
