API keys
Create your account, then generate an API key from the dashboard — every request to the API carries it as a bearer token. A key is shown once, at creation, and can be scoped to specific organizations and revoked independently of every other key on the account.
Under the hood a key is exchanged for a short-lived access token the same way a password is: see Bearer tokens below.
Bearer tokens
Authenticate every request with an Authorization: Bearer header. Tokens come from POST /auth/login and expire after one hour — exchange the refresh token for a new one before then rather than logging in again on every request.
Log in
curl -X POST https://api.kovalinq.com/auth/login \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "you@youragency.com",
"password": "your-password"
}'Refreshing an expired token
An access token past its expires_in window is rejected with 401 AUTHENTICATION_FAILED. Exchange the refresh token for a new access token instead of logging in again — the refresh token itself is long-lived and does not rotate on every use.
Refresh
curl -X POST https://api.kovalinq.com/auth/refresh \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "sp_rt_9c4e1b8a2f3d..."
}'Scopes
Every key carries scopes, and a request outside its scopes is refused with 403 INSUFFICIENT_SCOPE. Create narrowly-scoped keys for narrowly-scoped integrations — a key that only ever sends messages should not also be able to register webhooks.
| Scope | Grants |
|---|---|
| organizations:read | List and read organizations |
| organizations:write | Create and update organizations |
| messages:write | Send messages and upload media |
| templates:write | Create and submit templates |
| flows:write | Create and publish flows |
| webhooks:write | Register and delete webhook endpoints |
Webhook secrets
Every webhook endpoint gets its own signing_secret when you register it. Each delivery carries an HMAC-SHA256 signature of the raw request body in the X-SalePilot-Signature header — compute the same HMAC over the body you received and compare it before trusting the payload.
In code
Node.js
const response = await fetch("https://api.kovalinq.com/auth/login", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
"email": "you@youragency.com",
"password": "your-password"
}),
});
const data = await response.json();Python
import json
import requests
body = json.loads('{"email":"you@youragency.com","password":"your-password"}')
response = requests.post(
"https://api.kovalinq.com/auth/login",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json=body,
)
data = response.json()Keeping keys secure
- Never ship a live token in client-side JavaScript, a mobile app binary, or a public repository.
- Store tokens in your server’s secret manager, not in application code or version control.
- Rotate a key immediately if it may have leaked — an old key can be revoked without affecting others.
- Restrict a key to specific organizations when it only needs to act on a subset of your clients — see Organizations.