curl --request POST \
--url https://app.sideshift.app/api/oauth/v1/token \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=authorization_code \
--data code=ac_4f2b... \
--data redirect_uri=https://acme.example.com/oauth/callback \
--data code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk \
--data client_id=oauthc_8f1c2e...{
"access_token": "eyJhbGciOiJFUzI1NiIsImtpZCI6Ii4uLiIsInR5cCI6ImF0K2p3dCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "campaigns:read contracts:read",
"refresh_token": "rt_9f8e..."
}{
"error": "invalid_grant",
"error_description": "Authorization code is invalid or expired"
}{
"error": "invalid_client",
"error_description": "Client authentication failed"
}{
"error": "temporarily_unavailable",
"error_description": "Rate limit exceeded"
}Token endpoint
RFC 6749 token endpoint. Supports authorization_code (PKCE verifier required), refresh_token (rotation + reuse detection), and client_credentials for dashboard-authorized company apps. Public registration and human consent do not authorize machine access. New machine apps are capped by their creator’s live company permissions. Confidential clients authenticate with HTTP Basic or client_secret_post. Access tokens are RFC 9068 at+jwt, 1h TTL, audience-bound to the resource indicator. Subscription eligibility is enforced when the issued token calls a protected resource. Responses are no-store.
curl --request POST \
--url https://app.sideshift.app/api/oauth/v1/token \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=authorization_code \
--data code=ac_4f2b... \
--data redirect_uri=https://acme.example.com/oauth/callback \
--data code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk \
--data client_id=oauthc_8f1c2e...{
"access_token": "eyJhbGciOiJFUzI1NiIsImtpZCI6Ii4uLiIsInR5cCI6ImF0K2p3dCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "campaigns:read contracts:read",
"refresh_token": "rt_9f8e..."
}{
"error": "invalid_grant",
"error_description": "Authorization code is invalid or expired"
}{
"error": "invalid_client",
"error_description": "Client authentication failed"
}{
"error": "temporarily_unavailable",
"error_description": "Rate limit exceeded"
}Authorizations
Confidential-client authentication at the token/revoke endpoints — HTTP Basic client_id:client_secret (or the equivalent client_secret_post body params). Public (PKCE) clients send only client_id and use no scheme.
Body
Form-encoded token request. Fields apply per grant_type: authorization_code uses code + redirect_uri + code_verifier; refresh_token uses refresh_token; client_credentials uses scope. Public clients also send client_id.
authorization_code, refresh_token, client_credentials PKCE verifier (authorization_code grant).
RFC 8707 resource indicator.
client_secret_post auth (alternative to HTTP Basic).
Response
Token issued.
RFC 6749 / 9068 token response.
RFC 9068 at+jwt, ES256/RS256, 1h TTL.
Bearer Seconds until expiry (3600).
Present when the client registered the refresh_token grant. The optional OIDC offline_access scope is not required.