Authentication and API keys
How to create an Avensa API key, the scopes available, and how to send it on every REST API v1 request.
/api/v1/* requests accept a Bearer credential in the Authorization header. Three credential types are accepted by the middleware (apps/web/proxy.ts):
- API key — starts with
pk_live_orpk_test_. This is what you'll use for almost every integration. - OAuth 2.0 access token — starts with
oat_, issued through/api/v1/oauth/authorizeand/api/v1/oauth/token(Authorization Code flow with PKCE). Used by the MCP server and by third-party apps that go through OAuth consent instead of a static key. - Supabase user session JWT — used internally by the Avensa mobile app only.
Creating an API key
- Go to Settings → API in the account you want to integrate with (requires the
settings.managepermission — API keys mint account-wide read/write credentials, so only owners/admins can create them). - Click Create API key, give it a name, and select the scopes it needs (see below). You can optionally set an expiry date and an IP allowlist.
- The full key (
pk_live_<prefix>.<secret>) is shown once. Copy it immediately — Avensa only stores a hash of the secret, so it cannot be shown again. If you lose it, revoke the key and create a new one.
Keys can be rotated (a new secret is issued for the same key record) with an optional grace period during which the old secret keeps working, so a live integration can swap credentials without downtime. They can also be revoked immediately.
Sending the key
Every /api/v1/* request:
GET /api/v1/properties HTTP/1.1 Host: api.avensa.bg Authorization: Bearer pk_live_xxxxxxxxxx.yyyyyyyyyyyy Content-Type: application/json
curl https://api.avensa.bg/api/v1/properties \ -H "Authorization: Bearer pk_live_xxxxxxxxxx.yyyyyyyyyyyy" \ -H "Content-Type: application/json"
The middleware resolves the key, checks it isn't expired/revoked, enforces the IP allowlist (if set), verifies the request's scope requirement against the key's granted scopes, and attaches the account context — you never send an account ID separately.
Key format
pk_test_*— test-environment keys. Use these while building an integration.pk_live_*— production keys.
Scopes
A key only grants the scopes it was created with. Common scopes:
| Scope | Grants |
|---|---|
properties:read | List/get properties |
properties:write | Create/update/delete properties |
units:read | List/get property units |
units:write | Create/update units |
contacts:read | List/get contacts |
contacts:write | Create/update/delete contacts |
deals:read | List/get deals |
deals:write | Create/update deals |
tasks:read / tasks:write | Tasks |
documents:read / documents:write | Documents |
calendar:read / calendar:write | Calendar events |
viewings:read / viewings:write | Viewings |
notes:read | Notes/activities |
dictionaries:read | Property type/feature dictionaries |
exports:read / exports:write | Data exports |
webhooks:manage | Register/manage webhooks |
automations:read | View automation rules |
automations:manage | Create and toggle automation rules |
automations:trigger | Trigger a webhook-type automation rule with an API key |
These are also the scopes offered as OAuth 2.0 scopes for the Authorization Code flow (see the MCP page for the OAuth flow itself).
OAuth 2.0 (for MCP and third-party apps)
Authorize: GET /api/v1/oauth/authorize Token: POST /api/v1/oauth/token Revoke: POST /api/v1/oauth/revoke Userinfo: GET /api/v1/oauth/userinfo
Dynamic client registration is available at POST /api/v1/oauth/register. The token endpoint supports the standard Authorization Code grant with PKCE and issues short-lived access tokens plus a refresh token. See MCP server for the client-facing setup flow.
Unauthenticated / invalid credential response
{
"error": "Missing authentication token",
"status": 401,
"timestamp": "2026-09-02T18:00:00.000Z",
"request_id": "req_abc123",
"message": "API key or OAuth token required. Include Bearer token in Authorization header."
}