Fintech APIs & Platform for KYC, Verification & Transactions in India | Eko Platform Services
Eko Platform Services Logo

How Auth Works

Every Eko API request is authenticated with a static key plus a per-request HMAC signature. Nothing secret ever travels on the wire in plain form.

The two keys

KeyWhere it comes fromHow it's used
Access KeyShared once, kept server-side onlyNever sent in a request; used to compute the secret-key
Developer KeyUAT key from your dashboard; production key after KYCSent as the developer_key header

Request headers

HeaderRequiredDescription
developer_keyyesYour static developer key.
secret-keyyesPer-request HMAC signature (see below).
secret-key-timestampyesCurrent time in milliseconds since the UNIX epoch.
content-typeyesapplication/json

Computing the secret-key

The signature binds the request to a timestamp, so it must be generated fresh for every call:

  1. Base64-encode the access_key — keep this as a string.
  2. Take the current timestamp in milliseconds, as a string.
  3. Compute HMAC-SHA256 with the timestamp as the message and that base64 string as the key.
  4. Base64-encode the result — that's the secret-key.

Send the same timestamp in secret-key-timestamp. A stale or mismatched timestamp returns 403 Forbidden.

secret-key = base64( HMAC-SHA256( message = timestamp, key = base64(access_key) ) )

Common mistake: the HMAC key is the base64 string base64(access_key), used as-is. Do not base64-decode it back to raw bytes before signing — that produces a different signature and a 403.

Code examples

Sign on your backend — the access_key must never reach a browser. The same recipe in five languages:

// Backend only. Never expose access_key in a browser.
import crypto from "node:crypto";
const accessKey = process.env.EKO_ACCESS_KEY;
const timestamp = Date.now().toString();
const encodedKey = Buffer.from(accessKey).toString("base64");
const secretKey = crypto
.createHmac("sha256", encodedKey)
.update(timestamp)
.digest("base64");
// headers: { developer_key, "secret-key": secretKey, "secret-key-timestamp": timestamp }

Why sign client-side

Because the access_key never leaves your server, a leaked request can't be replayed or forged — the timestamp-bound signature is only valid for a short window. When using the in-page Test Request modal, signing happens locally in your browser with the UAT credentials you supply: your access_key is used only to compute the signature and is stripped before the request is sent — it is never transmitted.