Cofounder

Email

Give the company inboxes, read and send mail, save drafts, email your CRM contacts, use your own mail domain, and send email from your app.

The company gets its own inboxes, and your agent reads threads, replies, and sends from them. Once the company has its own domain, your agent can also email your CRM contacts in bulk and send email from your app. The first inbox on your own domain is free, and each one after it is $2 a month.

Any company member can read mail and drafts. Sending, replying, drafting, labeling, and attaching files need an admin.

Business-policy checks are rolling out and are not enabled for every company yet. Where enabled, a saved prohibited business or unsupported intended use blocks new email sends, including campaign tests. Ordinary communication from verification-sensitive businesses remains allowed; ad verification requirements do not apply to routine email. Missing business information alone does not block email. A business restriction explains how to correct inaccurate information or contact Support. Existing receipts remain available.

Name Your Agent

Your agent signs its email with a name and role you choose. Set them before managed setup, because setup turns the name into the inbox address: Alex Chen becomes alex.chen@<company-mail-domain>. Accents are dropped, separators become dots, and addresses stop at 64 characters. A name with no ASCII letters or digits gets a stable agent-<hash> address. The sender name keeps your spelling.

This is optional. Without a name, setup uses hello. Later changes apply only to new work. They don't rename inboxes or change setup runs already in progress.

Add Inboxes

Your agent adds inboxes on a verified company domain. Inboxes on the trial domain and the first inbox on your own domain are free. Each extra inbox on your own domain costs $2 a month while active.

New company inboxes use the company name as the sender name unless you provide a display name. Provisioning an existing inbox keeps its name.

Without a domain, the inbox goes on the shared cofounder.company trial domain. Trial inboxes are reply-only, to protect that shared domain. They can answer mail that arrives, but can't start new conversations or hold drafts.

To send new email, the company needs an inbox on a domain it owns (see Use Your Own Mail Domain). With no domain yet, buy one first. Buying a domain costs money, so your agent asks you before it buys.

If your domain isn't verified yet, your agent gets the list of DNS records to add. Add the missing ones at your DNS provider, and your agent retries.

Mail sent from Cofounder's shared domain has limits, all reset at midnight UTC:

Sending fromLimit per company
A company inbox on the shared domain10 messages a day, 100 in total
App email from the shared sender50 messages a day
App email on your own domain, during the trial100 messages a day
App email or an inbox on your own domain, on a paid planNo Cofounder limit

Each message from the shared domain goes to one recipient. All companies sending from the shared domain also share a pool of 1,000 recipients a day, so a send can be refused with global_daily_recipient_cap_exhausted before your own limit is reached. cofounder email status (email_get) shows today's counts against each limit. Sign-in email from your app's auth has its own limits and doesn't count.

Account Email Limits

Some accounts also have a rolling email pool across the companies they're responsible for. It's rolling out gradually and is off by default. When it's on, email status shows the account owner a responsible_account_email_limits object. The 10-new-recipient and 50-delivery caps are configured for trial companies and apply only when limits_enabled is true. A verified paid company is not limited by or charged to this account pool, though its existing company quotas and all recipient and sending policies still apply.

  • new_recipients_24h: first-contact addresses in the last 24 hours, against a limit of 10.
  • deliveries_24h: every To, Cc, and Bcc recipient in the last 24 hours, against a limit of 50.
  • limits_enabled: whether the trial caps are enforced for the selected company. It is false when the feature flag is off or the company has verified paid access. The cap fields still show the configured trial values.
  • legacy_review_required: older sends still need review before enforcement is reliable.

The pool covers inbox sends, CRM outreach and campaigns, and app email, including a campaign's test send. Simulated app email in test mode and your app's sign-in email don't count. A pending send holds its share until the outcome is known, and a rejected one gives it back. Retry with the same request key to get the original outcome. The company limits above still apply. The usage counters summarize the account's recent activity across companies that currently lack verified paid access, even when the selected company's limits_enabled is false. If a company becomes paid, its recent activity leaves the trial pool; if it later returns to trial before that activity ages out of the rolling window, it can count again. A plan change does not erase the underlying send history.

Email Restrictions

email status includes active restrictions with their ID, affected email stream and reason. These checks happen inside the normal sending flow.

If a send is refused, read its restriction in email status. To ask for review, open a Cofounder support ticket with the affected company and the restriction ID in the description. Follow the conversation through support list, support get and support reply.

cofounder email status
cofounder support create --org-id <company-id> --subject "Review email restriction" --description "Please review restriction <restriction-id>."

