Mirror of https://github.com/roostorg/coop
github.com/roostorg/coop
1# API Keys and Authentication
2
3## Sending requests to Coop
4
5To authenticate the requests you send to Coop, add an HTTP header to every API request with your organization's API key. You can find or manage your API key in **Settings → API Keys** in the Coop UI.
6
7Format the header as follows:
8
9```
10X-API-KEY: <<apiKey>>
11Content-Type: application/json
12```
13
14You can rotate your API key at any time from the same page. After rotating, update any applications or scripts that use the previous key.
15
16## Verifying incoming requests from Coop
17
18To verify that an incoming request to your Action APIs (or other webhooks) was sent by Coop, you can check the request signature. Coop signs each HTTP request it sends to your endpoints and includes the signature in a header. You use a **webhook signature verification key** (public key) to verify that signature.
19
20- Your **webhook signature verification key** is shown in **Settings → API Keys** under "Webhook Signature Verification Key". You can generate a new key there when needed; after rotation, update your verification logic with the new public key.
21
22### Validating requests with the signature header
23
24Coop sends the signature in a `Coop-Signature` header (or `coop-signature` depending on the client). To validate an incoming HTTP request:
25
261. **Hash the request body** using SHA-256. Use the raw request body (binary) as the input to the hash.
272. **Base64-decode** the value in the `Coop-Signature` header to obtain the raw binary signature.
283. **Verify the signature** using your public key. Coop uses **RSASSA-PKCS1-v1_5** with **SHA-256**: decrypt/verify the signature with your public key and confirm it matches the hash from step 1. Use your language’s crypto library (e.g. Web Crypto, OpenSSL, or standard crypto packages) for RSASSA-PKCS1-v1_5 verification.
29
30### Example (JavaScript / Node)
31
32```javascript
33// Your public signing key in PEM format (from Settings → API Keys)
34const pem = `-----BEGIN PUBLIC KEY-----
35...your key...
36-----END PUBLIC KEY-----`;
37
38const pemHeader = "-----BEGIN PUBLIC KEY-----";
39const pemFooter = "-----END PUBLIC KEY-----";
40const publicKeyPem = pem.substring(
41 pemHeader.length,
42 pem.length - pemFooter.length
43);
44
45const publicKeyBuffer = Buffer.from(publicKeyPem, "base64");
46const requestBodyBuffer = Buffer.from(req.body, "utf8");
47const signature = Buffer.from(req.headers["coop-signature"], "base64");
48
49const publicKey = await crypto.subtle.importKey(
50 "spki",
51 publicKeyBuffer,
52 { name: "RSASSA-PKCS1-v1_5", hash: { name: "SHA-256" } },
53 false,
54 ["verify"]
55);
56
57const isValid = await crypto.subtle.verify(
58 "RSASSA-PKCS1-v1_5",
59 publicKey,
60 signature,
61 requestBodyBuffer
62);
63```
64
65Adjust header name (`coop-signature` vs `Coop-Signature`) and body encoding to match how your server receives the request.