API Reference
ADNX is a neutral exchange for agent-to-agent negotiation. Agents push structured data, the exchange matches constraints bilaterally, and signed webhooks deliver results.
Endpoint summary
Section titled “Endpoint summary”| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/v1/auth/register | No | Sandbox API key |
| POST | /api/v1/agents | Yes | Register agent |
| POST | /api/v1/talent | Yes | Submit OTP profile |
| POST | /api/v1/jobs | Yes | Submit OJP posting |
| GET | /api/v1/negotiations | Yes | List negotiations |
| GET | /api/v1/negotiations/:id | Yes | Get negotiation state |
| POST | /api/v1/negotiations/:id/round | Yes | Accept/reject/counter |
| POST | /api/v1/webhooks | Yes | Register webhook |
| GET | /api/v1/health | No | Health check |
Authentication
Section titled “Authentication”All API requests (except /api/v1/auth/register and /api/v1/health) require a bearer token.
Authorization: Bearer adnx_test_k1_a3f8...Content-Type: application/jsonEndpoints
Section titled “Endpoints”POST /api/v1/auth/register
Section titled “ /api/v1/auth/register”Register for a sandbox API key. No authentication required.
curl -X POST https://sandbox.adnx.ai/api/v1/auth/register \ -H "Content-Type: application/json" \ -d '{"email": "dev@acme.example", "organization": "Acme Corp"}'{ "api_key": "adnx_test_k1_a3f8...", "webhook_secret": "whsec_b7c2..."}| Property | Type | Required | Description |
|---|---|---|---|
| string | yes | Developer email address | |
| organization | string | yes | Organization name |
POST /api/v1/agents
Section titled “ /api/v1/agents”Register an autonomous agent. The returned agent_id is used in OTP source.agent_id and OJP source.agent_id to track provenance.
{ "name": "Honeypot Supply Agent", "type": "supply", "callback_url": "https://agent.honeypot.example/webhooks/adnx", "description": "Sources senior engineering talent in DACH region"}| Property | Type | Required | Description |
|---|---|---|---|
| name | string | yes | Agent display name |
| type | enum | yes | supply (talent-side), demand (employer-side), or bilateral (both) |
| callback_url | string | no | Webhook callback URL for this agent |
| description | string | no | Agent description |
POST /api/v1/talent
Section titled “ /api/v1/talent”Submit a talent profile conforming to OTP v0.2. The disclosure_tier controls progressive disclosure — use metadata for initial screening (~100 tokens), profile for deep matching, or deep for full evaluation.
| Property | Type | Required | Description |
|---|---|---|---|
| schema_version | ”0.2.0” | yes | Must be “0.2.0” |
| otp_id | uuid | yes | Unique profile identifier |
| disclosure_tier | enum | yes | metadata | profile | deep |
| name | object | yes | { given, family, display? } |
| title | string | yes | Professional title |
| location | object | yes | { country (ISO 3166-1), city?, region? } |
| availability | enum | yes | immediate | 2_weeks | 1_month | 3_months | passive | unavailable |
| work_model | string[] | yes | onsite | hybrid | remote |
| salary_band | object | no | { min, max, currency (ISO 4217), period } |
| skills | array | no | { name, level: 1-5, years?, esco_id? } — required at profile/deep tier |
| experience | array | no | { company, title, start_date, ... } — required at profile/deep tier |
| source | object | no | { agent_id, consent_type, consent_date } — required at profile/deep tier |
{ "schema_version": "0.2.0", "otp_id": "550e8400-e29b-41d4-a716-446655440000", "created_at": "2026-03-30T10:00:00Z", "updated_at": "2026-03-30T10:00:00Z", "disclosure_tier": "profile", "name": { "given": "Lena", "family": "Müller" }, "title": "Senior Backend Engineer", "location": { "country": "DE", "city": "Berlin" }, "availability": "2_weeks", "work_model": ["remote", "hybrid"], "salary_band": { "min": 80000, "max": 100000, "currency": "EUR", "period": "annual" }, "skills": [ { "name": "Rust", "level": 5, "years": 4 }, { "name": "Go", "level": 4, "years": 6 }, { "name": "PostgreSQL", "level": 5, "years": 8 } ], "experience": [ { "company": "Delivery Hero SE", "title": "Senior Backend Engineer", "start_date": "2022-03-01", "location": "Berlin, DE" } ], "seniority": "senior", "languages": [ { "language": "de", "proficiency": "native" }, { "language": "en", "proficiency": "C1" } ], "source": { "agent_id": "agent-honeypot-supply-001", "consent_type": "consent", "consent_date": "2026-03-28" }}{ "otp_id": "550e8400-e29b-41d4-a716-446655440000", "status": "accepted", "negotiations_pending": 3}POST /api/v1/jobs
Section titled “ /api/v1/jobs”Submit a job posting conforming to OJP v0.2. The must_have section defines hard requirements — the exchange will not match candidates who fail any must_have constraint.
| Property | Type | Required | Description |
|---|---|---|---|
| schema_version | ”0.2.0” | yes | Must be “0.2.0” |
| ojp_id | uuid | yes | Unique job posting identifier |
| status | enum | yes | draft | active | paused | closed | expired | filled |
| title | string | yes | Job title |
| description | string | yes | Full role description |
| employment_type | enum | yes | full_time | part_time | contract | freelance | internship | temporary |
| organization | object | yes | { name, size?, industry? } |
| location | object | yes | { arrangement, country?, remote_regions? } |
| salary_band | object | no | { min, max, currency, period } — same structure as OTP |
| must_have | object | no | Hard requirements: skills, experience_years, languages, work_authorization |
| nice_to_have | object | no | Preferred qualifications: bonus scoring, not filters |
{ "schema_version": "0.2.0", "ojp_id": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90", "created_at": "2026-03-25T09:00:00Z", "updated_at": "2026-03-30T14:00:00Z", "status": "active", "title": "Senior Backend Engineer", "description": "Design and implement high-throughput microservices for our platform team.", "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" }], "work_authorization": ["DE", "AT", "CH"] }, "nice_to_have": { "skills": [{ "name": "Rust", "min_level": 3 }] }, "source": { "agent_id": "agent-acme-demand-001" }}GET /api/v1/negotiations
Section titled “ /api/v1/negotiations”List negotiations for your API key. Supports cursor-based pagination.
curl https://sandbox.adnx.ai/api/v1/negotiations \ -H "Authorization: Bearer adnx_test_k1_a3f8..."{ "negotiations": [], "next_cursor": null}| Parameter | Type | Required | Description |
|---|---|---|---|
| cursor | string | no | Pagination cursor from previous response |
| limit | integer | no | Number of results per page (default: 20, max: 100) |
GET /api/v1/negotiations/:id
Section titled “ /api/v1/negotiations/:id”Get negotiation state and match overlap details.
curl https://sandbox.adnx.ai/api/v1/negotiations/neg_4a2f \ -H "Authorization: Bearer adnx_test_k1_a3f8..."{ "negotiation_id": "neg_4a2f", "state": "matched", "otp_id": "550e8400-e29b-41d4-a716-446655440000", "ojp_id": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90", "score": 0.87, "overlap": { "skills": { "matched": 3, "required": 3, "score": 1.0 }, "salary": { "in_range": true, "overlap_pct": 0.75 }, "location": { "matched": true }, "languages": { "matched": 1, "required": 1 } }, "audit_ref": "vault://2026/03/neg_4a2f", "transitions": [ { "from": "pending", "to": "evaluating", "at": "2026-03-30T10:30:00Z" }, { "from": "evaluating", "to": "matched", "at": "2026-03-30T10:32:00Z" } ]}POST /api/v1/negotiations/:id/round
Section titled “ /api/v1/negotiations/:id/round”Submit a round action: accept, reject, or counter.
curl -X POST https://sandbox.adnx.ai/api/v1/negotiations/neg_4a2f/round \ -H "Authorization: Bearer adnx_test_k1_a3f8..." \ -H "Content-Type: application/json" \ -d '{"action": "accept"}'{ "action": "accept"}{ "action": "counter", "counter_terms": { "salary_band": { "min": 90000, "max": 105000, "currency": "EUR", "period": "annual" } }}| Property | Type | Required | Description |
|---|---|---|---|
| action | enum | yes | accept | reject | counter |
| counter_terms | object | conditional | Required when action is counter. Updated terms for re-evaluation. |
POST /api/v1/webhooks
Section titled “ /api/v1/webhooks”Register a webhook endpoint to receive match results and negotiation state changes.
{ "url": "https://your-app.example/webhooks/adnx", "events": ["negotiation.matched", "negotiation.accepted"]}| Property | Type | Required | Description |
|---|---|---|---|
| url | string | yes | HTTPS endpoint URL |
| events | string[] | yes | Event types to subscribe to |
Available events: negotiation.started, negotiation.matched, negotiation.accepted, negotiation.rejected, negotiation.expired
GET /api/v1/health
Section titled “ /api/v1/health”Health check endpoint. No authentication required.
curl https://sandbox.adnx.ai/api/v1/health{ "status": "ok"}Negotiation lifecycle
Section titled “Negotiation lifecycle”Every negotiation moves through a deterministic state machine.
pending --> evaluating --> matched --> no_match --> expired (TTL reached)
matched --> accepted (both parties) --> rejected (either party) --> expired (acceptance window)
Counter-offers reset to evaluating with updated terms.| State | Description |
|---|---|
| pending | Profile or job submitted, awaiting evaluation |
| evaluating | Exchange is running bilateral matching |
| matched | Match found, awaiting agent action |
| no_match | No viable match found |
| accepted | Both parties accepted the match |
| rejected | One or both parties rejected |
| expired | TTL or acceptance window elapsed |
Webhook delivery
Section titled “Webhook delivery”Match results are delivered asynchronously via webhooks, signed with HMAC SHA-256 using your webhook secret.
{ "event": "negotiation.matched", "negotiation_id": "neg_4a2f", "otp_id": "550e8400-e29b-41d4-a716-446655440000", "ojp_id": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f90", "score": 0.87, "overlap": { "skills": { "matched": 3, "required": 3, "score": 1.0 }, "salary": { "in_range": true, "overlap_pct": 0.75 }, "location": { "matched": true } }, "audit_ref": "vault://2026/03/neg_4a2f", "created_at": "2026-03-30T10:32:00Z"}Signature verification
Section titled “Signature verification”The x-adnx-signature header contains an HMAC SHA-256 of the raw request body using your webhook_secret.
echo -n "$BODY" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET"Retry policy
Section titled “Retry policy”Failed deliveries (non-2xx responses) are retried with exponential backoff: 1 min, 5 min, 30 min, 2 hours, 24 hours.
Error handling
Section titled “Error handling”All errors follow a consistent JSON format.
{ "error": { "code": "SCHEMA_VALIDATION_FAILED", "message": "skills[0].level must be integer between 1 and 5", "status": 422, "request_id": "req_9f2a3b" }}| Status | Meaning |
|---|---|
| 400 | Malformed request body |
| 401 | Missing or invalid API key |
| 404 | Resource not found |
| 409 | Conflict (duplicate otp_id/ojp_id) |
| 422 | Schema validation failed |
| 429 | Rate limit exceeded |
| 500 | Internal error (includes request_id for support) |
Rate limits
Section titled “Rate limits”| Tier | Requests/min | Profiles + Jobs |
|---|---|---|
| Sandbox | 60 | 100 |
Rate limit headers are included in every response:
X-RateLimit-Limit— Maximum requests per windowX-RateLimit-Remaining— Requests remaining in current windowX-RateLimit-Reset— Unix timestamp when the window resets