Backend API¶
This page documents the partner-facing API surface. Examples use sandbox placeholder hosts and credentials.
| Environment | Base URL |
|---|---|
| Test | https://ptest.yanez.ai |
| Production | https://yid.yanez.ai |
Validate a Record¶
POST /api/partners/records/validate
Confirms whether a Yanez identity record exists and, optionally, that a public key is bound to it. This is the only registry endpoint — there is no separate registration step. Yanez manages the yid-key binding; partners use this endpoint to verify it.
Run this after verifying the user's callback signature, before persisting the binding. Returns booleans, not the record.
This endpoint requires signed partner request authentication.
Request¶
{
"yid": "796aaf67d496447fa4059dcea80b03aa",
"public_key": "0x3b6a0f..."
}
| Field | Required | Notes |
|---|---|---|
yid |
yes | Opaque 32-char hex record ID, case-insensitive. Validate only that it is 32 hex characters — do not assert UUID structure. |
public_key |
no | The user's public key for this yid. Raw hex, 0x prefix optional, case-insensitive. Ed25519 = 64 hex chars; BLS12-381 G1 = 96 hex chars. Omit to check yid only. |
Unknown fields are rejected with 422.
Response — 200 OK¶
{
"yid_valid": true,
"public_key_valid": true
}
The pair is confirmed only when both are true.
yid exists |
public_key sent |
Key bound | yid_valid |
public_key_valid |
|---|---|---|---|---|
| yes | no | — | true |
null |
| no | no | — | false |
null |
| yes | yes | yes | true |
true |
| yes | yes | no | true |
false |
| no | yes | — | false |
false |
An unknown yid returns 200 with yid_valid: false — not a 404. Branch
on the booleans, not the HTTP status. The endpoint only tells you whether the
key you supplied is bound — it never enumerates the keys on a record. A yid
may carry several keys; this endpoint only tests membership. Duplicate
detection happens at enrollment.
Errors¶
| Status | When |
|---|---|
400 |
yid not 32 hex chars; public_key non-hex or outside 32–256 bytes. |
401 |
Signature or auth failed — generic, never says which check failed. |
422 |
Missing yid, unknown field, or invalid JSON body. |
429 |
More than 60 requests per 60 seconds per IP. Enforced before auth, so it can precede a 401. Body: {"detail":"Too many requests"}. |
Python Example¶
import base64, hashlib, json, secrets
from datetime import datetime, timezone
from typing import Optional
import requests
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
BASE_URL = "https://ptest.yanez.ai"
PARTNER_ID = "ptr_..."
KEY_ID = "key-1"
PRIVATE_KEY = "..." # 32-byte Ed25519 private key as hex
def b64url(raw: bytes) -> str:
return base64.urlsafe_b64encode(raw).rstrip(b"=").decode()
def validate_pair(yid: str, public_key: Optional[str] = None) -> dict:
path = "/api/partners/records/validate"
payload = {"yid": yid}
if public_key is not None:
payload["public_key"] = public_key
body = json.dumps(payload).encode()
timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
nonce = secrets.token_urlsafe(18)
body_hash = b64url(hashlib.sha256(body).digest())
canonical = "\n".join([
"YANEZ-SIG-V1", "POST", path, PARTNER_ID, KEY_ID, "EdDSA",
timestamp, nonce, body_hash,
]).encode()
sig = b64url(Ed25519PrivateKey.from_private_bytes(bytes.fromhex(PRIVATE_KEY)).sign(canonical))
headers = {
"Content-Type": "application/json",
"X-Yanez-Partner-Id": PARTNER_ID,
"X-Yanez-Key-Id": KEY_ID,
"X-Yanez-Signature-Alg": "EdDSA",
"X-Yanez-Timestamp": timestamp,
"X-Yanez-Nonce": nonce,
"X-Yanez-Content-SHA256": body_hash,
"X-Yanez-Signature": sig,
}
resp = requests.post(BASE_URL + path, data=body, headers=headers, timeout=10)
resp.raise_for_status()
return resp.json()
if __name__ == "__main__":
result = validate_pair(yid="<yid>", public_key="0x<hex>")
confirmed = result["yid_valid"] and result["public_key_valid"]
print("Confirmed" if confirmed else f"Rejected: {result}")