HTML version: https://cooperemail.com/privacy

Privacy

# Privacy policy

Last updated 24 October 2026. This policy describes how Cooper Email handles personal data for the website, HTTP API, hosted MCP, and ChatGPT / Claude / Cursor connectors. It is written to be skimmed: each heading answers one reviewer question.

On this page

- [Operator](#operator)
- [Scope of this policy](#scope)
- [Data collected](#data)
- [Purposes of use](#purposes)
- [Recipients and processors](#recipients)
- [International transfers](#transfers)
- [Retention](#retention)
- [User controls](#controls)
- [ChatGPT plugin and connectors](#chatgpt)
- [Current tool inputs and outputs](#tools)
- [Children](#children)
- [What we do not do](#not)
- [SMS alerts](#sms)
- [Changes](#changes)
- [Contact](#contact)

## Operator

Cooper Email is operated by Avatar 8 LLC ([ops@avatar33.com](mailto:ops@avatar33.com)). Product host: cooperemail.com. Branding and legal notices use Avatar 8 LLC only. Support and privacy requests go to [ops@avatar33.com](mailto:ops@avatar33.com) — that is the only public operator address.

## Scope of this policy

This policy covers personal data processed when you:

- visit cooperemail.com or read docs, blog, or this page;
- create an inbox or call the HTTP API at `/api/v1`;
- connect the hosted MCP at [/mcp](/mcp) from ChatGPT, Claude, Cursor, or another client;
- install Cooper as a ChatGPT plugin or custom connector (OAuth or API key);
- send or receive mail at a Cooper address (username@cooperemail.com);
- email [ops@avatar33.com](mailto:ops@avatar33.com) for support or deletion.

OpenAI, Anthropic, Cursor, and other AI clients have their own privacy policies for chat history, model training choices, and account credentials. This policy covers what Cooper itself stores and what Cooper returns to those clients.

## Data collected

We store the following when you use the service. This list matches the production schema and live tools. We do not collect payment cards, precise location, advertising identifiers, or ChatGPT / Claude account passwords.

### Account identifiers

Cooper account id and created time. Accounts have no separate login email or password in the database — identity is the account id plus API keys or OAuth tokens.

### Custom domains

When an account adds a hostname, we store the domain, a verify token, DNS status, and whether records were written on a zone the operator already controls. We do not buy domains or create new DNS zones.

### API key hashes

SHA-256 of `coop_live_` keys, plus key id, name, prefix, created time, and last-used time. The plaintext key is shown once (onboard or `POST /api/v1/keys`) and is not stored.

### OAuth tokens, clients, and session cookie

- OAuth `client_id`, client name, redirect URIs, grant types, token-endpoint auth method, hashed client secret if one was issued, optional JWKS URI and signing algorithm, and created time.
- Hashed authorization codes, PKCE challenge, redirect URI, scope (currently `email`), resource URL, expiry, and used-at time.
- Hashed access tokens (`coop_at_`), hashed refresh tokens, scope, resource URL, and expiry. Plaintext tokens are not stored.
- Private-key JWT assertion identifiers (jti + client_id + expiry) so a used assertion cannot be replayed.
- HttpOnly cookie `cooper_oauth` on the authorize/consent screens: a signed account id, 7-day max-age, SameSite=Lax. It is not a ChatGPT or Claude password.

### Inbox addresses

Username, full email (username@cooperemail.com), optional display name, inbox id, account id, created time. Custom-domain DNS instructions on [/domains](/domains) are documentation; Cooper does not store a separate custom-domain registration table today.

### Message bodies, HTML, attachments, and metadata

From, To, Cc, Bcc, Reply-To, Subject, text body, HTML body, extracted_text / extracted_html (quoted history stripped), preview, In-Reply-To, References, labels, direction, status, thread id, client_id, created time, and which sending path was used (`cloudflare`, `resend`, or inbound). We also store the provider message id internally for delivery debugging; it is not returned on the API or MCP tools. While a message is held, API and MCP responses omit the body, preview, and attachment bytes until it is released. The stored copy is kept.

Attachment files (bytes) plus filename, content type, size, content_id, disposition, and a download URL that requires the same Bearer key.

### Internal mail headers

RFC822 headers (including Message-ID) are stored so inbound identity and threading work. They are not returned on the API or MCP tools.

### Search index

Full-text search (FTS5) indexes subject, extracted_text, from address, and to addresses for the account. Attachment bytes are not indexed. The body of a held message is left out of the index until the message is released.

### Webhooks

Callback URL, event names (`message.received`, `message.sent`, `task.received`, `owner.reply`), signing secret, and created time.

### Human owners, updates, and tasks

When an agent registers a human owner, we store that email address, a digest preference (immediate or daily), verification status, a hashed confirmation token and code, and an unsubscribe token so later emails can include a one-click unsubscribe link. Update logs store the kind, title, text, https links, and delivery status. Tasks created from a verified owner or allowlisted sender store the sender address, the new reply text, quoted history, optional task id, and SPF, DKIM, and DMARC results from the receiving hop. A task is created only when DMARC passes or DKIM passes and aligns with the From domain, unless that inbox opts out. Confirmation secrets are not returned on the API after the email is sent.

### Dashboard counts

`GET /api/v1/stats` computes inbox, message, inbound, outbound, and webhook counts (plus a 14-day by-day rollup) from existing rows. Cooper does not keep a separate analytics or profiling table.

### Tool arguments from AI clients

When ChatGPT, Claude, Cursor, or another client calls a Cooper tool, Cooper receives the tool name and the argument values that client sends (for example a username, subject, or message body the model chose). Those arguments become the stored or sent mail described above when the tool is a write. See [ChatGPT plugin and connectors](#chatgpt) and [Current tool inputs and outputs](#tools).

### Support mail

If you email [ops@avatar33.com](mailto:ops@avatar33.com), we receive whatever you put in that message so we can answer or delete the account.

### IP and request logs

Cooper does not write client IP addresses into the mail database. The one exception is an SMS opt-in at [/sms-opt-in](/sms-opt-in), which records the IP address of the request as consent evidence (see [SMS alerts](#sms)). Vercel (hosting) and Cloudflare (email and workers) may record IP, User-Agent, URL, and status in their own operational logs for abuse prevention and reliability. Cooper does not run a first-party advertising pixel, analytics SDK, or behavioral profiler on the marketing site.

## Purposes of use

- **Email API and MCP** — create inboxes, send and receive mail, list and search messages, and register webhooks from ChatGPT, Claude, Cursor, or HTTP clients.
- **Authentication** — verify API keys and OAuth access tokens; record last-used time on keys; complete ChatGPT / Claude Connect.
- **Deliver mail** — send outbound Internet mail and accept inbound Internet mail for your inbox.
- **Search** — index subject, extracted_text, and addresses so tools can find messages.
- **Abuse prevention and operations** — keep the service running, debug delivery failures internally, and stop abuse. Operator access is limited to running the service.

We do not sell mailbox contents. We do not sell personal data. We do not use mailbox contents for advertising, and we do not train foundation models on your mail.

## Recipients and processors

We share data with the processors the code actually uses, only to operate Cooper Email:

- **Vercel** — hosts the website and API (cooperemail.com). Receives HTTPS requests (URL, headers the platform logs, request bodies for API/MCP calls).
- **Turso / libSQL** — production database for accounts, hashed keys, OAuth records, inboxes, messages, attachments, search index, and webhooks.
- **Cloudflare Email Routing** — receives inbound Internet mail for *@cooperemail.com.
- **Cloudflare Workers** — the cooper-inbound-email Worker parses the inbound message and forwards subject, text, HTML, headers, and attachments to Cooper.
- **Cloudflare Email Sending** — default outbound send path. Receives From, To, Cc, Bcc, Reply-To, subject, text, HTML, headers we set for delivery, and attachments.
- **Resend** — outbound fallback when Cloudflare Email Sending is unavailable or when the operator sets Cooper to send via Resend. Receives the same outbound fields.
- **Stripe** — checkout, subscriptions, and the customer portal when billing is configured. Receives the account id and an optional email. Card numbers stay at Stripe.
- **Twilio** — SMS delivery, only for owners who opted in at [/sms-opt-in](/sms-opt-in). Receives the opted-in mobile number and the text of each message, only to deliver the texts that owner opted into.
- **Webhook URLs you register** — Cooper POSTs message.received / message.sent events (sanitized message fields, not raw headers or provider ids) to the HTTPS URL you provide.
- **OpenAI, Anthropic, Cursor, or other clients you connect** — receive only the tool arguments that client sends and the minimized tool outputs described below, after you connect the plugin or paste an API key. They do not get RFC822 headers, provider ids, delivery flags, or Cooper session/trace ids.
- **Mail recipients you address** — people or systems in To / Cc / Bcc receive the outbound message you asked Cooper to send.

We do not sell personal data. We do not use mailbox contents for advertising. We disclose data if required by law or to stop ongoing abuse; we do not sell it as a product.

No mobile information will be shared with third parties or affiliates for marketing or promotional purposes. All the above categories exclude text messaging originator opt-in data and consent; this information will not be shared with any third parties.

## International transfers

Cooper is operated from the United States. The processors above are US-hosted companies. Traffic and mail may also be handled at nearby Vercel or Cloudflare edge locations. We do not run a separate EU-only region. If you use Cooper from outside the United States, your data is processed in the United States (and on those global edges) for the purposes in this policy.

- **Vercel** — application hosting, United States, with a global CDN/edge.
- **Turso** — production database, United States.
- **Cloudflare** — Email Routing, Workers, and Email Sending on the operator Cloudflare account; edge processing is global.
- **Resend** — United States outbound email API, used only as the fallback or when the operator selects it.
- **Stripe** — United States billing processor for subscriptions.

## Retention

- **Account data (messages, attachments, inboxes, webhooks, API key hashes, search index, owner addresses, update logs, tasks)** — kept until you ask us to delete the account, or until we delete an inbox at your request. Owners can also unsubscribe from update emails without deleting the inbox.
- **Event log** — summaries used by the long-poll and the 25-second event stream. Deleted after 7 days. The stored messages themselves stay until you delete them. A durable event consumer stores the client_id, an optional type filter, an optional inbox id, and the committed cursor. It does not store a second copy of the message. Delete the consumer to remove that cursor.
- **OAuth access tokens** — hashed tokens expire after 30 days. Refresh replaces the previous hashed pair.
- **OAuth refresh tokens** — 90 days, then the client must reconnect.
- **OAuth authorization codes** — expire after 10 minutes and are marked used when exchanged.
- **OAuth session cookie** — 7 days, or until the browser clears it.
- **JWT assertion jti records** — until that assertion's expiry, then deleted on the next cleanup.
- **OAuth client registrations** — kept while the connector remains registered.
- **Platform logs** — Vercel and Cloudflare keep operational logs for their own short platform-defined periods. Cooper does not keep a separate IP table.
- **Support email** — kept as needed to finish the request you sent, then deleted with the account if you asked us to delete it.

## User controls

- **Delete** — email [ops@avatar33.com](mailto:ops@avatar33.com) from a mailbox you control and name the Cooper account id, inbox address, or API key prefix. We will delete your account, inboxes, messages, attachments, search index rows, keys, tokens, webhooks, owner addresses, update logs, and tasks.
- **Rotate API keys** — `POST /api/v1/keys` with your current Bearer key issues a new key. Email us to revoke an old key hash.
- **OAuth disconnect** — disconnect Cooper in ChatGPT / Claude / Cursor, and email us to delete stored hashed tokens and the client registration.
- **Do not connect** — you can use the HTTP API without ChatGPT. You can also decline the OAuth consent screen.
- **Export** — list and get messages through the API or MCP (`cooper_list_messages`, `cooper_get_message`, `cooper_search`). There is no separate bulk-export product; email us if you need a full mailbox dump.

## ChatGPT plugin and connectors

This section is for users who install Cooper Email as a ChatGPT plugin, ChatGPT custom connector, or another MCP client (Claude, Cursor). Hosted endpoint: [/mcp](/mcp). Tool catalog: [/api/v1/mcp/tools](/api/v1/mcp/tools). Human install notes: [/docs/mcp](/docs/mcp).

### How connect works (OAuth vs API key)

ChatGPT and Claude custom connectors sign in on Cooper's OAuth screen (authorization code + PKCE). You create a new inbox or link an existing API key. Cooper then issues an access token for that Cooper account (scope: email). Scripts and Cursor can instead send `Authorization: Bearer coop_live_…`. We do not receive your Claude or ChatGPT password. Those services keep their own login; they send Cooper only an OAuth access token they obtained from us, or an API key you created on Cooper.

### What ChatGPT sends Cooper

After you connect, ChatGPT (the model) chooses when to call a Cooper tool and which argument values to send. Cooper receives only those tool names and arguments — for example `username`, `to`, `subject`, message text/HTML, or a search query. Tools do not request chat history, raw transcripts, location, payment data, government ids, health records, or extra profile fields. Input schemas are the fields in the table below and in [/api/v1/mcp/tools](/api/v1/mcp/tools).

### What Cooper returns to ChatGPT

Cooper returns minimized tool outputs: inbox fields, message summaries or stored message fields, or a webhook record. Responses omit diagnostic fields (session / trace / request ids, stacks, raw provider payloads, RFC822 headers, delivery flags, provider ids, and account ids on messages). Write tools that send mail or create addresses are labeled as writes so the client can ask you to confirm.

### What Cooper does not receive from ChatGPT

We do not receive your ChatGPT password, OpenAI account credentials, or the full chat history. We only see text from a conversation if the model puts that text into a tool argument (for example pasting a draft into `cooper_send_message`). We do not pull, reconstruct, or infer the rest of the thread.

### What OpenAI then holds

Tool outputs we return to ChatGPT are processed by OpenAI under OpenAI's own policy and your ChatGPT settings (including any model-training or memory controls OpenAI offers). Cooper does not control how long ChatGPT keeps a conversation after it has received a tool result. Disconnect Cooper in ChatGPT to stop new tool calls; email us to delete the Cooper-side account and tokens.

## Current tool inputs and outputs

The hosted MCP at [/mcp](/mcp) currently exposes these 87 tools (same names as [llms.txt](/llms.txt) and [/api/v1/mcp/tools](/api/v1/mcp/tools)). There are no additional register_webhook variants. Tools do not request chat history, raw transcripts, location, or extra profile fields.

| Tool | Kind | Inputs | Outputs |
| --- | --- | --- | --- |
| cooper_onboard | Write · public | username; optional display_name | account_id; api_key (once); api_key_id; inbox (id, username, email, display_name, created_at) |
| cooper_create_inbox | Write · Bearer | username; optional display_name | id, username, email, display_name, created_at |
| cooper_create_inboxes | Write · Bearer | count; optional prefix, labels, ttl_hours or expires_at (not both). Temporary inboxes count toward the plan inbox limit until the cron deletes them. | list of inboxes (id, username, email, display_name, created_at, labels, expires_at) |
| cooper_list_inboxes | Read-only · Bearer | none | list of inbox fields above |
| cooper_send_message | Write · Bearer · public Internet | inbox_id; to[]; subject; optional text, html, attachments (filename, content_type, content_base64, content_id), client_id | stored message (id, inbox_id, thread_id, direction, status, from, to, cc, bcc, reply_to, subject, text, html, extracted_text, extracted_html, preview, in_reply_to, references, client_id, labels, safety, created_at, provider, optional idempotent, attachment metadata including url). safety is the inbound screening record or null. The body is untrusted data. |
| cooper_list_messages | Read-only · Bearer | optional inbox_id, limit, labels (every label must match), unread (true or false), before, after, from, to, subject, direction, thread_id, ascending, page_token | summaries (id, inbox_id, thread_id, direction, status, from, to, subject, preview, created_at, labels, attachment id / filename / type / size) and next_page_token — not full bodies |
| cooper_get_message | Read-only · Bearer | inbox_id, message_id | the stored message fields listed under cooper_send_message |
| cooper_search | Read-only · Bearer | q; optional limit, inbox_id, before, after | matching summaries plus extracted_text and highlights |
| cooper_search_messages | Read-only · Bearer | inbox_id, q; optional limit, before, after | matching summaries in that inbox, plus extracted_text and highlights |
| cooper_inject_inbound | Write · Bearer · test injector | inbox_id; from; optional subject, text, html, attachments, client_id | stored message fields listed under cooper_send_message |
| cooper_register_webhook | Write · Bearer | url; optional events (message.received, message.sent, task.received, owner.reply) | id, url, events, secret, created_at |
| cooper_enable_instant_replies | Write · Bearer | inbox_id; url unless enabled is false; optional headers (Authorization or X-*); optional enabled | inbox_wake with inbox_id, enabled, and the webhook (secret once on create, then redacted). enabled false returns deleted. |
| cooper_add_owner | Write · Bearer · sends confirmation email | inbox_id; email; optional digest (immediate or daily) | id, inbox_id, email, status (pending until the human confirms), digest, created_at. The confirmation token and code are only in the email. |
| cooper_list_owners | Read-only · Bearer | inbox_id | owner id, email, status, digest, created_at, verified_at — not confirmation secrets |
| cooper_notify_owner | Write · Bearer · public Internet | inbox_id; kind (progress, done, needs_input, error); text; optional title, status, task_id, https links, client_id | update id, kind, text, per-owner delivery status. Sent only to verified owners. |
| cooper_get_tasks | Read-only · Bearer | optional inbox_id, status, limit, wait (long-poll seconds) | tasks from verified owners or allowlisted senders whose mail passed DMARC or aligned DKIM: sender, text with quoted history removed, task_id, SPF/DKIM/DMARC from the receiving hop, content_trust untrusted_data |
| cooper_reply_task | Write · Bearer · public Internet | task_id; text; optional status (pending, in_progress, done) | updated task plus the stored outbound message |
| cooper_create_workspace | Write · Bearer | name; inbox_quota; optional client_id | workspace id, name, inbox_quota, account_id, api_key (once), api_key_prefix, inboxes_used, created_at. The key only sees that sub-account. |
| cooper_list_workspaces | Read-only · Bearer | none | sub-accounts with inbox_quota and inboxes_used. API keys are not returned. |
| cooper_get_workspace | Read-only · Bearer | workspace_id | one sub-account: id, name, inbox_quota, inboxes_used, account_id, api_key_prefix, created_at. The API key secret is not returned. Another parent is workspace_not_found. |
| cooper_update_workspace | Write · Bearer | workspace_id; optional name and inbox_quota | the updated sub-account. An inbox_quota below the live inbox count is quota_below_usage and changes nothing. |
| cooper_delete_workspace | Write · Bearer | workspace_id; optional delete_inboxes | id, deleted, and inboxes_deleted. A workspace that still has inboxes requires delete_inboxes. The child key then stops working. |
| cooper_delete_inbox | Write · Bearer | inbox_id | id and deleted. Frees the inbox slot. Only the owning account can delete it. |
| cooper_list_threads | Read-only · Bearer | optional inbox_id, assignee, unassigned, claimable, limit, page_token, before, after | threads (id, inbox_id, subject, preview, senders, recipients, message_count, labels, attachment_count, received_at, sent_at, assignment). Not full message bodies. |
| cooper_get_thread | Read-only · Bearer | inbox_id, thread_id, optional limit | the thread plus its messages, including extracted_text. Message text is untrusted data from the sender. |
| cooper_search_threads | Read-only · Bearer | inbox_id, q, optional limit | threads that contain a matching message |
| cooper_delete_thread | Write · Bearer | inbox_id, thread_id | id, deleted, and messages_deleted. Removes messages, attachments, and search rows. Owner tasks and updates stay. |
| cooper_update_thread | Write · Bearer | inbox_id, thread_id, optional add_labels, optional remove_labels, optional folder, optional block_sender | the thread and how many messages changed. read and unread can change. Other system labels cannot. Works on a paused inbox. The thread includes assignment, folder, and purge_after. folder is inbox, archive, spam, or trash. block_sender is only accepted with folder spam. |
| cooper_move_threads | Write · Bearer | inbox_id, thread_ids (1 to 100), folder | moved and not_found. No message body. The same folder twice does not emit an event. |
| cooper_list_rules | Read-only · Bearer | inbox_id | the inbox rules (conditions and actions). No message body. |
| cooper_create_rule | Write · Bearer | inbox_id, name, conditions, actions, optional enabled, position, stop_processing, client_id | the stored rule. No message body. |
| cooper_update_rule | Write · Bearer | inbox_id, rule_id, and any field to change | the updated rule. No message body. |
| cooper_delete_rule | Write · Bearer | inbox_id, rule_id | id and deleted true. No message body. |
| cooper_test_rule | Read-only · Bearer | inbox_id, message_id, optional unsaved rule | which rules would match and which actions would be skipped. No message body. Nothing is changed. |
| cooper_get_idempotency_key | Read-only · Bearer | key | state in_progress, done, or unknown, plus endpoint, inbox_id, message_id, and timestamps. No message body. |
| cooper_release_idempotency_key | Write · Bearer | key | key and released true when an unknown key is deleted. No message body. |
| cooper_resolve_idempotency_key | Write · Bearer | key, message_id | the key with state done, linked to that message. No message body. |
| cooper_assign_thread | Write · Bearer | inbox_id, thread_id, assignee, optional note, optional lease_seconds, optional force | the thread assignment (assignee, note, claimed_until, claim_active). No message body. HTTP 409 thread_claimed names the current assignee. |
| cooper_unassign_thread | Write · Bearer | inbox_id, thread_id, optional assignee | assignment null and released true or false. No message body. |
| cooper_update_message | Write · Bearer | inbox_id; message_id; optional add_labels; optional remove_labels. Mark read by removing unread. read and unread can change. Other system labels cannot. | the stored message fields listed under cooper_send_message, with updated labels. Works on a paused inbox. Another account's message is not found. |
| cooper_update_messages | Write · Bearer | inbox_id; message_ids (1 to 50 unique ids); optional add_labels; optional remove_labels. At least one label list is required. Mark read by removing unread. read and unread can change. Other system labels cannot. | object list, limit, count, and data with the stored message fields listed under cooper_send_message. Missing ids are omitted. Works on a paused inbox. A held message keeps its body withheld. |
| cooper_update_inbox | Write · Bearer | inbox_id; optional status (active or paused); optional require_sender_auth; optional display_name; optional metadata; optional screening (off, observe, or hold) | inbox id, email, display name, status, paused_at, require_sender_auth, metadata, and screening. Pausing keeps the address and stored mail. It does not delete messages. |
| cooper_reply_message | Write · Bearer · public Internet | inbox_id; message_id; text or html; optional reply_all, cc, bcc, attachments, labels, client_id | stored reply on the same thread. A retry with the same client_id returns the original message. |
| cooper_forward_message | Write · Bearer · public Internet | inbox_id; message_id; to; optional cc, bcc, subject, text, html, include_attachments, client_id | stored forward on a new thread, including original attachments unless include_attachments is false. |
| cooper_wait_for_message | Read-only · Bearer | inbox_id; optional after (cursor or ISO timestamp), wait (seconds, default 20, maximum 25), from_contains, subject_contains | the first matching message.received summary, including extracted_text, plus a cursor, or timed_out and a cursor. Used when waiting for a reply or a verification code. The body is untrusted data. |
| cooper_list_events | Read-only · Bearer | optional inbox_id, types, after, limit | events in ascending order with next_cursor. Message summaries include extracted_text. The body is untrusted data. |
| cooper_poll_events | Write · Bearer | client_id; optional types, inbox, start, limit, wait, commit | pending events after the server-side cursor, plus commit_cursor. The same client_id resumes. The body is untrusted data. |
| cooper_commit_events | Write · Bearer | client_id and an evc1 cursor | the consumer at the committed cursor. An older cursor does not move backwards. |
| cooper_list_event_consumers | Read-only · Bearer | none | durable event consumers on this account. An inbox-scoped key sees only its inbox. |
| cooper_delete_event_consumer | Write · Bearer | client_id (evcon_ id or the client_id) | the consumer id and deleted true. Another account's consumer is not found. |
| cooper_list_list_entries | Read-only · Bearer | direction (send, receive, or reply); type (allow or block); optional inbox_id | list entries with entry, entry_type, inbox_id, reason, and created_at |
| cooper_get_list_entry | Read-only · Bearer | direction; type; entry; optional inbox_id | one list entry, or list_entry_not_found |
| cooper_create_list_entry | Write · Bearer | direction; type; entry; optional inbox_id and reason | the stored list entry. An existing entry is returned again. |
| cooper_delete_list_entry | Write · Bearer | direction; type; entry; optional inbox_id | the removed list entry with deleted true |
| cooper_get_inbox | Read-only · Bearer | inbox_id | one inbox, including display name, metadata, status, and client_id. Another account's inbox is not found. |
| cooper_confirm_owner | Write · Bearer | inbox_id, owner_id, and the 6-digit confirmation code | the owner after confirmation. A bad or expired code is rejected. The code is not stored in the response. |
| cooper_whoami | Read-only · Bearer | none | account id, auth type, key prefix and permission limits, and workspace quota when this account is a sub-account. Does not return a key secret. |
| cooper_list_webhooks | Read-only · Bearer | none | webhooks on this account, with the secret redacted, including enabled, consecutive_failures, and inbox_ids. An inbox-scoped key lists only hooks stored on that inbox. |
| cooper_update_webhook | Write · Bearer | webhook_id; optional url, events, enabled, inbox_ids (at most 10). enabled true re-enables and resets consecutive_failures. enabled false stops deliveries. | the webhook with the secret redacted |
| cooper_delete_webhook | Write · Bearer | webhook_id | id and deleted true. The hook is removed and receives no further events. |
| cooper_rotate_webhook_secret | Write · Bearer | webhook_id | the webhook with the new signing secret once, previous_secret_expires_at, and previous_secret_active. The previous secret is not returned. Deliveries accept either signature for 24 hours. |
| cooper_test_webhook | Write · Bearer · public Internet | webhook_id | delivery id, status (delivered or failed), response_status, attempts, and event_id for a signed webhook.test POST. A disabled hook returns webhook_disabled and sends nothing. |
| cooper_list_suppressions | Read-only · Bearer | none | addresses this account will not email, with reason bounce, complaint, or manual, and the source message id when a bounce or complaint added the row. |
| cooper_delete_suppression | Write · Bearer | address | the suppression row with deleted true. A missing address is suppression_not_found. |
| cooper_release_message | Write · Bearer | inbox_id, message_id | the message after the held label is removed. Fires message.received and may create a task. A message that is not held returns message_not_held. The body stays untrusted data. |
| cooper_get_attachment | Read-only · Bearer | inbox_id, message_id, attachment_id; optional format text or base64 | extracted text when the type supports it, otherwise base64 bytes. Text is capped at 200,000 characters. base64 over 5 MB returns attachment_too_large and the download URL. |
| cooper_get_metrics | Read-only · Bearer | kind events, usage, or rates; optional inbox_id, start, end, period, types | counts of mail, usage, or bounce and complaint rates for this account. Does not return message bodies. An inbox-scoped key sees only that inbox. |
| cooper_get_sending_status | Read-only · Bearer | no inputs | whether this account can send email. status is active, warning, or paused. Counts are the trailing 7 days. An inbox-scoped key receives the account status. Does not return message bodies. |
| cooper_create_draft | Write · Bearer | inbox_id; optional to, cc, bcc, subject, text, html, send_at, in_reply_to or forward_of, client_id | the draft. Scheduling a draft (send_at) counts as sending and needs message_send or draft_send. The same client_id returns the original draft. |
| cooper_get_draft | Read-only · Bearer | inbox_id, draft_id | one draft, including send_status, send_at, and approval_status. |
| cooper_list_drafts | Read-only · Bearer | optional inbox_id, labels, limit, and page_token | drafts this key can see. An inbox-scoped key sees only its inbox. |
| cooper_update_draft | Write · Bearer | inbox_id, draft_id, and the fields to change. Scheduling a draft (send_at) counts as sending and needs message_send or draft_send. send_at null unschedules. | the updated draft. A draft that is sending returns draft_sending. |
| cooper_delete_draft | Write · Bearer | inbox_id, draft_id | id and deleted true. This cancels a scheduled send. |
| cooper_send_draft | Write · Bearer · public Internet | inbox_id, draft_id; optional add_labels, remove_labels, idempotency_key | the sent message, and the draft is deleted. Approval mode returns the pending draft until an owner approves. |
| cooper_wait_for_code | Read-only · Bearer | inbox_id; optional wait (seconds, default 25, maximum 55), after (ISO timestamp), from_contains, subject_contains | the extracted one-time code, candidate codes, and the message id, sender, subject, and time, or timed_out true. The message body is not returned. |
| cooper_get_owner_preferences | Read-only · Bearer | optional inbox_id and owner_id | the account default email style and note, and one owner's style, note, and source when owner_id is given |
| cooper_set_owner_preferences | Write · Bearer | style (concise, detailed, casual, or null), optional note, inbox_id, owner_id | the same shape as cooper_get_owner_preferences. A style the owner set from their email link cannot be changed. |
| cooper_list_oauth_grants | Read-only · Bearer | none | connected OAuth apps on this account. Each row has the client id, name, redirect hostnames, scope, and when it was connected. Token hashes and client secrets are not returned. |
| cooper_revoke_oauth_grant | Write · Bearer | client_id | id, revoked true, and how many tokens were removed. That app's access and refresh tokens stop working. The client registration stays. Other apps and API keys stay valid. |
| cooper_list_event_subscriptions | Read-only · Bearer | none | MCP event subscriptions on this account. Each row has the id, event name, inbox, callback hostname, status, and refresh time. The callback URL and signing secret are not returned. |
| cooper_delete_event_subscription | Write · Bearer | id (mes_…) | the subscription with status ended. Another account's id is not found. |
| cooper_billing_status | Read-only · Bearer | none | plan, usage (sends, inboxes), limits, upgrade path, stripe customer id if one exists |
| cooper_upgrade_link | Write · Bearer | plan (starter or pro); optional email, client_id | Stripe Checkout url and session id |
| cooper_set_addons | Write · Bearer · Stripe | inboxes, domains, or email_packs (integers from 0 to 100; at least one) | the new extra inbox, domain, and email-pack quantities, the monthly amount, and the limits after the change. Starter or Pro only. Free returns HTTP 402 and buys nothing. |
| cooper_add_domain | Write · Bearer | domain (hostname); optional client_id | domain id, status (pending or verified), the DNS records to publish, mail, and status_detail. DNS is written only for a zone already on the operator account. Inboxes on your own domain are included on Starter (15 custom domains) and Pro (200 custom domains). Free includes 0 custom domains and returns HTTP 402 plan_limit_exceeded. When the hostname is already an active zone on the operator Cloudflare account, Cooper writes the DNS records and dns.mode is automatic. Cooper does not register a domain or create a zone. A zone that is on that account but not active stays manual. Publish the routing MX hosts, TXT SPF v=spf1 include:_spf.mx.cloudflare.net ~all, the routing DKIM TXT, the cf-bounce MX, SPF, and DKIM records, a DMARC TXT (an existing DMARC record is left as it is), and the _cooper-verify TXT, or point the nameservers at the ones in the response. mail.receiving stays false until the receiving records check out and the catch-all is live. Receiving goes live within a few minutes. status_detail says so while you wait. POST /api/v1/inboxes with domain then creates username@domain. When the hostname is not a zone on the operator account, dns.mode is external. Cooper does not move nameservers. Each record has host, type, value, priority for MX, and ttl. Publish the receiving MX, the return-path MX and one SPF TXT with a single include, the DKIM TXT, and the _cooper-verify TXT at your own DNS host. An existing SPF is merged into that one record. An apex v=spf1 -all does not reject mail whose envelope-from is the return-path host. Do not add a second SPF TXT. A DMARC p=reject record is left as published and blocks mail until DKIM for that domain verifies. Cooper checks the records with public DNS. mail.receiving becomes true after the receiving MX verifies and RESEND_WEBHOOK_SECRET is set. mail.sending becomes true after the return-path and DKIM records verify. The receiving MX hostname and the DKIM value come from Resend on that response. Do not invent them. DELETE /api/v1/domains/:id puts back the catch-all that was there before, deletes only the DNS records Cooper created, turns Email Routing off only if Cooper turned it on, and removes the sending domain only if Cooper created it. A Resend domain Cooper created is removed the same way. A cleanup that does not finish keeps the row with status cleanup_failed and deleted false so a later delete can finish it. |
| cooper_list_domains | Read-only · Bearer | none | custom domains on this account, with status, mail flags, and per-record DNS status. API keys are not returned. |
| cooper_verify_domain | Write · Bearer · public Internet | domain_id | the domain after a DNS check. domain.verified fires once when a pending domain becomes verified. A second call within 60 seconds is rate_limited. |

### HTTP API fields (same public shape)

The HTTP API at /api/v1 returns the same public message and inbox fields. It does not return headers, provider_id, delivery, account_id on messages/inboxes, key prefixes, or operator hints. Extra HTTP-only routes that are not MCP tools: `POST /api/v1/keys` (issues a key), `GET /api/v1/webhooks/:id/deliveries` (delivery log), `GET /api/v1/stats` (counts), and attachment byte download under `/api/v1/inboxes/:id/messages/:msgId/attachments/:attId`.

## Children

Cooper Email is an API for AI-agent operators and developers. It is not directed at children under 13. We do not knowingly collect personal data from children under 13. If you believe a child under 13 created a Cooper inbox, email [ops@avatar33.com](mailto:ops@avatar33.com) and we will delete that account.

## What we do not do

- We do not sell mailbox contents.
- We do not sell personal data or use it for advertising.
- We do not receive your Claude or ChatGPT password.
- We do not ask MCP tools for full chat history or raw transcripts.
- We do not pull ChatGPT conversation history unless the model places some of that text in a tool argument.
- We do not return session ids, trace ids, request ids, stack traces, raw provider payloads, or debug blobs in tool or API JSON.
- We do not run first-party ads, sale of mailbox contents, or model training on your mail.
- Paid plans are billed through Stripe Checkout. Card details go to Stripe; we never see or store card numbers. We keep the Stripe customer and subscription ids and your plan.

## SMS alerts

If you opt in at [/sms-opt-in](/sms-opt-in), Avatar 8 LLC stores your mobile number, the consent text you agreed to, the time, and the IP address of the request. After your Cooper account confirms the number with a code, we also store its confirmation status and time and daily and monthly alert counts. We use this only to send the texts you opted into: phone verification codes and account alerts about your agent's inbox (a send waiting for your approval, or unread mail older than 24 hours). No mobile information or consent will be shared with third parties or affiliates for marketing or promotional purposes. Text messaging originator opt-in data and consent will not be shared with any third parties. Our texting provider (Twilio) receives your number only to deliver those messages. Message frequency varies. Msg & data rates may apply. Reply STOP to opt out, HELP for help. Consent is not a condition of purchase. Questions: [ops@avatar33.com](mailto:ops@avatar33.com).

## Changes

If we change how Cooper collects, uses, or shares personal data, we will update this page and the "Last updated" date at the top (currently 24 October 2026). The published URL remains [https://cooperemail.com/privacy](/privacy). Review the page before installing or reconnecting the ChatGPT plugin.

## Contact

Questions, deletion, key revocation, or OAuth disconnect follow-up: [ops@avatar33.com](mailto:ops@avatar33.com). Human docs: [/docs](/docs) · MCP: [/docs/mcp](/docs/mcp) · Tools: [/api/v1/mcp/tools](/api/v1/mcp/tools).
