Webhook scoring
API reference · POST /v1/webhooks/score
Score a single record via webhook. Designed for Marketo, Zapier, etc.
A single-record variant with a flat response, shaped for Marketo, Zapier, and other tools that map fields one to one. The record is the raw JSON body; the model id is a query parameter.
Request
POST https://api.ax1om.ai/v1/webhooks/scoreAuthorize with your API key. Keys are minted in the app and the format is documented on authentication.
Parameters
| Name | In | Type | Required |
|---|---|---|---|
model_id | query | string | Yes |
authorization | header | string | No |
X-API-Key | header | string | null | No |
The record is the raw JSON body: a flat object of your field values. The artifact declares no body schema for this operation, so there is no field list to generate, and none is invented here.
Response
| Status | Body | When |
|---|---|---|
200 | V1WebhookResponse | Record scored. |
400 | V1Error | Bad request (code: bad_request). |
401 | V1Error | Missing or invalid API key (code: invalid_api_key). |
402 | V1Error | The org's trial ended and it has no active subscription, so it is in read-only mode (code: expired_read_only). Read access to existing scores, models, and factors is unaffected; API scoring resumes on upgrade. Unlike a 429 quota, this does not clear at the next billing period, so do not retry on a timer. |
403 | V1Error | Live API is turned off for the score that owns this model (code: api_disabled). Turn Live API on in that score's row under Activate. Retrying will not clear it. |
404 | V1Error | Model not found (code: model_not_found). |
409 | V1Error | Your org's deploy policy is set to block, and this model has not passed its validation gate (code: deploy_blocked). The message names the gate and the override path. Retrying will not clear it: either the model clears its gate as its predictions mature, or an admin lifts the refusal. |
422 | V1Error | Malformed request body (code: bad_request). |
429 | V1Error | Rate limited (code: rate_limited), or monthly scored-record quota exhausted past the backstop, including plans without API scoring (code: quota_exceeded). |
500 | V1Error | Internal error (code: internal_error). |
V1WebhookResponse
Single-record webhook response, flattened for Marketo/Zapier field mapping.
| Field | Type | Always present | Description |
|---|---|---|---|
age_sentinel | string | null | No | Recency age-guard note. Always present (null when in-range) for sentinel-trained models only. |
conversion_likelihood | number (float) | Yes | |
delta | integer | No | score minus previous_score, when a previous score exists. |
percentile | integer | Yes | Approximate percentile for the single record. |
previous_score | integer | No | Present when a prior score exists for record_id. |
record_id | string | No | Echoed crm_id when supplied. |
score | integer | Yes | |
test | boolean | No | Present and true only for test keys. |
tier | "hot" | "warm" | "cold" | Yes | |
top_reason_1 | string | null | No | |
top_reason_2 | string | null | No | |
top_reason_3 | string | null | No |
Example
The same call in three clients. Pick one and the choice follows you across every panel on the documentation that offers it.
curl -X POST "https://api.ax1om.ai/v1/webhooks/score?model_id=mdl_abc123" \ -H "X-API-Key: ax1m_sk_your_key" \ -H "Content-Type: application/json" \ -d '{ "Title": "VP Sales", "Industry": "SaaS", "LeadSource": "Webinar" }'import requests
response = requests.post( "https://api.ax1om.ai/v1/webhooks/score", headers={"X-API-Key": "ax1m_sk_your_key"}, params={ "model_id": "mdl_abc123" }, json={ "Title": "VP Sales", "Industry": "SaaS", "LeadSource": "Webinar" },)response.raise_for_status()print(response.json())const response = await fetch("https://api.ax1om.ai/v1/webhooks/score?model_id=mdl_abc123", { method: "POST", headers: { "X-API-Key": "ax1m_sk_your_key", "Content-Type": "application/json", }, body: JSON.stringify({ "Title": "VP Sales", "Industry": "SaaS", "LeadSource": "Webinar" }),});
if (!response.ok) { const { error } = await response.json(); throw new Error(`${error.code}: ${error.message}`);}
console.log(await response.json());{ "score": 87, "tier": "hot", "percentile": 87, "conversion_likelihood": 0.8732, "top_reason_1": "VP title (2.3x lift)", "top_reason_2": "SaaS industry", "top_reason_3": "Webinar source"}Errors
Every failure returns the /v1 envelope. Branch onerror.code, never on the HTTP status or the message text. The codes below are the ones the contract declares for this operation; the full table with prose for each is on theindex.
| Status | Codes |
|---|---|
400 | bad_request |
401 | invalid_api_key |
402 | expired_read_only |
403 | api_disabled |
404 | model_not_found |
409 | deploy_blocked |
422 | bad_request |
429 | quota_exceeded · rate_limited |
500 | internal_error |
Notes
- ax1om does not deliver outbound webhooks to a url you supply. This is an inbound endpoint: Marketo, Zapier, or your own service posts a record and gets a score back in the response.
- Errors use the same /v1 envelope as every other call. Branch on error.code, never on the status or the message text.