The email safety rollout is not available to every company yet. For enrolled accounts, a verified marketing spam complaint or three hard bounces among the last twenty completed recipient deliveries pauses campaign sends and tests and starts a provider pause of the company's marketing account. Product email, app sign-in email and mailbox replies remain separate. A provider pause is not cancellation of queued mail; clearing the restriction does not automatically resume the account or campaigns. Repeated feedback for one delivery counts once. Reviewed recovery starts a fresh delivery-quality window; late bounce feedback from before that recovery does not reopen it.

Other restrictions prevent new sends for their stream. Messages and campaigns already accepted may still be active. Opening a support ticket does not lift the restriction, restart old work or promise a review time. For a campaign with an uncertain result, inspect its receipt and status before retrying the same launch. Do not create a new key to bypass a restriction.

Read and Send

Your agent reads your inbox, searches it, labels and flags mail, downloads attachments, sends new mail, and replies. Search skips spam, trash, blocked, and unverified mail. Flags are unread, starred, important, and spam.

  • Mail to a CRM contact marked do-not-contact is refused.
  • Reply-all doesn't work on shared cofounder.company inboxes.
  • A reply-only inbox can't send new mail or save drafts. Use an inbox on your own domain instead.
  • If a send fails with a temporary error, your agent retries it without sending twice.

To review mail before it goes out, ask your agent to write drafts instead of sending. You or your agent edits, sends, or deletes them later. A draft shows its subject, text, recipients, and scheduled time, but not its attachments. Editing keeps its attachments, and scheduled or sending drafts can't be edited. Your agent can also open a draft in the company app for you to read.

Sends, replies, and draft sends can come back with notices suggesting more specific wording. They don't block or change the send.

A send receipt with delivery_status: accepted means the mail provider accepted the message. It does not confirm delivery. Follow its next_steps to read the message's current delivery status. A bounced or rejected message points you to delivery-failure notices in the same inbox, which can arrive as separate threads. Match the recipient and original message ID before attributing a cause, and resolve it before resending.

A message takes up to 5 attachments, 10 MiB each and 25 MiB total. Executables and scripts are refused. A file stays attachable for 24 hours after upload, and its upload link lasts 15 minutes.

Inbound Screening

Inbound screening is off by default and applies only to companies enrolled in the rollout. Before enrollment, an operator must enable Agent Armor for the inbox and confirm its scoped credential. The operator then enables the flag for the isolated company cohort, reruns the existing mailbox reprovisioning or trigger-enable operation to record the shared webhook secret for that company, and verifies completion delivery before reopening automation. The deployment's shared webhook subscribes to security-completion events independently of company flags; the company flag controls whether those events may dispatch message content. Enrollment does not configure provider Armor or credentials automatically.

For an enrolled company, thread summaries retain mailbox, thread, sender, recipient, date, and label metadata, but hide the subject and preview and set preview_withheld. In message detail, subject and body text are shown only when that message has a complete clear screening result. Pending, review, unavailable, missing, or invalid results hide the text and set content_withheld; agent_armor.status and agent_armor.verdict explain the result, with agent_armor.unavailable_reason when provided. A clear message may be readable in detail while its thread summary remains withheld. A provider-side release of a reviewed message does not currently make its text visible through these reads. Inbound attachment contents are not screened, so attachment download links are withheld while screening is enabled. Uploading and sending outbound attachments are unchanged.

The read filters follow the current company flag; they do not mean every historical message was screened. Disabling the flag restores legacy reads, but does not release an already-deferred receipt into automation. A receipt keeps the mode selected when it was first recorded: deferred receipts wait for the security-completion event, while ordinary receipts retain their received-event retry path. If a security-completion callback arrives before its received receipt exists for an enrolled linked inbox, the webhook returns a retryable 503 so the provider can try again.

While screening is enabled, historical CRM activity for inbound AgentMail mail also has its text and evidence link withheld in summaries, activity lists, and activity details. CRM text searches exclude those inbound activities before applying the result limit.

For automation, an enrolled inbox waits for the security-completion event even when the initial received event already includes a clear result; the received event records the inbound receipt but does not dispatch the message.

Use Your Own Mail Domain

Put the company's mail on a domain it owns, such as one from Domains. Mail can also go on a subdomain.

  1. Your agent adds the mail domain and gets the DNS records mail needs.
  2. If Cofounder runs your DNS, it adds missing records for you. If your DNS is elsewhere, or a record clashes with existing mail setup, you add or fix them at your DNS provider.
  3. Your agent verifies the domain.
  4. A verified mail domain has no inboxes yet. Your agent adds them.

If your DNS is elsewhere, your agent can give you a private setup link where you review and approve the records with a supported DNS provider. Keep it private. If it reports an existing mail provider, review the MX changes before approving, because they can replace that provider's records. Unsupported providers get a list of records to add by hand. Either way, your agent verifies afterward. Opening the link doesn't verify the domain.

Email Your CRM Contacts

