Skip to main content
For engineers. Covers the settings behind acceptance: the policy your KYA SDK runs on each request, the origins baselayer.js can report from, and browser keys. Every route takes your API key in X-API-Key and acts on that key’s application. To set which audiences your credential check accepts, see Audiences.

The Policy

The policy decides what your KYA SDK recommends for each request. It is a list of steps, such as browse, cart and checkout. Each step names the requests it covers and holds rules tried in order; the first rule that matches decides. Steps are also tried in order, so put the most specific first. A rule matches on transport, kind, trust and minimum_identity_level (L1 when you need to know which platform runs the agent, L2 the same person each time, L3 a verified person or business); a field left out matches anything. Its outcome is allow, challenge, step_up (step up: ask the agent for stronger proof, such as a KYA credential) or block, and step_up and challenge carry a requirement. A step’s enforcement_mode is report_only, where decisions are recorded and never applied, or enforce. detection_fallback is what a step decides on when no detection result is available: local_rules. conversions say which requests count as a sale.

What Step Up Means

Your KYA SDK returns a step_up decision with its requirement, and your server answers the agent. When the requirement is a scope and the agent carries a KYA credential, answer with a 401 and a KYA-Disclosure-Scope header naming the scope. The rule’s scope is a scope from your KYA profile. See Asking for Fields and Accepting Agents. When the requirement is an identity_level, the agent needs a KYA credential that meets it or goes beyond it. For other agents, treat step_up as a block or let them through. Asking a person to verify on the spot is coming soon. Handle challenge the same way: the decision is recorded, and your server decides what the agent gets.

Steps and Matching

A step’s name is one of these, and each name is used at most once: A step’s match says which requests it covers: An empty list matches nothing, so a plain web site leaves mcp_tools and ucp_operations as []. A rule’s minimum_identity_level needs policy schema version 2: a policy that uses it reports minimum_policy_schema_version: 2, and an older SDK runs it report-only. A new application starts on policy version 1, Baselayer’s default, where every step is report_only (watch-only). Your KYA SDK picks up a new version with no deploy; How It Gets Your Rules says when.

Read the Current Policy

Needs the acceptance_policy:read permission.
The response carries an ETag header. Keep it: you send it back to replace the policy. To poll for a change, send it as If-None-Match: the answer is 304 with no body until the policy or your audiences change.
policy_hash is the hash of the policy body. Each decision your SDK reports names the version it ran, so you can always tell which policy made it.

Replace the Policy

Needs the acceptance_policy:update permission. Send the whole policy, exactly as a read returns it under policy, with the ETag you read as If-Match:
policy.json:
The response is the new current version. If someone else replaced the policy after your read, the replace is refused with 412 policy_version_stale and nothing changes: read it again and reapply your change. A request with no If-Match is refused with 428 if_match_required. A policy that is valid but probably not what you meant, such as a rule no request can reach, is stored with warnings that say why.

Earlier Versions

Versions are never changed or deleted. GET /acceptance/policy/versions lists them, newest first, and GET /acceptance/policy/versions/{policy_version_id} returns one exactly as it ran, which is the version a decision’s policy_version_id names.

Allowed Origins

Your application’s allowed origins are the origins baselayer.js may send records from. Each is https:// and a host, such as https://shop.example, or http:// on a loopback host for local testing, such as http://localhost:8080, with no path and no default port. A record from any other origin is refused, and an application with no allowed origins accepts none. Your Baselayer team sets them: send them every origin your pages are served from. Treat browser records as reports, not proof: anyone can copy your browser key and claim an allowed origin.

Browser Keys

A browser key lets baselayer.js send records for your application. It is public: it ships in your page. An application has at most 2 live keys, so you can roll one over without a gap.

Mint a Key

Needs the organizations_apikeys:create permission. label says what the key is for:
browser_key is in this response only. Baselayer cannot show it again, so store it now. Baselayer accepts a new key usually within about 20 seconds.

List and Read Keys

Needs organizations_apikeys:read. GET /acceptance/browser_keys lists every key, live and revoked, newest first, and GET /acceptance/browser_keys/{browser_key_id} returns one. Neither ever shows the key itself, so tell keys apart by label and browser_key_id.

Rotate a Key

POST /acceptance/browser_keys/{browser_key_id}/rotate mints a new key with the same label and needs organizations_apikeys:create. The old key stays live, so deploy the new key to your pages first, then revoke the old one. It answers 409 with type browser_key_limit_reached when there are already 2 live keys (revoke one first), and browser_key_revoked when the key you rotate is revoked (mint a new key instead).

Revoke a Key

POST /acceptance/browser_keys/{browser_key_id}/revoke needs organizations_apikeys:delete. Baselayer stops accepting the key usually within about 20 seconds. Revoking a revoked key changes nothing.