# Blueticked integration instructions

Use these instructions whenever this repository sends WhatsApp, SMS, or email through Blueticked, consumes Blueticked webhooks, manages contacts, or triggers Blueticked flows.

## 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.

## Implementation rules

- Prefer the typed Blueticked MCP tools. Use `list_endpoints` and `call_api` only when no typed tool covers the task.
- Keep Blueticked calls in one small adapter/service boundary in the host application.
- Validate recipient phone numbers as E.164 and email addresses before calling the API.
- Verify webhook signatures against the raw request body before parsing JSON. Reject stale timestamps and use delivery IDs for deduplication.
- Persist Blueticked message IDs and idempotency keys so retries and asynchronous status updates can be reconciled.
- Handle 401, 403, 409, 422, 429, and 5xx responses explicitly. Respect `Retry-After`; do not retry validation or permission errors.
- Do not expose provider names or credentials to the host application's end users. Blueticked is the integration boundary.

## Definition of done

- A test-key request succeeds.
- An invalid payload produces the expected validation error.
- A duplicate idempotency key does not duplicate the action on a route listed under "Retry safety", and every other POST reconciles by re-reading rather than by retrying.
- A signed test webhook is accepted once and a replay is deduplicated.
- Live mode remains disabled until a human approves the production cutover.
