Authentication
Every authenticated request to the Coyns API must include Ed25519 signature headers. POST requests also require an OTP.
Required Headers
X-Agent-Id — your agent ID
X-Timestamp — Unix epoch seconds
X-Signature — Ed25519 signature (base64)
X-OTP — required for POST requests (use "000000" for staging)
X-Idempotency-Key — optional, for replay protection
Canonical String
The signature is computed over a canonical string built from the request:
method\n (lowercase: "post", "get") path\n (e.g. "/v1/payments") sha256(body)\n (hex-encoded hash of request body) timestamp\n (same value as X-Timestamp) idempotency_key (empty string if not provided)
The five parts are joined with newline characters. The resulting string is signed with your Ed25519 private key.
TypeScript Example
import { createHash } from "crypto";
import * as ed from "@noble/ed25519";
import { sha512 } from "@noble/hashes/sha512";
ed.etc.sha512Sync = (...m: Uint8Array[]) =>
sha512(ed.etc.concatBytes(...m));
function signRequest(opts: {
privateKey: Uint8Array;
method: string;
path: string;
body: string;
idempotencyKey?: string;
}) {
const timestamp = Math.floor(Date.now() / 1000).toString();
const bodyHash = createHash("sha256")
.update(opts.body || "")
.digest("hex");
const canonical = [
opts.method.toLowerCase(),
opts.path,
bodyHash,
timestamp,
opts.idempotencyKey || "",
].join("\n");
const sig = ed.sign(Buffer.from(canonical), opts.privateKey);
return {
timestamp,
signature: Buffer.from(sig).toString("base64"),
};
}
function buildHeaders(opts: {
agentId: string;
privateKey: Uint8Array;
method: string;
path: string;
body: string;
idempotencyKey?: string;
otp?: string;
}) {
const { timestamp, signature } = signRequest(opts);
return {
"Content-Type": "application/json",
"X-Agent-Id": opts.agentId,
"X-Timestamp": timestamp,
"X-Signature": signature,
...(opts.otp && { "X-OTP": opts.otp }),
...(opts.idempotencyKey && {
"X-Idempotency-Key": opts.idempotencyKey,
}),
};
}Staging OTP
In the staging environment, use 000000 as the OTP value for all POST requests.