Skip to content

Authentication

All API requests must be authenticated. Angelcam supports two methods:

  • OAuth2 — for integrations and commercial use
  • Personal Access Token — for personal/development use only

OAuth2 produces a short-lived Bearer token. Pass it with every request:

Terminal window
curl -H "Authorization: Bearer ACCESS_TOKEN" \
-X GET "https://api.angelcam.com/v1/cameras/?limit=5"

Tokens expire after 10 hours and must be refreshed using a refresh token. Each refresh returns the same refresh token; it expires if it is not used for 30 days.

Create your OAuth2 app in the MyAngelcam Dashboard to get your Client ID (and, for confidential applications, a Client Secret).

When you create an application, choose its type based on where it runs. You cannot change the type later.

ConfidentialPublic
Runs onA server you control — a web backend or an internal serviceThe user’s device — a mobile, desktop or single-page app
Client secretYes, shown once when you create the applicationNo — the app cannot keep a secret private
Sends to /oauth/token/client_id + client_secret + code_verifierclient_id + code_verifier

Both types use the authorization code flow with PKCE.

Important: Never put a client secret in a mobile, desktop or browser app — anyone can extract it. Use a public application instead.

The user authenticates through Angelcam’s login page — similar to “Sign in with Google” — and your app receives an authorization code that it exchanges for tokens.

PKCE (Proof Key for Code Exchange) ties the authorization code to the app that requested it, so an intercepted code cannot be used by anyone else. PKCE is required for both public and confidential applications.

Authorization code grant sequence diagram

Step 1 — generate a code verifier and its code challenge.

The code_verifier is a random string of 43–128 characters (A-Z, a-z, 0-9, -, ., _, ~). The code_challenge is its SHA-256 hash, base64url-encoded without padding. Generate a new pair for every authorization request and keep the verifier until Step 3.

function base64UrlEncode(bytes) {
return btoa(String.fromCharCode(...bytes))
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}
const codeVerifier = base64UrlEncode(crypto.getRandomValues(new Uint8Array(32)));
const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(codeVerifier));
const codeChallenge = base64UrlEncode(new Uint8Array(digest));

Or in a shell:

Terminal window
CODE_VERIFIER=$(openssl rand -base64 32 | tr '+/' '-_' | tr -d '=')
CODE_CHALLENGE=$(printf '%s' "$CODE_VERIFIER" | openssl dgst -sha256 -binary | base64 | tr '+/' '-_' | tr -d '=')

Step 2 — redirect the user to:

GET https://my.angelcam.com/oauth/authorize/
?response_type=code
&client_id=CLIENT_ID
&redirect_uri=https://yourapp.com/callback
&scope=user_access
&state=CSRF_TOKEN
&code_challenge=CODE_CHALLENGE
&code_challenge_method=S256

Use a random state and check that it matches when the user comes back. Requests without code_challenge are rejected with error=invalid_request.

The user will be asked to approve your app:

OAuth approval screen

Step 3 — Angelcam redirects back to your redirect_uri with code and state. Exchange the code together with the code_verifier from Step 1.

Confidential application (from your server):

Terminal window
curl -X POST https://my.angelcam.com/oauth/token/ \
-d grant_type=authorization_code \
-d client_id=CLIENT_ID \
-d client_secret=CLIENT_SECRET \
-d code=AUTH_CODE \
-d redirect_uri=https://yourapp.com/callback \
-d code_verifier=CODE_VERIFIER

Public application (from the user’s device — no client secret):

Terminal window
curl -X POST https://my.angelcam.com/oauth/token/ \
-d grant_type=authorization_code \
-d client_id=CLIENT_ID \
-d code=AUTH_CODE \
-d redirect_uri=https://yourapp.com/callback \
-d code_verifier=CODE_VERIFIER

The /oauth/ endpoints allow cross-origin requests, so a single-page app can call them directly from the browser.

Response:

{
"access_token": "...",
"refresh_token": "...",
"token_type": "Bearer",
"expires_in": 36000,
"scope": "user_access"
}

Note: Applications created before PKCE was introduced keep working without code_challenge and code_verifier. We recommend adding PKCE to them as well.

When a request returns 401 Unauthorized, refresh the access token. Confidential applications must also send their client_secret:

Terminal window
curl -X POST https://my.angelcam.com/oauth/token/ \
-d grant_type=refresh_token \
-d client_id=CLIENT_ID \
-d client_secret=CLIENT_SECRET \
-d refresh_token=REFRESH_TOKEN

Public applications send only client_id and refresh_token.

To revoke a token, use the oauth/revoke-token/ endpoint.

Legacy: New applications use the authorization code flow with PKCE. The password grant is only available to applications that already have it enabled.

Your app collects the user’s credentials and exchanges them directly for a token.

Password grant type sequence diagram

Important: Never store the user’s password. For “remember me”, store the refresh token instead.

Terminal window
curl -X POST https://my.angelcam.com/oauth/token/ \
-d "client_id=CLIENT_ID&scope=user_access&grant_type=password&username=user%40example.com&password=PASSWORD"

Confidential applications must also send client_secret.

The response has the same format as in the authorization code flow.

For personal use only. No expiration, but can be revoked manually.

Obtain your token in the MyAngelcam Dashboard.

Terminal window
curl -H "Authorization: PersonalAccessToken YOUR_TOKEN" \
-X GET "https://api.angelcam.com/v1/me/"