# Environments and API keys (/docs/environments)

## Organizations and projects [#organizations-and-projects]

Everything in coss.com belongs to an **organization**. Its people are owners, admins or members
(see [members and roles](/docs/members-and-roles)).
An organization has any number of **projects**, and each project has two **environments**:

| Environment   | Mode      | Key prefix   | Sends email                                      |
| ------------- | --------- | ------------ | ------------------------------------------------ |
| `production`  | `live`    | `coss_live_` | Yes, from your organization's verified domains   |
| `development` | `sandbox` | `coss_test_` | No. Emails are recorded with `sandbox: true`     |

## API keys [#api-keys]

An API key belongs to exactly one environment, and everything it creates or reads lives in that
environment. A key can only read emails sent from its own environment.

### Personal keys [#personal-keys]

A key is either an **organization key**, for production servers, staging and shared jobs, or a
**personal key** assigned to one member: what a personal key sends counts as that member's spend,
so developers can experiment with their own keys and you can see (and cap) what each of them
costs.

- Owners and admins create both kinds, and can assign a personal key to any member.
- Members create personal keys for themselves in environments an owner or admin has opened to
  them (the switch on the environment's API keys page). New projects open their development
  environment and keep production closed; closing an environment leaves existing keys working.
- `coss login` and `coss init` create personal keys of the member who approves them.
- A personal key works only while its owner is a member: it is revoked when they leave or are
  removed (also by directory sync), and refused while their account is banned.
- Organization-wide permissions (managing domains, reading billing and the audit log) work on a
  personal key only while its owner's role allows them in the dashboard. Everything else in its
  environment is available to it, so opening an environment gives members write access to it
  through their keys.

### Permissions [#permissions]

When you create a key in the dashboard, you choose what it can do:

| Access             | Can                                                                                  |
| ------------------ | ------------------------------------------------------------------------------------ |
| **Full access**    | Everything, including the permissions of products coss.com adds later                |
| **Sending access** | Only `email:send`: send, schedule and cancel emails through the API, the SDK or SMTP |
| **Read only**      | Every `read` permission below                                                        |
| **Custom**         | The permissions you check                                                            |

Keys with sending access, read-only access or custom permissions are **restricted**. A restricted key
keeps exactly the permissions it was created with: it never gains new ones, even when coss.com adds
products. Give each server or job the narrowest key that does its work: an application that only
sends email needs only sending access.

A request the key isn't allowed to make fails with `403` `permission_error`
(`insufficient_permissions`), and the message names the permission it needed. Any key can read
its own environment and access with `GET /v1/environment`
(`coss.environment.get()`: `api_key.access` and `api_key.permissions`) and revoke itself.
To change what a key can do, create a new key and revoke the old one.

| Resource | Permissions | Covers |
| --- | --- | --- |
| Emails | `email:send`, `email:read` | Send, schedule and cancel emails (API, SDK and SMTP), change tracking and content storage settings; read sent and received emails, their events and those settings. |
| Templates | `emailTemplate:create`, `emailTemplate:read`, `emailTemplate:update`, `emailTemplate:delete`, `emailTemplate:publish` | Manage email templates and publish their versions. |
| Received emails | `receivedEmail:delete` | Delete received emails (reading them needs Emails: Read). |
| Inboxes | `inbox:create`, `inbox:read`, `inbox:update`, `inbox:delete`, `inbox:send` | Create, rename and delete inboxes; read their threads and messages, send and reply from them. |
| Domains | `domain:create`, `domain:read`, `domain:verify`, `domain:delete` | Add, verify and remove sending domains; read them and dedicated IPs. |
| Suppressions | `suppression:create`, `suppression:read`, `suppression:delete` | Manage the suppression list. |
| Contacts | `contact:create`, `contact:read`, `contact:update`, `contact:delete` | Manage contacts, audiences, segments and topics. |
| Broadcasts | `broadcast:create`, `broadcast:read`, `broadcast:update`, `broadcast:delete`, `broadcast:send` | Manage broadcasts and send them. |
| Sub-accounts | `subaccount:create`, `subaccount:read`, `subaccount:update`, `subaccount:delete` | Manage sub-accounts (your users' own domains, suppressions, quotas and reputation) and reinstate paused ones; read them and their stats. |
| Reputation | `reputation:read` | Read the organization's sending reputation. |
| SMS | `sms:send`, `sms:read` | Send, schedule and cancel text messages; read sent and received messages, their events and the organization's numbers. |
| SMS suppressions | `smsSuppression:create`, `smsSuppression:read`, `smsSuppression:delete` | Manage the SMS suppression list. |
| Signature requests | `sign:create`, `sign:read`, `sign:update`, `sign:delete`, `sign:send` | Upload documents, create, send and cancel signature requests; read them, their signers and audit trails. |
| Verifications | `verify:send`, `verify:check`, `verify:read`, `verify:update` | Start, check and cancel verifications (one-time codes by SMS or email); read them; change Verify's settings. |
| Forms | `form:create`, `form:read`, `form:update`, `form:delete` | Create and change forms; read their submissions and files, release submissions held as spam and delete them. |
| Scheduling | `scheduling:create`, `scheduling:read`, `scheduling:update`, `scheduling:delete` | Manage hosts, event types and settings; read availability; create, change and cancel bookings. |
| Webhooks | `webhook:create`, `webhook:read`, `webhook:update`, `webhook:delete` | Manage webhook endpoints and listeners and send test events; read deliveries. |
| Logs | `log:read` | Read the environment's logs. |
| Log drains | `logDrain:create`, `logDrain:read`, `logDrain:update`, `logDrain:delete` | Manage log drains. |
| Audit log | `audit:read` | Read the organization's audit log. |
| Risk | `risk:assess`, `risk:read`, `risk:feedback`, `risk:update` | Assess events and run lookups, report feedback, read assessments and change risk settings and rate limits. |
| Risk lists | `riskList:create`, `riskList:read`, `riskList:delete` | Manage allow and block lists. |
| Risk rules | `riskRule:create`, `riskRule:read`, `riskRule:update`, `riskRule:delete` | Manage risk rules. |
| Hooks | `hook:create`, `hook:read`, `hook:update`, `hook:delete`, `hook:send` | Manage Hooks applications, event types and endpoints; send messages. |
| Billing | `billing:read` | Read the plan, usage, invoices and credits. |

Keys are secrets. Call coss.com from your server, never from a browser: the SDK refuses to run where a
`document` global exists unless you opt in with `dangerouslyAllowBrowser`.

Creating a live key requires a verified email address on your account.

## Sandbox behaviour [#sandbox-behaviour]

Sandbox keys accept any `from` address and never deliver anything. Delivery events are simulated
the way the Amazon SES mailbox simulator behaves, so you can test failure handling:

| Recipient                                  | Simulated events                                  | Recipient status |
| ------------------------------------------ | ------------------------------------------------- | ---------------- |
| any address outside `simulator.amazonses.com` | `email.delivered`                              | `delivered`      |
| `bounce@simulator.amazonses.com`           | `email.bounced` (permanent)                       | `bounced`        |
| `complaint@simulator.amazonses.com`        | `email.delivered`, then `email.complained`        | `complained`     |
| `suppressionlist@simulator.amazonses.com`  | `email.bounced` (on the suppression list)         | `suppressed`     |

Every sandbox email also gets `email.sent`.

Every other product works in a sandbox too, and nothing is billed unless the table says so:

| Product                         | In a sandbox                                                                                                              | Testing                                  |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
| [Marketing email](/docs/email/broadcasts) | Broadcasts and other marketing sends are simulated like any email above.                                        | The table above                          |
| [Inboxes](/docs/inboxes)        | Every inbox can send, and nothing is delivered. Simulate received mail from the dashboard; real mail to one is received. | [Testing inboxes](/docs/inboxes/testing) |
| [SMS](/docs/sms)                | Any `from` number works, nothing is sent, and the simulator's numbers produce each delivery outcome.                      | [SMS simulator](/docs/sms/testing)       |
| [Verify](/docs/verify)          | The code is always zeros, and nothing reaches a phone or mailbox. The fraud guard still runs.                             | [Testing Verify](/docs/verify/testing)   |
| [Sign](/docs/sign)              | Requests complete on the real signing page, which says it's a test. Emails go to the dashboard, not to signers.           | [Testing Sign](/docs/sign/testing)       |
| [Forms](/docs/forms)            | Posts are screened, stored and delivered, and emails go to the dashboard. `http://localhost` is allowed while you develop. | [Testing Forms](/docs/forms/testing)     |
| [Scheduling](/docs/scheduling)  | Everything works as live, with simulated calendars available. Nobody is emailed.                                         | [Testing Scheduling](/docs/scheduling/testing) |
| [Hooks](/docs/hooks)            | Messages are delivered for real to your endpoints' URLs, under lower limits.                                              | [Testing Hooks](/docs/hooks/testing)     |
| [Risk](/docs/risk)              | Assessments work as live with their own memory, and test inputs trigger each reason.                                      | [Testing Risk](/docs/risk/testing)       |

Real mail a sandbox environment receives, at an inbox or any of its addresses, is billed as
[received email](/docs/email/receiving#limits-and-retention).
