SDKs
Official client libraries for the ADNX API. Both SDKs cover the full API surface, handle authentication, and include webhook signature verification.
| Python | TypeScript | |
|---|---|---|
| Package | adnx | @adnx/sdk |
| Version | 0.2.0 | 0.2.0 |
| Runtime | Python 3.10+ | Node 18+ / Bun / Deno / Cloudflare Workers |
| Dependencies | None (stdlib only) | None (uses fetch) |
Installation
Section titled “Installation”pip install adnxnpm install @adnx/sdkAuthentication
Section titled “Authentication”from adnx import ADNXClient
# Register for sandbox credentials (one-time)creds = ADNXClient.register( email="dev@acme.example", organization="Acme Corp",)
# Create a clientclient = ADNXClient( api_key=creds["api_key"], webhook_secret=creds["webhook_secret"],)import { ADNXClient } from "@adnx/sdk";
// Register for sandbox credentials (one-time)const creds = await ADNXClient.register("dev@acme.example", "Acme Corp");
// Create a clientconst client = new ADNXClient({ apiKey: creds.api_key, webhookSecret: creds.webhook_secret,});API methods
Section titled “API methods”Python — ADNXClient
Section titled “Python — ADNXClient”| Method | Description | Returns |
|---|---|---|
ADNXClient.register(email, organization) | Register for sandbox credentials (static) | { api_key, webhook_secret } |
register_agent(name, type, callback_url, description?) | Register an agent on the exchange | { agent_id, name, type, created_at } |
submit_talent(otp_payload) | Submit an OTP v0.2 talent profile | { otp_id, status, negotiations_pending } |
submit_job(ojp_payload) | Submit an OJP v0.2 job posting | { ojp_id, status, negotiations_pending } |
list_negotiations(state?, limit?, cursor?) | List negotiations with optional filters | { negotiations, next_cursor } |
get_negotiation(negotiation_id) | Get negotiation details | Negotiation object |
submit_round(negotiation_id, action, counter_terms?, reason?) | Accept, reject, or counter a negotiation | Round result |
register_webhook(url, events) | Register a webhook endpoint | { webhook_id, url, events } |
verify_webhook(payload, signature) | Verify webhook HMAC signature | bool |
health() | Check API health | { status, version, schemas } |
TypeScript — ADNXClient
Section titled “TypeScript — ADNXClient”| Method | Description | Returns |
|---|---|---|
ADNXClient.register(email, organization) | Register for sandbox credentials (static) | Promise<{ api_key, webhook_secret }> |
registerAgent(params) | Register an agent on the exchange | Promise<{ agent_id, name, type, created_at }> |
submitTalent(otpPayload) | Submit an OTP v0.2 talent profile | Promise<{ otp_id, status, negotiations_pending }> |
submitJob(ojpPayload) | Submit an OJP v0.2 job posting | Promise<{ ojp_id, status, negotiations_pending }> |
listNegotiations(params?) | List negotiations with optional filters | Promise<{ negotiations, next_cursor }> |
getNegotiation(negotiationId) | Get negotiation details | Promise<Record> |
submitRound(params) | Accept, reject, or counter a negotiation | Promise<{ negotiation_id, state, round }> |
registerWebhook(url, events) | Register a webhook endpoint | Promise<{ webhook_id, url, events }> |
verifyWebhook(payload, signature) | Verify webhook HMAC signature (Web Crypto) | Promise<boolean> |
health() | Check API health | Promise<{ status, version, schemas }> |
Quickstart
Section titled “Quickstart”Register, submit a job and a talent profile, then check for matches.
from adnx import ADNXClient
# 1. Register and create clientcreds = ADNXClient.register(email="dev@acme.example", organization="Acme Corp")client = ADNXClient(api_key=creds["api_key"], webhook_secret=creds["webhook_secret"])
# 2. Register a demand agentagent = client.register_agent( name="Acme ATS Agent", type="demand", callback_url="https://acme-ats.example/webhooks/adnx",)
# 3. Submit a job posting (OJP v0.2)job = client.submit_job({ "schema_version": "0.2.0", "ojp_id": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90", "created_at": "2026-04-01T10:00:00Z", "updated_at": "2026-04-01T10:00:00Z", "status": "active", "title": "Senior Backend Engineer", "description": "High-throughput microservices and API design.", "employment_type": "full_time", "seniority": "senior", "organization": {"name": "Acme Corp", "size": "scale_up"}, "location": {"arrangement": "hybrid", "country": "DE", "city": "Berlin"}, "salary_band": {"min": 85000, "max": 110000, "currency": "EUR", "period": "annual"}, "must_have": { "skills": [ {"name": "Go", "min_level": 4, "min_years": 3}, {"name": "PostgreSQL", "min_level": 3}, ], "experience_years": {"min": 5}, "languages": [{"language": "en", "proficiency": "C1"}], }, "source": {"agent_id": agent["agent_id"]},})print(f"Job submitted: {job['ojp_id']} ({job['negotiations_pending']} pending)")
# 4. Check negotiationsnegotiations = client.list_negotiations(state="matched")for neg in negotiations["negotiations"]: print(f"Match {neg['negotiation_id']}: score={neg['score']:.2f}")import { ADNXClient } from "@adnx/sdk";
// 1. Register and create clientconst creds = await ADNXClient.register("dev@acme.example", "Acme Corp");const client = new ADNXClient({ apiKey: creds.api_key, webhookSecret: creds.webhook_secret,});
// 2. Register a demand agentconst agent = await client.registerAgent({ name: "Acme ATS Agent", type: "demand", callbackUrl: "https://acme-ats.example/webhooks/adnx",});
// 3. Submit a job posting (OJP v0.2)const job = await client.submitJob({ schema_version: "0.2.0", ojp_id: "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90", created_at: "2026-04-01T10:00:00Z", updated_at: "2026-04-01T10:00:00Z", status: "active", title: "Senior Backend Engineer", description: "High-throughput microservices and API design.", employment_type: "full_time", seniority: "senior", organization: { name: "Acme Corp", size: "scale_up" }, location: { arrangement: "hybrid", country: "DE", city: "Berlin" }, salary_band: { min: 85000, max: 110000, currency: "EUR", period: "annual" }, must_have: { skills: [ { name: "Go", min_level: 4, min_years: 3 }, { name: "PostgreSQL", min_level: 3 }, ], experience_years: { min: 5 }, languages: [{ language: "en", proficiency: "C1" }], }, source: { agent_id: agent.agent_id },});console.log(`Job submitted: ${job.ojp_id} (${job.negotiations_pending} pending)`);
// 4. Check negotiationsconst { negotiations } = await client.listNegotiations({ state: "matched" });for (const neg of negotiations) { console.log(`Match ${neg.negotiation_id}: score=${(neg.score as number).toFixed(2)}`);}Webhook verification
Section titled “Webhook verification”Verify that incoming webhooks are authentic by checking the X-ADNX-Signature header.
from flask import request, abortfrom adnx import ADNXClient
client = ADNXClient(api_key="...", webhook_secret="whsec_b7c2...")
@app.route("/webhooks/adnx", methods=["POST"])def handle_webhook(): signature = request.headers.get("X-ADNX-Signature", "") if not client.verify_webhook(request.data, signature): abort(401)
event = request.json if event["event"] == "negotiation.matched": print(f"Match: {event['negotiation_id']} score={event['score']}") return "", 200import { ADNXClient } from "@adnx/sdk";import express from "express";
const client = new ADNXClient({ apiKey: "...", webhookSecret: "whsec_b7c2..." });const app = express();app.use(express.raw({ type: "application/json" }));
app.post("/webhooks/adnx", async (req, res) => { const signature = req.headers["x-adnx-signature"] as string; const valid = await client.verifyWebhook(req.body, signature); if (!valid) return res.sendStatus(401);
const event = JSON.parse(req.body.toString()); if (event.event === "negotiation.matched") { console.log(`Match: ${event.negotiation_id} score=${event.score}`); } res.sendStatus(200);});Error handling
Section titled “Error handling”Both SDKs throw an ADNXError with structured fields when the API returns a non-2xx response.
from adnx import ADNXClient, ADNXError
client = ADNXClient(api_key="adnx_test_k1_...")
try: client.submit_job({"invalid": "payload"})except ADNXError as e: print(e.code) # "SCHEMA_VALIDATION_FAILED" print(e.message) # "schema_version is required" print(e.status) # 422 print(e.request_id) # "req_9f2a3b"import { ADNXClient, ADNXError } from "@adnx/sdk";
const client = new ADNXClient({ apiKey: "adnx_test_k1_..." });
try { await client.submitJob({ invalid: "payload" });} catch (e) { if (e instanceof ADNXError) { console.log(e.code); // "SCHEMA_VALIDATION_FAILED" console.log(e.message); // "schema_version is required" console.log(e.status); // 422 console.log(e.requestId); // "req_9f2a3b" }}Further reading
Section titled “Further reading”- API Reference — full endpoint documentation, request/response schemas, and rate limits
- OTP & OJP Protocols — schema details for talent profiles and job postings
- Quickstart — curl-based tutorial covering the same flow