Coop
Concepts

Security

How Coop handles authentication, data isolation, and message security.

This page covers the security model behind Coop — how authentication works, how data is protected, and what trust assumptions the system makes.

Authentication methods

Coop supports two ways to authenticate API requests:

API keys are long-lived credentials designed for server-to-server use. When you create a key, the raw value is shown once. Coop stores only the bcrypt hash — if someone gains access to the database, they can't recover your keys.

JWT tokens are session-based credentials issued when a user logs in. They're short-lived and automatically refreshed. The dashboard uses them internally.

Both methods provide the same level of API access. The difference is lifecycle: API keys are persistent and must be manually revoked, while JWTs expire on their own.

Tenant isolation

Every API request is scoped to the authenticated user's organization. This is enforced at the database query level — not through application logic that could be accidentally bypassed.

When you call GET /api/v1/contacts, the query includes a WHERE tenant_id = ? clause automatically. There's no API endpoint that operates across tenants, and no admin backdoor that returns data from multiple organizations.

Sub-teams add a second layer within an organization, isolating contacts and conversations between teams while sharing organization-level resources like members and API keys.

Webhook signing

Webhooks are the one place where data flows from Coop to your server. Without verification, anyone who discovers your webhook URL could send fake events.

When you register a webhook with a signing secret, every delivery includes an X-Webhook-Signature header — an HMAC-SHA256 hash of the raw request body using your secret. Validating this hash confirms the request came from Coop.

This is optional but strongly recommended for production use. See the webhooks guide for implementation examples.

Coop Desktop

Coop Desktop runs on your Mac. Coop (the hosted service) never has access to your Apple ID, iMessage password, or Mac login credentials.

The relay authenticates with a short-lived registration token (valid for 30 minutes) and then maintains a persistent WebSocket connection. It reads from the local iMessage SQLite database (read-only) to sync conversations and uses AppleScript to send outgoing messages through the Messages app.

Message content passes through the Coop API for routing and storage. If this is a concern for your use case, be aware that message bodies are stored in the database for conversation history and delivery tracking.

Rate limiting

API rate limits are enforced per tenant: 100 requests per minute with a burst allowance of 20. This prevents any single organization from degrading the service for others. When you hit the limit, the API returns 429 with a Retry-After header.

What's stored

  • Passwords — bcrypt hashed, never stored in plaintext
  • API keys — bcrypt hashed after initial display
  • Messages — stored for conversation history and delivery tracking
  • Contacts — stored in your organization's isolated database partition
  • Webhook secrets — stored encrypted for signing outbound deliveries

On this page