# Blueticked

This project integrates with Blueticked. Use the configured `blueticked` remote MCP server for discovery and testing. Do not guess the REST contract from memory.

## Required workflow

1. Read the Blueticked MCP resource `blueticked://docs/full`, or fetch https://app.blueticked.com/llms-full.txt when MCP resources are unavailable.
2. Call `get_workspace_context` before making workspace-specific requests. Use only the returned business IDs.
3. Call `list_channels` before implementing a send path. Do not assume a channel is connected.
4. Authorize a Test OAuth connection first (or use a `blu_test_...` service key). Test access validates the full send lifecycle without contacting a recipient or spending wallet credit.
5. Send a stable `Idempotency-Key` on every create, send, launch or replay, and reuse it only to retry that same intended operation. Read "Retry safety" below first: most POST routes ignore the header, and a blind retry on one of those creates a second resource.
6. Treat HTTP 202 as accepted, not delivered. Inspect the event outcome before assuming it queued a send. Confirm final delivery through signed webhooks or the message status endpoint.
7. Require explicit human approval before a live campaign, WhatsApp Form publish, or any action that can contact customers or spend credit.
8. Never hard-code keys or webhook signing secrets. Read them from environment variables and never print them to logs.

## Sources of truth

- Remote MCP: https://app.blueticked.com/api/mcp
- Complete agent-readable reference: https://app.blueticked.com/llms-full.txt
- OpenAPI 3.1: https://app.blueticked.com/api/v1/openapi.json
- Integration recipes: https://app.blueticked.com/agent-kit/integration-recipes.md

When docs and assumptions disagree, follow OpenAPI and the live MCP tool schema. Never infer undocumented fields.

## Retry safety

`Idempotency-Key` is honoured by 15 POST routes and ignored by every other endpoint in the API. Only these deduplicate a repeated key:

- POST /api/v1/messages
- POST /api/v1/campaigns
- POST /api/v1/contacts
- POST /api/v1/templates
- POST /api/v1/flows
- POST /api/v1/events/send
- POST /api/v1/webhooks
- POST /api/v1/integrations
- POST /api/v1/groups
- POST /api/v1/flows/{id}/publish
- POST /api/v1/webhook-deliveries/{id}/replay
- POST /api/v1/webhooks/{id}/replay-failed
- POST /api/v1/tables/{id}/rows
- POST /api/v1/studio-flows
- POST /api/v1/templates/{id}/submit

Anywhere else (creating a product, discount, payment link, site, business, API key, suppression entry, journey enrolment, sending domain or webhook test), the header is accepted and discarded. A timeout or 5xx there may still have committed, so never retry blind: re-read the resource and reconcile first. `@blueticked/sdk` enforces this for you and raises `retry_unsafe` instead of repeating an off-list POST.

## Claude Code setup

If the MCP server is not configured, connect it in this order:

1. Register the server: `claude mcp add --transport http --scope user blueticked https://app.blueticked.com/api/mcp` (other MCP clients use the same URL). This only writes config; nothing connects yet.
2. Authenticate: in Claude Code start a new session, type /mcp, choose blueticked, then Authenticate. The browser opens Blueticked's approval page, where the person picks the businesses, the access profile, Test or Live, and an expiry. The client stores and refreshes the tokens; no key is copied.
3. Without OAuth (a script, a CI job, or a client that cannot sign in): create a connection in Agent access (https://app.blueticked.com/developers/agent-access), copy its key once into the environment as BLUETICKED_AGENT_KEY, and send it as the Authorization header: `claude mcp add --transport http --scope user blueticked https://app.blueticked.com/api/mcp --header "Authorization: Bearer $BLUETICKED_AGENT_KEY"`. The shell expands the variable when you run it, so Claude Code stores the key in its MCP config. A full API key (blu_ prefix) from /developers/keys works the same way.

Never ask the developer to paste a Blueticked password or API key into chat.

Do not hand-roll the OAuth flow. A compliant MCP client already implements it. If you do call `/api/oauth/token` directly, every request needs `resource=https://app.blueticked.com/api/mcp` (RFC 8707); omitting it returns `invalid_target`, which no amount of re-authorizing will clear.

Use the MCP prompts for common integrations. Start with `integrate_sms_otp`, `integrate_whatsapp_notifications`, `integrate_transactional_email`, or `integrate_webhooks` as appropriate.

Before completing an integration, run the checks in the `audit_integration` MCP prompt and report any live-provider step that still requires the account owner.
