KEYRA Developer Documentation
Integrate hardware-rooted human authorization into your application. KEYRA issues cryptographic challenges, verifies attestation on-device, and returns signed proof that a human approved an action.
Introduction
Hardware-rooted human authorization for apps, AI agents, and high-trust workflows.
- A KEYRA developer account (sandbox available at launch)
- KEYRA ONE device or simulator for local testing
- HTTPS endpoint for webhook delivery
Getting started
Install an SDK, configure secrets, and issue your first challenge.
Install SDK
npm install @keyra/sdkimport { Keyra } from "@keyra/sdk";
const keyra = new Keyra({ apiKey: process.env.KEYRA_API_KEY });Configure
Store secrets in environment variables. Never expose KEYRA_API_KEY in client-side code.
| Variable | Description |
|---|---|
KEYRA_API_KEY | Secret key for server-side API calls. Never expose in client bundles. |
KEYRA_WEBHOOK_SECRET | Used to verify webhook signatures (HMAC-SHA256). |
KEYRA_ENV | sandbox | production. Defaults to sandbox. |
First challenge
Create a challenge from your backend, present it to KEYRA ONE, then verify the signed attestation when the user approves.
const challenge = await keyra.challenges.create({
action: "transfer.approve",
userId: "usr_8f2a",
payload: {
amount: 12500,
currency: "USD",
memo: "Wire to Acme Corp",
},
expiresIn: 120, // seconds
});
// Returns: { id, status: "pending", expiresAt }Authentication
Send your API key as a Bearer token on every server-side request.
Authorization: Bearer sk_live_...
Content-Type: application/jsonChallenges API
Single-use, time-bound authorization requests bound to your action payload.
Create challenge
{
"action": "transfer.approve",
"userId": "usr_8f2a",
"payload": { "amount": 12500, "currency": "USD" },
"expiresIn": 120
}Response 201 Created
{
"id": "chl_9k2m",
"status": "pending",
"expiresAt": "2026-05-29T18:42:00Z"
}Verify response
Forward the attestation from the client to your backend and verify with the SDK — never trust client-only validation.
const result = await keyra.challenges.verify(challengeId, {
attestation: req.body.attestation,
deviceId: req.body.deviceId,
});
if (result.status === "approved") {
// Proceed with protected action
}Endpoints
| Method | Path | Description |
|---|---|---|
| POST | /v1/challenges | Create a single-use authorization challenge. |
| GET | /v1/challenges/:id | Retrieve challenge status and metadata. |
| POST | /v1/challenges/:id/verify | Verify attestation payload from KEYRA ONE. |
| POST | /v1/credentials/register | Begin WebAuthn / passkey registration. |
| POST | /v1/credentials/authenticate | Begin WebAuthn authentication ceremony. |
Webhooks
Receive signed events when a human approves, rejects, or lets a challenge expire.
app.post("/webhooks/keyra", (req, res) => {
const sig = req.headers["keyra-signature"];
if (!keyra.webhooks.verify(req.rawBody, sig)) {
return res.status(401).send("Invalid signature");
}
switch (req.body.type) {
case "challenge.approved":
fulfillTransfer(req.body.data.challengeId);
break;
case "challenge.rejected":
cancelPendingAction(req.body.data.challengeId);
break;
}
res.status(200).send({ received: true });
});Event types
| Event | Description |
|---|---|
challenge.approved | Human authorized the challenge on KEYRA ONE. |
challenge.rejected | User explicitly rejected or timed out. |
challenge.expired | Challenge TTL elapsed without a response. |
device.paired | New KEYRA ONE bound to a user account. |
WebAuthn
FIDO2-aligned passkey flows — biometric templates never leave the secure element.
- Server requests registration or authentication options.
- Browser calls
navigator.credentials. - Server verifies attestation with KEYRA SDK helpers.
// Server: issue registration options
const options = await keyra.credentials.registrationOptions({
userId: "usr_8f2a",
displayName: "Jane Founder",
});
// Client: pass options to navigator.credentials.create()
// Server: verify attestation with keyra.credentials.verifyRegistration()SDK reference
Typed clients with retry logic and webhook signature verification.
JavaScript / TypeScript
npm install @keyra/sdkPython
pip install keyra-sdkGo
go get keyra.dev/sdk/v1Error codes
Errors include code, message, and optional details. Retry only on 429 and 5xx.
| Code | HTTP | Description |
|---|---|---|
invalid_api_key | 401 | Missing or invalid API key. |
challenge_expired | 410 | Challenge TTL elapsed. |
challenge_already_used | 409 | Challenge was already consumed. |
attestation_invalid | 422 | Signature or device certificate failed verification. |
device_not_found | 404 | No paired KEYRA device for this user. |
rate_limit_exceeded | 429 | Too many requests; retry with backoff. |
{
"code": "challenge_expired",
"message": "Challenge chl_9k2m expired at 2026-05-29T18:42:00Z"
}