Skip to Content
OneKYC
Tenant API (KYC)

Authentication

Last updated:

API status. The OneKYC Tenant API is in beta. Endpoints, data formats, and API versions may change. Track documentation updates.

To call the OneKYC API from a server, you need to authenticate. Two mechanisms are supported: HMAC signing for server-to-server interaction (Tenant API) and a JWT token for verification-session access (used by the verification page when the end user opens a link).

HMAC (server-to-server with the OneKYC API)

Server-side requests are signed with HMAC-SHA256. This mechanism proves that the request came from an authorised API key holder.

Required headers:

  • Authorization — HMAC-SHA256 Credential={key_id}, Signature={signature}
  • X-Timestamp — current Unix time (seconds). Requests with clock drift over 5 minutes are rejected (replay protection).

Signature algorithm:

  1. Build the string to sign (components are joined by a newline \n):

    stringToSign = timestamp + "\n" + method + "\n" + path + "\n" + bodyHash

    where:

    • timestamp — value of the X-Timestamp header (Unix seconds)
    • method — HTTP method in upper case (GET, POST, PUT, DELETE, etc.)
    • path — full request path with query parameters (for example, /tenant/v1/kyc/applicants?page=1)
    • bodyHash — SHA256 hash of the request body in hex (empty string for GET requests and other bodyless requests)
  2. Compute HMAC-SHA256 using the API key secret:

    signature = HMAC-SHA256(stringToSign, api_secret)

    Encode the result in hex (a 64-character string).

  3. Build and send the request with the headers above. Example endpoint for creating a verification link:

POST
/v1/kyc/verification-links

Authorization

ApiKeyAuth
headerAuthorization<token>

HMAC-SHA256 Credential=<key_id>, Signature=<hex_signature>. SignedHeaders=x-timestamp is optional. Requires X-Timestamp header.

Header Parameters

X-Timestamp*string

Unix timestamp (seconds, max 5 min drift)

Request Body

Link options (flow_id required)

application/json
  1. body
expires_in?integer

seconds

external_reference?string
external_user_id?string
flow_id?string
locale?string
metadata?
prefilled?
redirect_url?string
utm_campaign?string
utm_medium?string
utm_source?string

Response Body

Created or reused link

application/json
  1. response
data?
success?boolean
Example Request
curl -X POST 'https://api.onekyc.io/tenant/v1/kyc/verification-links' \  -H 'X-Timestamp: string' \  -H 'Content-Type: application/json' \  -d '{}'
Example Response
{  "success": true,  "data": {    "created_at": "string",    "delivery_eligible": true,    "expires_at": "string",    "external_reference": "string",    "external_user_id": "string",    "flow_id": "string",    "id": "string",    "link_url": "string",    "locale": "string",    "qr_code_url": "string",    "redirect_url": "string",    "reuse_reason": "external_reference",    "reused": true,    "session_id": "string",    "session_resumable": true,    "session_status": "string",    "short_url": "string",    "status": "string",    "url": "string",    "verification_link": "string",    "verification_url": "string"  }}

Example (JavaScript / Node.js):

const crypto = require("crypto");

// 1. Compute bodyHash (SHA256 hash of the request body)
const body = JSON.stringify({ flow_id: "uuid-here" });
const bodyHash = crypto.createHash("sha256").update(body).digest("hex");

// 2. Build the string to sign
const timestamp = Math.floor(Date.now() / 1000).toString();
const method = "POST";
const path = "/tenant/v1/kyc/verification-links";
const stringToSign = `${timestamp}\n${method}\n${path}\n${bodyHash}`;

// 3. Compute the HMAC-SHA256 signature
const apiSecret = "your_api_secret_here";
const signature = crypto
  .createHmac("sha256", apiSecret)
  .update(stringToSign)
  .digest("hex");

// 4. Build the request headers
const headers = {
  "Content-Type": "application/json",
  "X-Timestamp": timestamp,
  Authorization: `HMAC-SHA256 Credential=kyc_test_<your_key_id>, Signature=${signature}`,
};

Example (Go):

