Except for internal /in/v1 APIs, every API requires an Authorization: Bearer <token> HTTP header.
curl -H "Authorization: Bearer <token>" \
https://<your-instance>/api/bkn-backend/v1/knowledge-networks
For deployments that use self-signed certificates, append -k (--insecure) to the curl and openbkn commands on this page. Skipping TLS verification is suitable only for development environments.
Choose one of these token acquisition methods:
| Method | Use case | Coverage |
|---|---|---|
| CLI login | Personal or interactive use | All service APIs |
AppKey (bak_) | Scripts and automation | Context Loader only (retrieval and MCP, read-only) |
| Device authorization flow | Applications acting on behalf of users | All service APIs |
BKN management REST APIs under /api/bkn-backend/v1 require an OAuth access token, including read-only requests such as GET /api/bkn-backend/v1/knowledge-networks. AppKeys are not supported by these APIs. A shared Bearer header format does not make the two credential types interchangeable.
Sign in once with the openbkn CLI from bkn-sdk. Subsequent commands send and refresh the token automatically. Login uses the OAuth2 device authorization flow (RFC 8628).
# Browser login: prints a URL and user code for browser confirmation
# Add -k for a deployment with a self-signed certificate
openbkn auth login https://<your-instance>
# Headless or CI login: the CLI completes login and consent with credentials
openbkn auth login https://<your-instance> -u <account> -p <password> -k
Use the token subcommand when another tool or curl needs the raw token. An expired token is refreshed automatically.
openbkn auth token # Print the current access token
openbkn auth status # Show login status and current platform
openbkn auth whoami # Show the current identity
# Use the token directly with curl
curl -H "Authorization: Bearer $(openbkn auth token)" \
https://<your-instance>/api/bkn-backend/v1/knowledge-networks
/api/agent-retrieval/.... It supports read-only operations only. Write APIs intentionally reject AppKeys. Requests run as the issuer and have the same read scope as the issuer's OAuth token. Use an OAuth token for writes or other services.The read-only scope above is the existing authentication-guide boundary. Execution-operation documentation also advertises AppKeys; that discrepancy needs a separate support-boundary decision. Until it is resolved, use OAuth for execution operations rather than treating MCP initialization success as evidence that all tools are supported.
Safe reporting active: true establishes that the key is valid and identifies its owner. Context Loader routes bak_ credentials to Safe for verification, whereas BKN management APIs validate OAuth tokens through Hydra. An active AppKey sent to a BKN management API can therefore return 401 / Public.Unauthorized before resource authorization. Changing the owner's roles or knowledge-network grants does not address this credential mismatch. Use the OAuth example above for management requests, including CLI and integration calls. Successful MCP initialize only establishes initialization; business tools still require their own authorization.
Create and manage an AppKey in the BKN Studio profile page or issue it through the API with an authenticated OAuth token. An AppKey cannot issue another AppKey. name is required; omitting expires_at uses a one-year lifetime.
# Issue a key with an authenticated OAuth token
curl -X POST https://<your-instance>/api/safe/v1/me/api-keys \
-H "Authorization: Bearer $(openbkn auth token)" \
-H "Content-Type: application/json" \
-d '{"name":"my-key","expires_at":"2027-01-01T00:00:00Z"}'
# 201 response. The plaintext key appears only once; store it securely
# {"id":"...","key_id":"2882bb603277","name":"my-key",
# "key":"bak_2882bb603277_BSxTZHTBiJXk4QoUBc0u17zSWua",
# "masked":"bak_2882****SWua","expires_at":"...","enabled":true}
# Use the Bearer header with a Context Loader API. kn_id is required and can
# alternatively be sent in X-Kn-ID
curl -X POST https://<your-instance>/api/agent-retrieval/v1/kn/search_schema \
-H "Authorization: Bearer bak_2882bb603277_BSxTZHTBiJXk4QoUBc0u17zSWua" \
-H "Content-Type: application/json" \
-d '{"query":"customer","kn_id":"<knowledge-network-id>"}'
CLI equivalent: openbkn appkey create --name my-key. Use it with openbkn --token bak_... context .... Management APIs: GET /api/safe/v1/me/api-keys lists keys, DELETE /api/safe/v1/me/api-keys/{id} revokes one, and POST /api/safe/v1/me/api-keys/{id}/regenerate rotates one.
import requests
BASE = "https://<your-instance>"
oauth_token = "<OAuth access token>" # For example, openbkn auth token output
# Issue a key. The plaintext key appears only once; store it securely
resp = requests.post(
f"{BASE}/api/safe/v1/me/api-keys",
headers={"Authorization": f"Bearer {oauth_token}"},
json={"name": "my-key"}, # Optional expires_at; defaults to one year
)
app_key = resp.json()["key"] # bak_...
# Use a read-only Context Loader retrieval API. kn_id is required and can also
# be sent in X-Kn-ID
r = requests.post(
f"{BASE}/api/agent-retrieval/v1/kn/search_schema",
headers={"Authorization": f"Bearer {app_key}"},
json={"query": "customer", "kn_id": "<knowledge-network-id>"},
)
For self-signed certificates, add verify=False to every request or configure it once on a requests.Session().
An application can call platform APIs without registering a client or involving an administrator. Every deployment includes the public openbkn-sdk client for the OAuth2 device authorization flow (RFC 8628). The application asks the user to sign in once in a browser, receives a token with that user's permissions, and then uses the refresh token for long-running access.
curl -X POST https://<your-instance>/oauth2/device/auth \
-d "client_id=openbkn-sdk" -d "scope=openid offline"
# -> {"device_code":"ory_dc_...","user_code":"EKgw7AQa",
# "verification_uri_complete":"https://<your-instance>/oauth2/device/verify?user_code=EKgw7AQa",
# "expires_in":600,"interval":5}
Present verification_uri_complete as a link or QR code. The user opens it, confirms the device code, signs in, and grants consent.
curl -X POST https://<your-instance>/oauth2/token \
-d "grant_type=urn:ietf:params:oauth:grant-type:device_code" \
-d "device_code=ory_dc_..." \
-d "client_id=openbkn-sdk"
# Before login completes: {"error":"authorization_pending"}. Retry after the
# number of seconds in interval
# After completion -> {"access_token":"...","refresh_token":"...","expires_in":3600,
# "scope":"openid offline","token_type":"bearer"}
# Call any service API with the signed-in user's permissions
curl -H "Authorization: Bearer <access_token>" \
https://<your-instance>/api/bkn-backend/v1/knowledge-networks
# The access token lasts one hour. Refresh it without another login.
# Every refresh rotates refresh_token; always store the latest value
curl -X POST https://<your-instance>/oauth2/token \
-d "grant_type=refresh_token" \
-d "refresh_token=<refresh_token>" \
-d "client_id=openbkn-sdk"
import time
import requests
BASE = "https://<your-instance>"
CLIENT_ID = "openbkn-sdk"
s = requests.Session()
# s.verify = False # Enable for a deployment with a self-signed certificate
# 1. Start device authorization
da = s.post(f"{BASE}/oauth2/device/auth",
data={"client_id": CLIENT_ID, "scope": "openid offline"}).json()
print("Open this URL in a browser and sign in:", da["verification_uri_complete"])
# 2. Poll until the user completes login
while True:
time.sleep(da.get("interval", 5))
r = s.post(f"{BASE}/oauth2/token", data={
"grant_type": "urn:ietf:params:oauth:grant-type:device_code",
"device_code": da["device_code"],
"client_id": CLIENT_ID,
}).json()
if "access_token" in r:
tokens = r
break
if r.get("error") not in ("authorization_pending", "slow_down"):
raise RuntimeError(r)
# 3. Call an API with the signed-in user's permissions
kns = s.get(f"{BASE}/api/bkn-backend/v1/knowledge-networks",
headers={"Authorization": f"Bearer {tokens['access_token']}"}).json()
# 4. Refresh after the one-hour access-token lifetime without another login.
# Refreshing rotates refresh_token, so overwrite the stored value
tokens = s.post(f"{BASE}/oauth2/token", data={
"grant_type": "refresh_token",
"refresh_token": tokens["refresh_token"],
"client_id": CLIENT_ID,
}).json()
openbkn-sdk is a public client with no secret; PKCE and the device authorization flow provide its security. Any application can use it directly. A headless script that submits the login or consent pages must URL-decode the percent-encoded *_challenge query parameter before submitting the form to avoid double encoding.
The interactive login in Method 1 uses the Method 3 device flow internally; the CLI automates it.