Cofounder CLI
Company inboxes, reading and sending mail, drafts, email campaigns to CRM contacts, your own mail domain, and email from your app.
The company gets its own inboxes. Agents read threads, reply, and send from them, and once the company has its own domain they can email CRM contacts in bulk.
Inboxes
| MCP | CLI | API |
|---|---|---|
email_provision | cofounder email provision --local-part <name> | POST /cofounder-cli/v1/company/email |
email_get | cofounder email status | GET /cofounder-cli/v1/company/email/status |
The first inbox is free; each extra inbox costs $2 a month while it's
active. Without a domain, the inbox goes on the company's trial domain. Pass
--mail-domain <domain> to use a domain the company owns in Cofounder, or
--mail-domain-id for a mail domain you set up below. Running provision
again with the same name and domain returns the same inbox.
email status shows today's sending against your limits, any pauses, and
bounces on app email over the last seven days. App and inbox email share a
limit of 1,000 recipients a day, which resets at midnight UTC.
Read and send
| MCP | CLI | API |
|---|---|---|
email_threads_list | cofounder email threads <inbox-id> | GET /cofounder-cli/v1/company/email/threads |
email_threads_get | cofounder email read <inbox-id> <thread-id> | GET /cofounder-cli/v1/company/email/threads/{thread_id} |
email_threads_attachments_get | cofounder email attachment <inbox-id> <thread-id> <attachment-id> --out <path> | GET /cofounder-cli/v1/company/email/threads/{thread_id}/attachments/{attachment_id} |
email_messages_send | cofounder email send <inbox-id> --to <emails> --subject <text> --body-file <path> | POST /cofounder-cli/v1/company/email/messages |
email_threads_reply | cofounder email reply <inbox-id> <thread-id> --message <message-id> --to <emails> --body <text> | POST /cofounder-cli/v1/company/email/threads/{thread_id}/reply |
email_drafts_create | cofounder email draft create <inbox-id> --to <emails> --subject <text> --body <text> | POST /cofounder-cli/v1/company/email/drafts |
email_drafts_list | cofounder email draft list <inbox-id> | GET /cofounder-cli/v1/company/email/drafts |
email_drafts_send | cofounder email draft send <inbox-id> <draft-id> | POST /cofounder-cli/v1/company/email/drafts/{draft_id}/send |
attachment returns a link to the file; --out downloads it instead.
reply needs the message id from email read. Recipient lists are
comma-separated. Mail to a CRM contact marked do-not-contact is refused.
If a send or reply fails with a 503, retry with the same --idempotency-key
and content and it won't go out twice. Drafts have no key: if a
draft send result is unclear, run draft list before retrying — a draft
that's gone or shows send_status scheduled or sending was already accepted.
Have your agent write drafts when you want to review mail before it goes out.
Each command also has a flag form that picks the inbox with --resource
(its address or id) and uses the company's default inbox when you leave it
out:
cofounder email threads list
cofounder email threads get --thread-id <id>
cofounder email threads attachments get --thread-id <id> --attachment-id <id>
cofounder email messages send --to <email> --subject <text> --body <text>
cofounder email threads reply --thread-id <id> --message-id <id> --to <email> --body <text>
cofounder email drafts create --to <email> --subject <text> --body <text>
cofounder email drafts list
cofounder email drafts send --draft-id <id>Pause and resume sending
| MCP | CLI | API |
|---|---|---|
email_streams_pause | cofounder email pause --stream mailbox | POST /cofounder-cli/v1/company/email/streams/{stream}/pause |
email_streams_resume | cofounder email resume --stream mailbox | POST /cofounder-cli/v1/company/email/streams/{stream}/resume |
--stream mailbox covers inbox mail and --stream app covers email your app
sends. A pause stops new sends right away but doesn't recall mail already
accepted, and doesn't affect your app's sign-in emails. resume lifts only a
pause you set; pauses caused by bounces or complaints stay in place. Check
cofounder email status afterwards.
Use your own mail domain
| MCP | CLI | API |
|---|---|---|
email_domains_create | cofounder email domains create --managed-resource-binding-id <domain-id> | POST /cofounder-cli/v1/company/email/domains |
email_domains_verify | cofounder email domains verify --mail-domain-id <id> | POST /cofounder-cli/v1/company/email/domains/{mail_domain_id}/verify |
email_domains_list | cofounder email domains list | GET /cofounder-cli/v1/company/email/domains |
email_domains_get | cofounder email domains get --mail-domain-id <id> | GET /cofounder-cli/v1/company/email/domains/{mail_domain_id} |
<domain-id> is the domain's id from cofounder domains list (see
Domains); add --subdomain-label to put mail on a
subdomain. create returns the DNS records to publish. If the domain's DNS is
hosted elsewhere, add them there, then run verify. A verified mail domain
has no inboxes yet — create them with
cofounder email provision --local-part <name> --mail-domain-id <id>.
Email campaigns
A campaign sends one message to a list of CRM contacts, each as its own
email, from news.<your-domain>. Campaigns need a paid plan and go to at
most 5,000 contacts. Every contact must have consent recorded for their
current primary email, and must not be marked do-not-contact or blocked from
receiving email. One ineligible contact blocks the whole send.
| MCP | CLI | API |
|---|---|---|
email_campaigns_setup | cofounder email campaign sender setup --domain-binding-id <domain-id> | POST /cofounder-cli/v1/company/email/campaign/setup |
email_campaigns_preview | cofounder email campaign audience preview --domain-binding-id <domain-id> --contact-id <id> | POST /cofounder-cli/v1/company/email/campaign/preview |
email_campaigns_drafts_create | cofounder email campaign drafts create --name <name> --content <json> | POST /cofounder-cli/v1/company/email/campaign/drafts |
email_campaigns_drafts_list | cofounder email campaign drafts list | GET /cofounder-cli/v1/company/email/campaign/drafts |
email_campaigns_drafts_get | cofounder email campaign drafts get --draft-id <id> | GET /cofounder-cli/v1/company/email/campaign/drafts/{draft_id} |
email_campaigns_drafts_update | cofounder email campaign drafts update --draft-id <id> --expected-revision <n> --name <name> --content <json> | PUT /cofounder-cli/v1/company/email/campaign/drafts/{draft_id} |
email_campaigns_drafts_preview | cofounder email campaign drafts preview --draft-id <id> | GET /cofounder-cli/v1/company/email/campaign/drafts/{draft_id}/preview |
email_campaigns_drafts_test_send | cofounder email campaign drafts test --draft-id <id> --expected-revision <n> --request-key <key> | POST /cofounder-cli/v1/company/email/campaign/drafts/{draft_id}/test |
email_campaigns_drafts_launch | cofounder email campaign drafts launch --draft-id <id> --expected-revision <n> --request-key <key> | POST /cofounder-cli/v1/company/email/campaign/drafts/{draft_id}/launch |
email_campaigns_send | cofounder email campaign send --request-key <key> --domain-binding-id <domain-id> --contact-id <id> --subject <text> --text <text> ... | POST /cofounder-cli/v1/company/email/campaign/send |
email_campaigns_receipts_list | cofounder email campaign list | GET /cofounder-cli/v1/company/email/campaign |
email_campaigns_receipts_get | cofounder email campaign get --campaign-id <id> | GET /cofounder-cli/v1/company/email/campaign/{campaign_id} |
email_campaigns_receipts_request_keys_get | cofounder email campaign get-by-key --request-key <key> | GET /cofounder-cli/v1/company/email/campaign/by-key/{request_key} |
Run sender setup once with the domain's id from cofounder domains list:
it sets up the news. sender, returns the DNS records it still needs, and
adds an unsubscribe footer. audience preview checks a contact list without
writing anything. A draft's --content holds the audience, sender, and
message:
{
"domain_binding_id": "<domain-id>",
"contact_ids": ["<crm-contact-id>"],
"sender_name": "Acme",
"contact_email": "hello@acme.com",
"postal_address": "1 Main St, Springfield, CA 94000",
"subject": "We just launched",
"text": "Plain-text body",
"html": "<p>HTML body</p>"
}Then work through the draft:
drafts previewshows who would be left out and why, plus the finished email with its footer. Nothing is sent.drafts testsends one copy to your own email, once per version of the draft.drafts launchsends the campaign. A draft launches once and then can't be edited; start a new draft for the next campaign.
--expected-revision is the draft's current version number from
drafts get or drafts preview; each edit makes a new version and clears
its test. --request-key is a key you choose and save: retrying with it
returns the saved result instead of sending again, and get-by-key finds the
campaign by it. campaign send skips the draft and sends straight away, with
the content as flags.
Results show which recipients the email provider accepted, which is not the same as delivered. If part of a send has an unknown outcome, the campaign stops there and is never retried automatically.
Email from your app
| MCP | CLI | API |
|---|---|---|
email_app_email_setup | cofounder email setup --app-binding-id <app-id> | POST /cofounder-cli/v1/company/app-email/setup |
email_auth_smtp_setup | cofounder email auth smtp setup --source-domain-binding-id <domain-id> | POST /cofounder-cli/v1/company/email/auth/smtp/setup |
email_auth_smtp_get | cofounder email auth smtp get | GET /cofounder-cli/v1/company/email/auth/smtp |
email_auth_smtp_migrate | cofounder email auth smtp migrate --previous-sending-domain-binding-id <id> --source-domain-binding-id <domain-id> | POST /cofounder-cli/v1/company/email/auth/smtp/migrate |
email setup lets the company's deployed app send email. It creates a new
sending key and adds COFOUNDER_APP_EMAIL_API_KEY and
COFOUNDER_APP_EMAIL_SEND_URL to the app's Vercel Production environment;
the key itself is never shown. <app-id> is the id at the end of the app's
managed:vercel_project:<id> resource. The change reaches the next deploy,
and Cofounder asks Vercel to redeploy. Each run makes another key and older
keys keep working, so revoke them with cofounder company api-keys revoke
once the new deploy works.
email auth smtp setup sends your app's Supabase sign-up and sign-in emails
from the company's verified domain, or from a shared sender if you leave out
--source-domain-binding-id. auth smtp get shows how that's set up without
sending anything. auth smtp migrate moves an app from the shared sender to
your own domain: pass the current shared sender as
--previous-sending-domain-binding-id. Add --project-target staging_branch
to any of these to work on the staging branch instead of production.