import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "encoding/json"
    "fmt"
    "strconv"
    "time"
)

// 1. Compute bodyHash (SHA256 hash of the request body)
body := map[string]string{"flow_id": "uuid-here"}
bodyBytes, _ := json.Marshal(body)
hash := sha256.Sum256(bodyBytes)
bodyHash := hex.EncodeToString(hash[:])

// 2. Build the string to sign
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
method := "POST"
path := "/tenant/v1/kyc/verification-links"
stringToSign := fmt.Sprintf("%s\n%s\n%s\n%s", timestamp, method, path, bodyHash)

// 3. Compute the HMAC-SHA256 signature
apiSecret := "your_api_secret_here"
mac := hmac.New(sha256.New, []byte(apiSecret))
mac.Write([]byte(stringToSign))
signature := hex.EncodeToString(mac.Sum(nil))

// 4. Build the request headers
// Authorization: HMAC-SHA256 Credential=kyc_test_<your_key_id>, Signature={signature}
// X-Timestamp: {timestamp}

The API key secret is shown once when you create the key in the admin panel — store it in a secure vault. Keep the secret on the server side; do not ship it to client applications.

Key formats:

  • KYC keys: prefix kyc_live_ for production, kyc_test_ for the test environment. Grant access to /tenant/v1/kyc/ endpoints.
  • KYB keys: prefix kyb_live_ for production, kyb_test_ for the test environment. Grant access to /tenant/v1/kyb/ endpoints only.

The key secret carries the sk_ prefix. Keys are created and revoked in the API keys section of the admin panel.

Test and live modes:

  • Test keys (kyc_test_*, kyb_test_*) — for development and testing. No real verifications are run.
  • Live keys (kyc_live_*, kyb_live_*) — for production. Process real user verifications.
  • Keys are isolated: test keys do not access live data and vice versa.
  • KYC keys cannot call KYB endpoints and vice versa — the server returns HTTP 403.

Scopes: when you create a key, you select scopes that determine the available operations.

KYC scopes (for kyc_* keys):

ScopeDescription
applicants:readRead applicant data
applicants:writeModify and delete applicants
sessions:createCreate verification sessions and create, batch-create, or revoke KYC verification links
verifications:readRead verification and AML results
documents:readRead documents
media:readRead media files
webhooks:readRead webhook configuration
webhooks:writeManage webhooks
metrics:readRead metrics and analytics
audit:readRead the audit log
verification-links:readRead verification links
documents:uploadUpload documents
reviews:readRead the manual review queue, tasks, comments, and reject reasons
reviews:writeAssign, decide, comment, priority, and resubmit on KYC review tasks

KYB scopes (for kyb_* keys):

ScopeDescription
businesses:readRead business data
businesses:writeModify business data
kyb.sessions:readRead KYB sessions
kyb.verification-links:readRead KYB verification links
kyb.verification-links:writeCreate and manage KYB verification links
kyb.documents:readRead KYB documents
kyb.media:readRead KYB media files (also required for review document URLs)
kyb.webhooks:readRead KYB webhook configuration
kyb.webhooks:writeManage KYB webhooks
kyb.metrics:readRead KYB metrics
kyb.audit:readRead the KYB audit log
kyb.reviews:readRead the KYB manual review queue and tasks
kyb.reviews:writeAssign, decide, comment, priority, and resubmit on KYB review tasks

Manual review for integrators: Review tasks.

Each endpoint requires the matching scope; if access is insufficient, the server returns HTTP 403. Wildcard scopes are supported: * (full access) or applicants:* (all applicant operations).

JWT (verification-session access)

When a verification link is activated, OneKYC issues a short-lived JWT token. The OneKYC verification page uses this token: when the end user opens the link, every API request (fetching session data, uploading documents, executing steps) carries the Authorization: Bearer <token> header. The token lifetime is set when you create the link (for example, 600 seconds).


Summary: server-side integration uses HMAC signing with an API key to call the Tenant API; the end user's verification access uses a JWT token issued when the link is activated. For full endpoint reference, see Sessions and API reference (OpenAPI).

On this page