# Keys and origins

GraveMint partner keys are invite-only. Request a key with the collections you plan to integrate and the origins where your application will run.

## The three classes

| Class | Prefix | Use | Restrictions |
| --- | --- | --- | --- |
| Publishable | `gm_pub_` | Browser applications | Registered origins and collection scope |
| Secret | `gm_live_` | Servers and MCP clients | Collection scope; keep the key private |
| Sandbox | `gm_test_` | Browser development on test networks | Registered origins, collection scope and test networks only |

Use the prefix to identify a key's class when configuring an application or contacting support.

## Publishable keys {#a-publishable-key-is-public-by-construction}

A publishable key is designed to appear in a browser bundle. The API checks its registered origins and collection scope on each request. Sandbox keys add a test-network restriction.

Origin checks are browser access controls; they do not make a publishable key a secret. Keep its scope limited to the collections your integration needs.

## Server keys {#gm-live-never-reaches-a-browser}

Store `gm_live_` keys in server environment variables, such as `GRAVEMINT_API_KEY`. Variables with public build prefixes, including `NEXT_PUBLIC_`, `VITE_`, `REACT_APP_` and `EXPO_PUBLIC_`, can be included in browser bundles and must not contain a server key.

Use a server key for backend calls. Publishable and sandbox keys require a matching `Origin` header, which a server request does not normally send.

## Registering origins

Register each origin that will make browser requests:

- Production, such as `https://yourdrop.io`.
- The `www` hostname as well, if it serves your application.
- Staging and local development origins, including their ports.
- Each preview hostname, or a fixed preview hostname used across builds.

Origins match exactly. An origin consists of the scheme, host and port, so HTTP and HTTPS are separate origins. Wildcard preview domains are not supported.

## Scope

A key grants access to specific collections. A request outside that scope returns `403 COLLECTION_NOT_IN_SCOPE`, whether or not the requested collection exists. A key with no assigned collections does not grant collection access.

Collection scope applies to reads as well as mint operations.

## Rate limits

| Operation | Limit | Scope |
| --- | --- | --- |
| Reads | 600/min | Per IP |
| `prepare` and `execute`, combined | 60/min | Per key |
| Collection `prepare` | 30/10s | Per collection, shared with gravemint.io |

A single mint normally uses one prepare and one execute request. Both count toward the same per-key limit, and the collection limit also applies. Handle `429` responses using `Retry-After`; see [SDK retry behavior](https://docs.deads.io/sdk/gravemint.md#errors-and-retries) for the distinction between reads and transaction submission.

## Key rotation {#if-a-key-leaks}

If a server key is exposed, request revocation and replace it. Revocation prevents further use; it does not reverse completed mints.

For a planned rotation, issue the replacement, update the application, then revoke the old key after confirming the replacement works.

## Sandbox keys

Use a `gm_test_` key with a collection on a test network. Sandbox keys return `SANDBOX_KEY_ON_MAINNET` on production chains; production keys return `LIVE_KEY_ON_TESTNET` on test networks. The [API reference](https://docs.deads.io/api/gravemint-v1.md) uses a sandbox key scoped to a devnet collection.

---
Source: https://docs.deads.io/guides/keys
Markdown: https://docs.deads.io/guides/keys.md