A campaign sends one message to a list of CRM contacts, each as their own email, from news.<your-domain> by default. Choose another label with sender_subdomain on email_campaigns_setup. Results show opens, clicks, unsubscribes, and complaints. Campaigns need a paid plan and go to at most 5,000 contacts.

Every contact needs consent recorded for their current main email, and can't be marked do-not-contact or blocked from email. One ineligible contact blocks the whole send.

Set Up the Sender

Your agent sets up the campaign sender once and adds an unsubscribe footer. If Cofounder runs your DNS, it adds the records. Otherwise you add the records it returns. Sending works once DNS is verified and delivery tracking is ready.

Write the Campaign

A campaign draft holds the audience, sender name, postal address, subject, preview text, and message. The subject, preview text (up to 200 characters), and sender name are plain text.

  • Every email gets a footer with your company name, postal address, contact email, and an unsubscribe link.
  • Replies go to the company's main inbox, so they reach the CRM. With no inbox, the send is refused until your agent adds one or names another contact address. Replies to any other address won't reach the CRM.
  • Instead of plain text and HTML, the message can use an MJML template saved as a .mjml file in the Library. The draft saves that exact version of the file. Includes aren't supported, and templates with scripts, forms, or unsafe links are refused.

Test and Launch

Campaign → preview → test send to you → launch:

  1. Your agent previews the campaign: who would be left out and why, plus the finished email with its footer. Nothing is sent. It can also review the message against your goal and audience. That review uses model credit and opens no links.

  2. A test sends one copy to your own email, once per version of the draft, up to 50 test sends a day. After a known temporary refusal, wait any provided delay, then edit the draft before testing again; the old version keeps its saved result. Each edit makes a new version and clears its test.

    A saved test in preparing has not started dispatch. Retry its original request key to continue preparation. An uncertain test may have been sent; inspect its saved result before considering another send. Drafts cannot be edited while either state is active.

  3. Launch sends the campaign. A launch can't be undone, and the draft can't be edited after. Your agent starts a new draft for the next campaign.

If a launch fails midway, your agent retries it. It picks up where it stopped and never sends twice. Your agent can also skip the draft and send a campaign right away.

Track Results

A campaign is preparing, sending, sent, or blocked. Results show delivered, opens, clicks, unsubscribes, and complaints. A campaign waiting for review is held before sending. A paused campaign hit the daily marketing limit and continues at the time shown.

Open and click tracking is always on. Per-recipient delivery isn't kept. People who unsubscribe or complain are blocked in your CRM automatically. A launch can come back with the same notices as a single send.

Send Email From Your App

Your product app can send its own email from the company's verified sender: your own domain when it's ready, otherwise a shared sender.

Set Up App Email

Your agent sets up sending for one product app. Setup takes a while. It checks your plan and billing, then readies the sender. While DNS is still updating, your agent keeps checking the same setup instead of starting another.

Once ready, setup creates one sending key for the app and saves COFOUNDER_APP_EMAIL_API_KEY and COFOUNDER_APP_EMAIL_SEND_URL to the app's production environment. You never see the key. Running setup again reuses it, and other keys keep working. Setup doesn't confirm the running app picked up the settings or that any email arrived. Check both in the app before relying on it.

To restore removed or changed environment settings, run setup with --credential-action reinstall and a new setup idempotency key. This writes the existing valid sending key and current send URL again.

To replace a revoked, expired, or otherwise unwanted setup key, use --credential-action rotate --expected-key-id <saved-key-id> with a new setup idempotency key. Keep that same setup key while recovering an interrupted rotation. The previous sending key keeps its current state. After confirming the deployed app uses the replacement, revoke the previous key if it is still active.

Sender setup and reads return the same sender status, including DNS records, purpose, readiness, notices, and structured next_steps. App setup also returns structured next steps for sender checks and deployment inspection. A failed setup can offer a restart with the saved action and expected key identity; resolve the reported error before following it.

Send From Your App

Each email your app sends carries its own key. Repeating that key with the same content returns the saved result or checks whether the message was accepted. An uncertain message is not automatically sent again.

Live sends check the subject and both text and HTML before using allowance or submitting the email. Unsafe or unfinished content is blocked. Generic writing can return a non-blocking suggestion in notices on a fresh accepted receipt. Replaying an earlier receipt doesn't repeat the check. Test mode returns a simulated receipt without checking content or sending.

  • outbound_message_blocked_invalid: nothing was sent. Follow the reason in the response; do not work around a security block.
  • outbound_guard_unavailable: the content check couldn't finish, and nothing was sent. Retry the same call after the returned wait.
  • app_email_send_failed: nothing was sent. Fix the cause, then try again with a new key. A temporary refusal includes retry_after_seconds and a Retry-After header when the provider supplies a delay. Wait before trying again; the old key keeps its saved rejection.
  • app_email_unavailable: the message may have gone out. Check before sending again, and never retry automatically on this error.

