> ## Documentation Index
> Fetch the complete documentation index at: https://docs.merchantops.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Server API keys

> Create, scope, rotate, and revoke keys that let your own services call the MerchantOps API.

**Settings › API Keys** manages *server* API keys — long-lived credentials for
software you run: a nightly import job, a publishing worker that polls
MerchantOps for pending work, or any service that calls the
[REST API](/api-reference) without a person signing in.

This is the credential for **machine-to-machine** access. Interactive tools
authenticate as *you* instead: the [MCP server](/tools/mcp) and the
[CLI](/tools/cli) both use browser-based OAuth sign-in and never take an API
key.

<Warning>
  Creating, rotating, and revoking API keys is **Owner-only**. Admins, Editors,
  and Viewers don't see the page. See [Team & roles](/settings/team-and-roles).
</Warning>

## Create a key

<Steps>
  <Step title="Open Settings › API Keys">
    Sign in as an organization Owner and choose **Create API Key**.
  </Step>

  <Step title="Name it">
    Use a name that identifies the service, not the person — for example
    `Nightly catalog import` or `Pricing publish worker`. The name is how you'll
    recognize the key later when deciding what to rotate or revoke.
  </Step>

  <Step title="Assign roles">
    Tick one or more roles. **There is no per-key scope picker** — a key's
    permissions are exactly the permissions bundled into the roles you assign,
    the same roles you assign to people. At least one role is required; a key
    with no usable role authorizes nothing and every call it makes is rejected.
  </Step>

  <Step title="Copy the key">
    MerchantOps shows the full key **once**, immediately after creation. Copy it
    into your secret store now — it cannot be retrieved again. If you lose it,
    rotate the key to get a new secret.
  </Step>
</Steps>

<Tip>
  Give each service its own key. One key per service means you can rotate or
  revoke that service's access without taking anything else down, and the
  **Last used** column tells you which keys are still live.
</Tip>

## Use a key

A key has two halves — a public identifier and a secret — joined by a colon and
sent as a bearer token:

```http theme={null}
Authorization: Bearer mcp_key_<id>:mcp_secret_<secret>
```

```bash theme={null}
curl "$MERCHANTOPS_API_URL/api/products" \
  -H "Authorization: Bearer mcp_key_...:mcp_secret_..."
```

Use the API base URL your MerchantOps admin gave you for your organization.

Both halves are required, in that exact form. The API rejects a malformed token,
an unknown or revoked key, and a key whose roles resolve to no permissions —
each with its own error, so a misconfigured key fails loudly rather than
silently returning empty results.

<Note>
  Keys are scoped to the organization that created them. A key can only ever read
  or change that organization's data, and only through actions its roles allow —
  the same permission checks that apply to a signed-in member.
</Note>

## What a key can do

Permissions come from **roles**, not from the key. Assigning the `Viewer` role
produces a read-only key; assigning a pricing-capable role produces a key that
can also write price records. Roles are configured for your organization, so the
list you see in the key dialog is the same list the member-invite dialog shows.

The rule of thumb: **assign the least-privileged role that lets the service do
its job.** A key that only reads the catalog should never carry an approving or
deleting role.

| Want the key to…            | Assign a role that includes                                        |
| --------------------------- | ------------------------------------------------------------------ |
| Read catalog data           | `product:read`, `product_type:read`                                |
| Import or update products   | `product:write`                                                    |
| Read pricing                | `pricing:read`                                                     |
| Write price records         | `pricing:write`                                                    |
| Run your own publish worker | `pricing.publish.outcome:read` and `pricing.publish.outcome:write` |

<Note>
  Those are permission names, not role names — they're what a role bundles. If no
  configured role matches what a service needs, ask your MerchantOps admin about
  adding one rather than over-granting an existing role.
</Note>

## Rotate and revoke

Two lifecycle actions, both immediate:

<ResponseField name="Rotate" type="new secret, same key id">
  Issues a new secret while keeping the same key identifier. The old secret
  stops working the moment you rotate, so update the service's configuration in
  the same maintenance window. Use this for scheduled rotation, or when a secret
  may have been exposed but the service is otherwise fine.
</ResponseField>

<ResponseField name="Revoke" type="key is disabled">
  Deactivates the key permanently. Anything using it loses access immediately.
  The record is retained for audit history rather than erased. Use this when a
  service is decommissioned or a key is compromised.
</ResponseField>

<Warning>
  Keys created here never expire on their own — there is no expiry control in the
  create dialog, so a key stays valid until you rotate or revoke it. Put rotation
  on a calendar and revoke keys for services you've retired. One exception: a key
  created through the API with an `expires_at` timestamp stops authenticating at
  that time.
</Warning>

## How this differs from MCP and CLI access

|                      | Server API key                                     | MCP server / CLI                                     |
| -------------------- | -------------------------------------------------- | ---------------------------------------------------- |
| Who it acts as       | A service you run                                  | The signed-in member                                 |
| How you authenticate | Paste a long-lived key into your service's secrets | Browser OAuth sign-in, no key to paste               |
| Permissions from     | Roles you assign to the key                        | The member's own roles                               |
| Can write            | Yes, if its roles allow                            | CLI: as the member allows. MCP: no — it is read-only |
| Lifecycle            | Rotate / revoke in Settings › API Keys             | Sign out or disconnect the client                    |

<CardGroup cols={2}>
  <Card title="Connect the MCP server" icon="robot" href="/tools/mcp">
    Read-only catalog tools for Claude, over OAuth.
  </Card>

  <Card title="Team & roles" icon="users" href="/settings/team-and-roles">
    What each role can do, and who can manage keys.
  </Card>
</CardGroup>
