Skip to Content
Advanced TopicsPasskeys & Approvals

Passkeys & Approvals

Koywe exposes a public approval layer for sensitive actions. It combines WebAuthn passkeys, short-lived MFA tokens, and transactional policy approvals.

Public Endpoint Families

WebAuthn / Passkeys

  • POST /api/v1/organizations/{organizationId}/webauthn/register/init
  • POST /api/v1/organizations/{organizationId}/webauthn/register/complete
  • POST /api/v1/organizations/{organizationId}/webauthn/challenge
  • POST /api/v1/organizations/{organizationId}/webauthn/verify
  • GET /api/v1/organizations/{organizationId}/webauthn/credentials
  • GET /api/v1/organizations/{organizationId}/webauthn/credentials/all

Enrollment, Wallet Provisioning, and Recovery

  • POST /api/v1/organizations/{organizationId}/webauthn/enroll/init
  • POST /api/v1/organizations/{organizationId}/webauthn/enroll/prepare
  • POST /api/v1/organizations/{organizationId}/webauthn/wallet/prepare
  • GET /api/v1/organizations/{organizationId}/webauthn/wallet/{merchantId}/status
  • POST /api/v1/organizations/{organizationId}/webauthn/wallet/complete
  • recovery endpoints under /webauthn/recovery/*

Transactional Policy

  • POST /api/v1/organizations/{organizationId}/policy
  • GET /api/v1/organizations/{organizationId}/policy
  • POST /api/v1/organizations/{organizationId}/policy/rules
  • PUT /api/v1/organizations/{organizationId}/policy/rules/{ruleId}
  • GET /api/v1/organizations/{organizationId}/policy/audit

Pending Approvals

  • GET /api/v1/organizations/{organizationId}/policy/approvals
  • GET /api/v1/organizations/{organizationId}/policy/approvals/{approvalId}
  • POST /api/v1/organizations/{organizationId}/policy/approvals/{approvalId}/approve
  • POST /api/v1/organizations/{organizationId}/policy/approvals/{approvalId}/reject

Human User Passkey Enrollment

Human users should enroll passkeys in Koywe Platform, not by calling the WebAuthn endpoints directly.

This is the recommended flow for super admins and other operators who need to approve sensitive actions:

  1. Sign in to Koywe Platform with your normal user account.
  2. If your organization does not have passkeys active yet, Koywe will show a prompt to enroll or activate passkeys for the organization.
  3. A super admin starts the enrollment flow and approves passkey activation for the organization.
  4. Each user who must operate protected flows is prompted to create their own passkey.
  5. Once created, that user can use the passkey for MFA and approval flows inside the platform.

What the User Experience Looks Like

  • Users will see an in-product prompt to create a passkey when their organization requires it.
  • The browser or device will open the native passkey dialog.
  • The user can store the passkey on the current device or in a password manager / cloud keychain.
  • If their passkey provider syncs across devices, the passkey will usually become available automatically on their other enrolled devices as well.
  • Ask at least one super admin to complete organization activation first.
  • Ask every approver to enroll their own passkey before enabling high-friction approval policies.
  • Tell users to save the passkey in a synced provider when possible, so they are not tied to a single device.
  • Treat this as the standard path for human users; reserve the API-user signing flow below for delegated or service-driven operations.

API User Signing Tutorial

If you want an API user to participate in delegated MFA or embedded wallet signing flows, the simplest setup is:

  1. generate a PEM key pair
  2. submit the public key for enrollment
  3. have a root user approve the enrollment
  4. sign protected payloads locally with the private key

Step 0: Create the API User Credentials

Before enrolling delegated MFA, create organization- or merchant-scoped API credentials for the API user. See Organization Setup & Invitations.

Step 1: Generate a PEM Key Pair

openssl genpkey -algorithm RSA -out api-user-private.pem -pkeyopt rsa_keygen_bits:2048 openssl rsa -pubout -in api-user-private.pem -out api-user-public.pem

Keep the private key in your secret manager. Only the public key should be submitted to Koywe.

Step 2: Submit the Public Key for Delegated MFA Enrollment

The API user submits its public key to create a pending approval:

curl -X POST 'https://api-sandbox.koywe.com/api/v1/auth/organizations/YOUR_ORG_ID/api-users/mfa/prepare' \ -H 'Authorization: Bearer YOUR_API_USER_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "publicKey": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----" }'

This returns the enrollment payload and the pendingApprovalId that the root user will approve.

Step 3: Root User Approves the Enrollment

The root passkey holder loads the prepared enrollment request:

curl -X POST 'https://api-sandbox.koywe.com/api/v1/auth/organizations/YOUR_ORG_ID/api-users/mfa/enroll/prepare' \ -H 'Authorization: Bearer YOUR_ROOT_USER_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "pendingApprovalId": "pap_123" }'

The root user signs the returned request with their passkey and finalizes approval with:

curl -X POST 'https://api-sandbox.koywe.com/api/v1/auth/organizations/YOUR_ORG_ID/api-users/mfa/enroll/approve' \ -H 'Authorization: Bearer YOUR_ROOT_USER_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "pendingApprovalId": "pap_123", "stampedRequest": { "...": "signed-by-root-passkey" } }'

You can then confirm the delegated credential exists with:

  • GET /api/v1/auth/organizations/{organizationId}/api-users/{apiKey}/mfa

Step 4: Sign Payloads with the Private Key

Once approved, your API user keeps the PEM private key locally and uses it when a protected flow requires delegated signing.

Minimal Node.js example:

import { createSign, readFileSync } from 'crypto' const privateKey = readFileSync('./api-user-private.pem', 'utf8') const payload = JSON.stringify(requestBody) const signer = createSign('RSA-SHA256') signer.update(payload) signer.end() const signature = signer.sign(privateKey, 'base64')

The exact payload shape and transport field depend on the protected endpoint you are calling. Use the relevant request schema in the API Reference as the source of truth.

Embedded Wallet Access Variant

For embedded wallet access, the approval flow is similar but uses dedicated endpoints:

  1. API or user context requests access with POST /api/v1/auth/organizations/{organizationId}/wallet-access/request
  2. root user loads the approval payload with POST /api/v1/auth/organizations/{organizationId}/wallet-access/prepare
  3. root user signs and finalizes with POST /api/v1/auth/organizations/{organizationId}/wallet-access/approve

The operational model is the same: request, root approval, then perform the protected signing flow with the approved signer.

How the Flow Works

  • Passkeys prove the identity of the acting user.
  • The MFA token authorizes a short-lived protected action.
  • Transactional policy decides whether the action can proceed immediately or requires approval.
  • Approval endpoints let a separate approver accept or reject that pending operation.

When You Need This

These flows matter when you use:

  • protected bank-account creation flows that require MFA confirmation
  • embedded wallet or signing flows
  • organization-level approval rules for treasury or operational controls

Best Practices

  • Treat MFA tokens as short-lived session artifacts, not durable credentials.
  • Build a pending-approval state into your application if you enable transactional policy.
  • Surface approval IDs in operator tooling so reviewers can approve or reject quickly.
  • Pair this guide with Security Best Practices for credential and webhook hardening.

Next Steps

Last updated on