Send Sign-Up and Sign-In Emails

Your app's sign-up and sign-in emails can come from the company's verified domain, or from a shared sender. Switching to your domain moves the app off the shared sender. This works for production and staging, and is separate from the company inbox and the app email key.

  • New managed setup runs set up the shared sender automatically. Older setups can turn it on once they have a verified sender.
  • Setup waits until the sender's DNS is verified, the sender isn't paused, and delivery tracking is ready. Until then it tells you what's left.
  • If setup is interrupted, your agent runs it again. It picks up where it left off and keeps the old credentials until the new ones are confirmed. This confirms the settings, not that email arrives.
  • It replaces empty settings or an earlier Cofounder setup. Settings from any other email provider are kept, and setup reports a conflict.

These emails send users back to your app's site URL and allowed redirect URLs. Your agent sets the site URL to the app's deployed URL and adds <site-url>/auth/callback as a redirect, so sign-up and password-reset links return to the app. Setting redirect URLs replaces the whole list.

Auth SMTP setup also adds a password-reset email with your company name, including when SMTP is already configured or setup resumes a saved attempt. It keeps existing custom templates and subjects.

Customize Password-reset Email

Read the current subject and HTML before making changes, and save both with the returned target so you can restore them later.

MCPCLIAPI

Select the database with resource; omit it to use the company default. project_target defaults to platform. Use staging_branch for its recorded staging branch.

cofounder email auth recovery get
cofounder email auth recovery update --template '{"subject":"Reset your password"}'

The update accepts a template with subject, html, or both. Omitted fields stay unchanged. Null and empty values are passed to Supabase without replacing them with the branded default. Restore a saved template by supplying both saved fields to the same target. The update confirms the saved values and sends no email. SMTP and redirect settings stay unchanged. Subjects allow up to 998 characters; HTML must fit within 1 MB.

Your agent can use the app's Graphical theme to prepare the HTML. Keep {{ .ConfirmationURL }} as the reset button's link. Active HTML and unsafe links are rejected. Verify the recovery flow and delivery separately; a styled template does not guarantee inbox placement.

Commands

Name your agent and add inboxes:

MCPCLIAPI

--mail-domain <domain> puts an inbox on a domain the company owns in Cofounder, and --mail-domain-id on a mail domain you set up. Running provision again with the same name and domain returns the same inbox.

Read and send:

MCPCLIAPI

Updating a saved draft (email_drafts_update, cofounder email drafts update) is not available to every company yet.

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 list --label unread
cofounder email threads <inbox-id> --label unread
cofounder email threads list --include-spam --include-trash
cofounder email threads get --thread-id <id>
cofounder email messages get --message-id <id> --resource <mailbox-id>
cofounder email messages labels set --message-id <id> --resource <mailbox-id> --add-label reviewed --remove-label unread
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 get --draft-id <id> --resource <mailbox-id>
cofounder email drafts update --draft-id <id> --subject <text> --bcc-empty
cofounder email drafts send --draft-id <id>
cofounder email drafts delete --draft-id <id>

To attach a file, reserve it with email attachments create, upload it to the returned link with a PUT, then pass its id with --attachment-id to a send, reply, or draft:

cofounder email attachments create --filename brief.pdf --content-type application/pdf --size-bytes 48213
curl -X PUT -H "Content-Type: application/pdf" --data-binary @brief.pdf "<upload_url>"
cofounder email messages send --to ada@example.com --subject "Brief" --body "Attached." --attachment-id <attachment_id>

Use your own mail domain:

MCPCLIAPI

After verifying, add inboxes with cofounder email provision --local-part <name> --mail-domain-id <id>.

Email your CRM contacts:

MCPCLIAPI

A draft's --content takes the audience, sender, and message. Its domain_binding_id is your company domain's id from cofounder domains get --resource <domain>, not the sender id that sender setup returns. cofounder domains list shows the domains to pass to sender setup.

{
  "domain_binding_id": "<domain-id>",
  "contact_ids": ["<crm-contact-id>"],
  "sender_name": "Acme",
  "postal_address": "1 Main St, Springfield, CA 94000",
  "subject": "We just launched",
  "preheader": "See what is new",
  "message": {
    "kind": "inline",
    "text": "Plain-text body",
    "html": "<p>HTML body</p>"
  }
}

For a template, use "message": {"kind": "template", "file_id": "<id>", "revision_token": "<token>"} with the file's current revision token.

Send email from your app:

MCPCLIAPI

<app-id> is the last part of the app's managed:vercel_project:<id> resource. Add --project-target staging_branch to email auth smtp setup or get to work on staging.