# auth.md

You are an agent that wants to work in Chargezen for a person. This file says how to get access,
how a new person signs up, and what you must never do along the way.

Chargezen is a revenue platform for commerce brands: Concierge AI agents, Subscriptions,
CheckoutOS, SmartyTap (texting, email and calls) and Spark! (affiliates and creators).

Hosts:

- **MCP server and authorization server:** `https://mcp.chargezen.com`. The whole platform is at
  `https://mcp.chargezen.com/mcp`; each product also has its own endpoint at
  `https://mcp.chargezen.com/mcp/<product>` (`concierge`, `subscriptions`, `checkoutos`, `spark`,
  `smartytap`).
- **Admin app:** `https://admin.chargezen.com`, where the person signs in, signs up and approves
  access.

Discovery: `https://chargezen.com/.well-known/mcp.json` and the get-started skill at
`https://chargezen.com/.well-known/agent-skills/get-started/SKILL.md`.

## The supported way in: connect the MCP server with OAuth

There is no API key to copy into chat. The person connects Chargezen to you as a remote MCP
server and signs in in their browser:

1. Add `https://mcp.chargezen.com/mcp` as a custom connector (or remote MCP server) in your app.
2. The app opens Chargezen's sign-in. The person signs in, or creates an account on the same
   screen (see "A new person" below).
3. The person picks the workspaces to connect, reviews what you may do, and presses Allow.
4. You call tools as that teammate, with that teammate's permissions, checked on every call.

Protocol details for MCP clients:

- OAuth 2.1 authorization code with PKCE (S256). Refresh tokens rotate; reusing an old one
  revokes the grant.
- Clients identify themselves with a Client ID Metadata Document (the `client_id` is an HTTPS URL).
  There is no registration endpoint and nothing to pre-register.
- Protected resource metadata (RFC 9728):
  `https://mcp.chargezen.com/.well-known/oauth-protected-resource/mcp[/<product>]`.
- Authorization server metadata (RFC 8414):
  `https://mcp.chargezen.com/.well-known/oauth-authorization-server`.
- A token works only on the endpoint it was issued for. A sign-in at `/mcp` covers every product
  endpoint too: name the one you want as `resource` at the token endpoint, and you get a token for
  it with that product's share of the granted scopes (`scope` in the response says which). A
  connector added at a product endpoint reaches only that product.
- Ask for no scopes to be offered every scope the endpoint has; the person can grant fewer.

On a phone: phone chat apps can't easily take a pasted server URL. In Claude, add the connector
once at claude.ai on the web (Settings → Connectors → Add custom connector); it then appears in the
mobile app too. Sign-in and the approval page work in the app's in-app browser.

### Several workspaces

One connection can reach several workspaces. When it does, every tool takes a `workspace`
argument naming the one to act in, and `chargezen.connection.get_profile.v1` lists them.

## A new person

There are three ways in. Use the first one your app allows. In each, the person does every step
that proves who they are, in their own browser. Confirm the details with the person before you
send anything.

1. **Your app can add a connector (preferred):** add `https://mcp.chargezen.com/mcp` (or
   `/mcp/<product>`). On the sign-in screen the person chooses to create an account, and after
   signup they come straight back to the approval page. One flow, also on a phone.
2. **You can make HTTP requests but can't add a connector:** start the signup for them, then
   connect once they're done.

   ```http
   POST https://admin.chargezen.com/api/v1/agent_signups
   Content-Type: application/json

   { "email": "sam@brand.com", "first_name": "Sam", "last_name": "Lee",
     "company_name": "Brand Co", "website_url": "brand.com", "product": "smartytap",
     "business_address": { "country_code": "US", "address1": "1 Main St", "city": "Austin",
                           "province": "TX", "zip": "78701" },
     "client_id": "https://your-host.example/oauth-client-metadata.json" }
   ```

   Only `email` and `client_id` (your Client ID Metadata Document URL) are required. Add
   `"product"` when the person wants one product: `subscriptions`, `checkoutos`, `smartytap`,
   `spark` or `concierge` (the same names as the MCP endpoints). Chargezen emails the person a
   link that names you. Your details are only suggestions they check. The response is `202` with
   `{ "id": "…", "status": "waiting" }`. Read
   `GET https://admin.chargezen.com/api/v1/agent_signups/{id}` when the person says they're done,
   or now and then while they work through it. It returns only `waiting`, `finished`,
   `under_review` or `expired`. On `finished`, connect; the person is already signed in, so they
   only press Allow.
3. **Neither (most phone chat apps), or the request got a `429`:** show the person a signup link
   with the details they gave you filled in:
   `https://admin.chargezen.com/signup?email=…&company=…&website=…&agent=<your host>`, plus
   `&product=<one of the names above>` when they want one product. URL-encode each value. The
   fields are only a starting point. Once they've signed up, connect.

The person does all of this in their browser:

- confirming their email with the code Chargezen sends;
- confirming their phone with a text message code;
- adding a card;
- accepting the terms.

New signups are sometimes held for a short review. If that happens, tell the person: "Chargezen
is reviewing your signup and will email you." Then connect once they're approved.

## Workspace API keys (servers, not chat)

For a person's own server code there is a REST API at `https://api.chargezen.com/v1` that takes a
workspace API key from Settings → API keys in the admin app. Never ask the person to paste a key
into the conversation. Ask them to put it in an environment variable or secret store you can read,
and read it from there at the moment of the call. Never echo, log or commit it.

## What you must never do

- Never ask for, read out or type email codes, text message codes or passwords. The person enters
  them in their browser.
- Never ask for or handle card details.
- Never accept terms or agreements for the person.
- Never send anything (an email, a text, a campaign, a launch) without the person's confirmation
  first.
- Never get around a rate limit, a review hold or a confirmation, for example by retrying from
  another address or with another email.

## Confirmations

Big changes (deleting, launching, publishing) need the person's OK. ChatGPT and Claude ask with
their own prompt. Other clients either show Chargezen's confirmation form, or get a
`CONFIRMATION_REQUIRED` result with a `confirmation_token`: ask the person, then repeat the
identical call with that token. An identical change repeated within two minutes returns the first
call's result instead of acting again.

## Errors

| Status | Meaning | What to do |
| --- | --- | --- |
| `401` with `WWW-Authenticate` | No token, an expired one, or a token for another endpoint. | Follow `resource_metadata` in the header and sign in again. |
| Tool result naming a missing permission | The teammate lacks that permission in Chargezen. | Tell the person which permission; an owner or admin can grant it. |
| `429` | Rate limited. | Wait for `Retry-After`, then retry once. For `agent_signups`, show the prefilled signup link instead. |

## Revoking access

The person can disconnect you at any time in the admin app under Settings → Connected AI
assistants, or by removing Chargezen in your app. Disconnecting stops access right away; treat a
`401` on a working connection as revoked and ask the person to reconnect.
