CasePrimus.aiby Attestr
Documentation menu
API guide

API authentication and request signing

Every call to the CasePrimus.ai API is authenticated with an API key. For integrations that need more, you can also have requests signed with your own key pair, and payloads encrypted.

API keys

An API key is a secret that identifies your integration. Create and manage keys from the Developer console in your CasePrimus.ai dashboard. A key's secret is shown once, when you create it, so store it somewhere safe, such as your secrets manager. Never put it in client-side code or a public repository.

Create a separate key for each system that connects. If one is exposed or no longer needed, you can switch off just that key without touching the others.

Send your key

Put the key in the X-CasePrimus-Api-Key header. All requests go to https://api.caseprimus.ai/api/caseprimus/v1 over HTTPS.

Authenticated request
curl "https://api.caseprimus.ai/api/caseprimus/v1/watchlist/entities/search" \
  -X POST \
  -H "X-CasePrimus-Api-Key: $CASEPRIMUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "$skip": 0, "$limit": 10 }'

Signed requests (optional)

For integrations that need to prove each request came from you and was not altered, you can turn on request signing for a key. You give CasePrimus.ai your public key; you keep the private key. Each request then carries two extra headers: X-Signature and X-Signature-Timestamp.

  • Build the string METHOD\nPATH\nTIMESTAMP\nBODY: the HTTP method, the full request path, the timestamp, and the exact raw body, separated by newlines.
  • Sign it with your private key using RSA with SHA-256, and send the result base64-encoded in X-Signature.
  • Send the timestamp in milliseconds since the Unix epoch. Requests older than five minutes are rejected, which protects against replay.
Sign a request
const crypto = require("crypto");

const method = "POST";
const path = "/api/caseprimus/v1/watchlist/cases";
const body = JSON.stringify({ caseIdentifier: { cnr: "DLHC01-004821-2026" } });
const timestamp = Date.now().toString();

// Sign EXACTLY this string: method, path, timestamp and the raw body bytes,
// joined by newlines, with your own RSA private key.
const payload = `${method}\n${path}\n${timestamp}\n${body}`;
const signature = crypto
  .sign("RSA-SHA256", Buffer.from(payload), YOUR_PRIVATE_KEY_PEM)
  .toString("base64");

const response = await fetch(`https://api.caseprimus.ai${path}`, {
  method,
  headers: {
    "Content-Type": "application/json",
    "X-CasePrimus-Api-Key": YOUR_API_KEY_SECRET,
    "X-Signature": signature,
    "X-Signature-Timestamp": timestamp,
  },
  body,
});

Sign the exact bytes you send

The body you sign must be byte-for-byte the body you send. Serialize it once, sign that string, and send that same string.

Encrypted payloads (optional)

On top of HTTPS, a key can also be set up so that request and response bodies are encrypted, using a hybrid scheme that combines RSA and AES. Only the holder of your private key can read the responses. This is off by default and is turned on per key in the Developer console. The same option exists for webhook deliveries.

Permissions

Each endpoint lists the permission it needs, such as watchlist.write or case.read. A call without the right permission returns 403. Your plan also decides which products you can call, for example Watchlist, Live Case Lookup or Historical Search; calling one your plan does not include returns 403 with the code PRODUCT_NOT_IN_PLAN, and nothing is charged. See Rate limits & errors.

Frequently asked questions

How do I authenticate with the CasePrimus.ai API?

Create an API key in the Developer console of your CasePrimus.ai dashboard and send it in the X-CasePrimus-Api-Key header of every request. No other login or token exchange is needed.

Do I have to sign my requests?

No. Request signing is an optional extra layer you can turn on per API key, by giving CasePrimus.ai your public key. When it is on, every request must carry a valid signature and a timestamp no older than five minutes.

Can I use separate keys for separate systems?

Yes, and it is recommended. Keys are created per integration, so a CRM sync and an internal alerting pipeline can each have their own key and be revoked independently.

What does a 401 response mean?

The key is missing, invalid or inactive, or the request was signed incorrectly or too long ago. Check the header, that the key is active, and, if signing is on, the signature and timestamp.

Last updated 14 October 2026