# API keys and OAuth sign-in

API keys are for your own software. OAuth 2.1 is for apps that other Julius Answer customers connect, and it's how Claude, ChatGPT and other MCP clients sign in.

Every request to the Julius Answer API or MCP server carries a bearer token: an API key (jak_…) made in the console, an OAuth access token (jat_…) given to a connected app, or a partner key (jap_…) for agencies. Each one acts as a person in a workspace, with that person's role lowered to the access it was given: read, write or admin.

## Access levels

Scopes and what they allow
| Scope | Allows | Acts as |
|---|---|---|
| read | Every list and detail: calls, transcripts, contacts, bookings, the to-do list, the team and the setup | A team member (viewer) |
| write | Also bookings, to-dos, call-backs, notes and sales pitches | An operator |
| admin | Also the receptionist's setup, team, numbers and connections | The person's own role (owner or admin) |

A key or app never does more than the person's own role allows. Billing, logins and team accounts, keys and connected apps, and deleting the workspace are never reachable with any token.

## API keys
- **Made in the console** by owners and admins: Settings, API & AI apps, API keys. Up to 25 per workspace.
- **Shown once.** Julius Answer keeps a fingerprint and the last four characters, so you can tell keys apart.
- **Expiry:** never, or after 30, 90 or 365 days. An expired key gets 401.
- **Revoke** one in the console and it stops working at once. The list shows when each key was last used.
- **Send it** as Authorization: Bearer jak_…. Keys work only with /api/v1 and /api/mcp: never with the console's own pages.

## OAuth 2.1 for apps

Build an integration that any Julius Answer customer can connect. MCP clients do all of this by themselves; you need it only for your own app.

OAuth endpoints
| What | Address |
|---|---|
| Authorization server metadata (RFC 8414) | https://app.julius.dealsflow.ai/.well-known/oauth-authorization-server |
| Protected resource metadata (RFC 9728) | /.well-known/oauth-protected-resource/api/mcp and /.well-known/oauth-protected-resource/api/v1 |
| Authorization (the sign-in screen) | https://app.julius.dealsflow.ai/oauth/authorize |
| Token | https://app.julius.dealsflow.ai/api/oauth/token |
| Dynamic client registration (RFC 7591) | https://app.julius.dealsflow.ai/api/oauth/register |
| Revocation (RFC 7009) | https://app.julius.dealsflow.ai/api/oauth/revoke |

## Registering your app

Either register once with dynamic client registration: curl -X POST https://app.julius.dealsflow.ai/api/oauth/register \ -H "Content-Type: application/json" \ -d '{"client_name": "Acme Field Service", "redirect_uris": ["https://acme.example/julius/callback"], "token_endpoint_auth_method": "client_secret_post"}'

The answer has your client_id (and a client_secret for confidential clients; public clients use "none" and PKCE alone). Or use a **client ID metadata document**: make your client_id an https address that serves your app's metadata as JSON (client_id, client_name, redirect_uris). It's fetched when someone opens the sign-in screen (up to 20 KB, cached for a day).
- **Redirect addresses** must match exactly. Use https; plain http only for localhost, 127.0.0.1 or [::1] (any port, for desktop apps). Native app schemes are allowed. No fragments, no user@ parts and no encoded hosts.
- **Unused registrations** that nobody connected are removed after a week.

## The flow
1. Make a PKCE verifier and its S256 challenge, then send the person to: https://app.julius.dealsflow.ai/oauth/authorize?response_type=code &client_id=YOUR_CLIENT_ID&redirect_uri=https%3A%2F%2Facme.example%2Fjulius%2Fcallback &scope=read%20write&state=RANDOM&code_challenge=CHALLENGE&code_challenge_method=S256 &resource=https%3A%2F%2Fapp.julius.dealsflow.ai%2Fapi%2Fv1
1. They sign in, pick the workspace and the access, and press Allow. Your redirect address gets code, your state and iss (check it is https://app.julius.dealsflow.ai). If they decline, you get error=access_denied.
1. Exchange the code within 10 minutes: curl -X POST https://app.julius.dealsflow.ai/api/oauth/token \ -d grant_type=authorization_code -d code=CODE -d code_verifier=VERIFIER \ -d redirect_uri=https://acme.example/julius/callback -d client_id=YOUR_CLIENT_ID \ -d client_secret=YOUR_SECRET {"access_token": "jat_…", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "jar_…", "scope": "read write"}
1. Call the API with Authorization: Bearer jat_…. Refresh with grant_type=refresh_token before the hour is up.

- **Lifetimes:** codes 10 minutes and single use; access tokens 1 hour; refresh tokens 60 days.
- **Rotation:** every refresh returns a new refresh token. Using an old refresh token (or a code twice) ends the whole connection, so a stolen copy is useless.
- **Resource indicators (RFC 8707):** a token issued for /api/mcp or /api/v1 works there; a token for another service is refused.
- **Bad links never redirect:** an unknown app, an unregistered redirect address or a missing PKCE challenge is explained on the sign-in screen instead.
- **The person stays in charge:** your app appears in their console with a Disconnect button, and changes it makes are listed in their activity log with its name.

## Frequently asked questions

### How are keys and tokens stored?

Only as SHA-256 fingerprints. A key is shown once when it's made; nobody at Julius Answer can show it again.

### What happens when someone leaves the workspace?

Their keys and app connections are deleted with their place on the team, so they stop working at once. A password reset also ends every key and app connection of that person.

### Can my app ask for less access than full?

Yes. Ask for the scopes you need (read, write or admin). The person can also give your app less than it asks for; the token response's scope says what was given.

### Do you support client credentials or API keys for third-party apps?

No. Apps that act for other customers use the authorization code flow with PKCE, so each business signs in and chooses the access itself.

---
Source: https://julius.dealsflow.ai/docs/authentication/
Updated: 2026-10-20
