skills/protocolsio-integration/references/authentication.md
Verified 2026-07-23 against the official Developer resources page and API authentication reference.
The official documentation names two bearer-token modes:
| Mode | Officially documented use | Safe default |
|---|---|---|
| Client access token | The Developer resources page says it can read all public data. The API authentication section additionally says it can access the creating user's private content. | Treat it as public-read unless the exact account/endpoint behavior and permissions have been verified. |
| OAuth access token | Public content plus the authorizing user's permitted private content. | Use only for a multi-user application or a user-approved private/write workflow. |
The two official descriptions of client-token private access are not perfectly aligned. Do not use that ambiguity as authorization. Check the returned access flags and the user's intended scope before touching private content.
“Public protocol” describes the resource's visibility; it does not imply that a
REST call is anonymous. The current list/get endpoint sections require
Authorization: Bearer .... The official PDF section documents signed-in and
signed-out rates, so the bundled client allows anonymous access only when
export-pdf --anonymous is explicit.
The bundled scripts read only PROTOCOLS_IO_ACCESS_TOKEN, the bearer token
used by the read helper. They do not read OAuth client credentials or refresh
tokens. A separately reviewed confidential application should keep those
credentials in its own secret-manager scope and perform OAuth exchange there.
Never:
.env files;Configure secrets through the execution host's credential manager. Validate presence locally:
python3 -B scripts/validate_auth_config.py --require read
The validator reads only the named access token, reports a boolean, performs
no network access, and never loads .env.
The current official flow documents:
https://www.protocols.io/developers.https://www.protocols.io/api/v3/oauth/authorize.client_id, redirect_url, response_type=code,
scope=readwrite, and a high-entropy, single-use state.state before accepting the authorization code.POST https://www.protocols.io/api/v3/oauth/token using
grant_type=authorization_code, client_id, client_secret, and code.grant_type=refresh_token,
client_id, client_secret, and refresh_token.Use the documented parameter name redirect_url; do not silently substitute
redirect_uri. The token response documents access_token, token_type,
expires_in, scope, refresh_token, refresh_expires_in, and user.
The reference's example scope is readwrite. No finer REST scope list was
found in the official materials reviewed. Therefore:
readwrite only when a reviewed write workflow genuinely needs it;Do not perform OAuth token exchange in a browser-only client or general agent transcript. Keep the client secret and token endpoint in a confidential server-side component with redacted observability.
The official authentication page says an OAuth access token resets after about
one year, returns an expires_in value, and warns one month before expiry with
warning_code: 1. It documents API status_code: 1219 and “token is expired”
after expiry. Treat the response fields—not a hardcoded calendar interval—as
authoritative.
On refresh, the documentation says old tokens stop working. Store the newly returned access and refresh credentials atomically, then revoke or discard the old pair. Never log the response body.
Endpoint examples use the standard Authorization: Bearer ... header. The
authentication introduction contains a label typo (“Authentication”), so use
the endpoint contract and standard header name.
Build the header only inside the HTTP transport immediately before a validated request. Redact it from plans, tracing, error reports, and mocks. Disable redirects; do not assume a same-site redirect is safe for a bearer credential.
Before any authenticated operation:
readwrite, authorize/token paths,
response fields, lifetime/refresh behavior.