---
title: Test and live keys
description: Two environments, two key types, and what each one can reach.
---

Every API key is one of two environments and one of two types. The
prefix tells you which, at a glance and in a log.

| Prefix | Environment | Type | Safe in a browser |
|---|---|---|---|
| `sk_live_` | Live | Secret | No |
| `sk_test_` | Test | Secret | No |
| `pk_live_` | Live | Publishable | Yes |
| `pk_test_` | Test | Publishable | Yes |

## Test keys

A test key validates everything and sends nothing.

Your request is authenticated, the body is checked, the topic is
resolved, the contact is written. What does not happen is the part with
real-world consequences: no email leaves, and no webhook fires at your
endpoint.

That last one catches people out, and it is deliberate. A sandbox call
that reached your production webhook would have your CRM record a
subscriber who does not exist.

Test keys write to the same audience as live keys. If you subscribe
`ada@example.com` with a test key, Ada is really in your contacts. Use
addresses you recognise as fake, and clean them up before you launch.

## Publishable keys

A publishable key can do exactly one thing: `POST /v1/subscribe`.

That is the whole permission. It cannot read your contacts, cannot
export anything, cannot send, cannot change settings. Every other
endpoint refuses it, with `publishable_key_not_allowed`, even if the
key belongs to your workspace and the endpoint would otherwise work.

This is what makes it safe to put in a page's source, where anybody
can read it. The worst somebody can do with a stolen publishable key is
add addresses to a topic — which is why confirmation email matters, and
why we rate-limit that route.

**Restrict the origins.** When you create a publishable key you can
name the domains allowed to use it. Do. It turns a copied key into a
key that only works from your own site.

## Secret keys

Secret keys reach the rest of the API: reading contacts, importing,
suppressing, managing lists and topics.

Keep them on your server. We show a secret key **once**, at creation.
We store only a hash, so if you lose it we genuinely cannot recover it
and you will need to create another.

Rotating is uneventful: create a new key, deploy it, then revoke the
old one. Both work during the overlap.

## Scoping a key to one brand

A key can be limited to a single brand. If it is, every call through it
sees only that brand's topics, lists and campaigns, and a call naming
another brand's topic is refused.

If you run an agency, scope one key per client. A mistake then affects
one client instead of all of them.

## Switching to live

Swap the key. There is no other switch to flip, no separate base URL
and no "go live" button.

Before you do, check:

- your webhook endpoint is reachable from the public internet
- you are verifying webhook signatures ([how](/webhooks/signatures))
- your brand and sending domain are approved
  ([how](/guide/approval))
- the test contacts you created are gone