Ask a person to approve a sign-in
const url = 'https://api.trybage.com/v1/bc-authorize';const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"client_assertion":"eyJhbGciOiJFZERTQSIsInR5cCI6ImNsaWVudC1hc3NlcnRpb24rand0In0...","login_hint":"alex@example.com","client_notification_token":"example","audience":"https://shop.example","scope":"browse cart","binding_message":"Reorder this week\'s groceries","bind_key_proof":"example","platform_attestation":"example"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.trybage.com/v1/bc-authorize \ --header 'Content-Type: application/json' \ --data '{ "client_assertion": "eyJhbGciOiJFZERTQSIsInR5cCI6ImNsaWVudC1hc3NlcnRpb24rand0In0...", "login_hint": "alex@example.com", "client_notification_token": "example", "audience": "https://shop.example", "scope": "browse cart", "binding_message": "Reorder this week'\''s groceries", "bind_key_proof": "example", "platform_attestation": "example" }'Starts a sign-in request. The person gets a push on the Bage iPhone app, or an email with a link, and chooses Allow once, Always or Deny. If they chose Always before for this agent, site and scopes, the request is approved at once.
A website that verified its domain in the console may limit scopes (invalid_scope) and agents (site_refused);
those are checked before anyone is asked.
Request Bodyrequired
Section titled “Request Bodyrequired”object
A one-time JWT signed with the agent’s private key (RFC 7523). See the description at the top.
The person’s email address (they don’t need a Bage account yet), or the account_link this agent got
from an earlier sign-in with them. A link only works for the agent it was given to, and stops working
when the person cuts the agent off (unknown_user_id).
Ping mode only, and then required: a random secret (at least 128 bits) Bage sends back as the bearer token when it calls the agent’s notification endpoint about this request.
The website’s origin, as its /.well-known/agent-login names it.
Space-separated scopes - standard ones (the Scope schema) or the site’s own (custom_scopes in GET /v1/sites). A verified site allows email plus what it turned on.
Shown to the person on the approval screen.
Bind the token to a per-session Ed25519 key instead of the agent’s own (for a browser extension that signs
inside the browser). A JWT signed by that key: header typ: "key-binding+jwt" and jwk (the public key),
claims iss = the client ID, aud = the issuer, exp at most 5 minutes out.
Bind the token to a browser platform’s key, so the platform signs requests. A JWT from the platform, signed
with its registered key: header typ: "platform-key+jwt", claims iss = the platform’s client ID,
sub = this agent’s client ID, aud = the issuer, cnf.jwk = the browser’s public key, exp at most a day
out. The token then names the platform in a nested act.
Responses
Section titled “Responses”The request was created.
object
Seconds until the request expires.
Seconds to wait between polls.
Example
{ "auth_req_id": "req_3f9c2b1a", "expires_in": 300, "interval": 2}invalid_request, invalid_scope, invalid_binding (a bad key proof or platform attestation), unknown_user_id (an account link this agent doesn’t have), or a test person asked by a live agent.
object
Example
{ "error": "authorization_pending"}invalid_client: unknown client, or a bad, expired or reused client assertion.
object
Example
{ "error": "authorization_pending"}site_refused: the website blocked this agent, or only lets in agents it allowed. test_mode: a test agent asked someone outside its team and the test people.
object
Example
{ "error": "authorization_pending"}rate_limited: too many requests, or too many to people who haven’t set up Bage.
object
Example
{ "error": "authorization_pending"}