Authentication
All Ariftly API requests use Bearer token authentication. This page covers API key creation, scopes, rate limits, webhook signature verification, and credential security best practices.
Get your API key
- Log in to app.ariftly.io
- Go to Settings → API Keys
- Click Create API Key
- Select the scopes you need (see below)
- Give the key a descriptive name (e.g., "CI Pipeline Key" or "Dashboard Integration")
- Copy the key — it is shown only once
Store your key in an environment variable — never hardcode it in source code:
export ARIFTLY_API_KEY=ak_live_...
For CI/CD pipelines, store it as an encrypted secret in your CI provider (GitHub Actions Secrets, GitLab CI/CD Variables, etc.).
Using the API key
Include it in the Authorization header on every request:
curl https://api.ariftly.io/v1/tasks \
-H "Authorization: Bearer $ARIFTLY_API_KEY"
All API calls must be made over HTTPS. HTTP requests are rejected with a 400 Bad Request.
Key scopes
When creating a key, select the minimum scopes required for the use case. Principle of least privilege — a key used only to trigger tasks does not need approvals:write or agents:admin.
| Scope | Access |
|---|---|
tasks:write | Create tasks and cancel running tasks |
tasks:read | Read tasks, poll status, and fetch artifacts |
approvals:write | Resolve approvals (approve or deny) |
approvals:read | Read pending and resolved approvals |
events:read | Read the event log and stream |
agents:admin | Register new agents, update agent config, delete agents |
webhooks:write | Create, update, and delete webhook subscriptions |
integrations:read | Read integration connection status |
integrations:write | Connect and configure integrations |
A key with no scopes is valid but useless — all requests return 403 Forbidden.
Environment-specific keys
Create separate keys for each environment:
- Production key —
ak_live_...— restricted scopes, rotated quarterly - Staging key —
ak_test_...— full scopes for development - CI key —
ak_live_...— onlytasks:writeandtasks:read
Test keys (ak_test_...) interact with a sandboxed environment and do not trigger real agent tasks, send real emails, or charge against your plan.
Rotating keys
Keys can be rotated in Settings → API Keys. When you create a replacement key:
- The old key continues working for 24 hours — use this window to update all deployments
- After 24 hours, the old key is automatically revoked
- You can revoke the old key immediately if you have confirmed all deployments use the new key
If a key is compromised, click Revoke Immediately — this takes effect within 30 seconds across all regions.
Rate limits
Rate limits apply per API key:
| Plan | Requests per minute |
|---|---|
| Free | 60 |
| Starter | 300 |
| Pro | 1,000 |
| Enterprise | Custom (contact us) |
Rate limit headers are included on every response:
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 247
X-RateLimit-Reset: 1745233260
X-RateLimit-Reset is a Unix timestamp indicating when the current window resets.
When you exceed the rate limit, the API returns 429 Too Many Requests with a Retry-After header indicating how many seconds to wait before retrying.
Tenant isolation
API keys are scoped to a single tenant. All data returned by the API (tasks, artifacts, approvals, agents) belongs exclusively to that tenant. There is no mechanism to read another tenant's data — the API enforces tenant isolation at every layer.
Webhook signature verification
When you register a webhook, Ariftly includes an X-Ariftly-Signature header on every delivery. Verify this header before processing the payload to ensure the request is genuinely from Ariftly and has not been tampered with.
Verifying in Node.js:
import crypto from 'crypto';
function verifyWebhookSignature(
payload: string,
signature: string,
secret: string
): boolean {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}
// In your webhook handler:
app.post('/webhooks/ariftly', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-ariftly-signature'] as string;
const secret = process.env.ARIFTLY_WEBHOOK_SECRET!;
if (!verifyWebhookSignature(req.body.toString(), sig, secret)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body.toString());
// process event...
res.status(200).send('ok');
});
Verifying in Python:
import hmac, hashlib
def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(
secret.encode(), payload, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
Always use a constant-time comparison function (crypto.timingSafeEqual in Node.js, hmac.compare_digest in Python) to prevent timing attacks.
BYOK (Bring Your Own Key)
Your AI provider keys (Anthropic, OpenAI, etc.) are stored separately in Settings → AI Keys. Ariftly never bills for AI usage — your provider keys are used directly through the Vercel AI Gateway. This means:
- You see AI costs directly in your provider dashboard
- You retain full control over your AI spend and usage policies
- You can rotate provider keys independently of your Ariftly API keys
- Provider keys are stored encrypted at rest and never exposed in API responses
To add a provider key: Settings → AI Keys → Add Key → Select Provider.
Error responses
All authentication errors return standard HTTP status codes:
| Status | Code | Meaning |
|---|---|---|
401 | UNAUTHORIZED | Missing or malformed Authorization header |
401 | TOKEN_EXPIRED | API key has been revoked or expired |
403 | INSUFFICIENT_SCOPE | API key lacks the required scope for this operation |
429 | RATE_LIMITED | Too many requests — check Retry-After header |
Error response body:
{
"error": {
"code": "INSUFFICIENT_SCOPE",
"message": "This operation requires the 'approvals:write' scope",
"required_scope": "approvals:write"
}
}
Security best practices
- Never commit API keys to source control — use environment variables or secret management tools (AWS Secrets Manager, HashiCorp Vault, etc.)
- Use the narrowest scope that satisfies the use case
- Rotate keys quarterly, or immediately after any team member with key access leaves
- Create separate keys per service — don't share one key across multiple CI pipelines or integrations
- Monitor the Settings → API Keys → Last Used column — keys with no recent activity should be revoked
What's next
- Tasks API — start triggering agent tasks
- RAP v1 Protocol — HMAC signing for agent-to-core communication
- Webhooks — event subscriptions and delivery guarantees