Guard API
Stop bad data before it reaches your application. Guard sits in front of your ingestion pipeline — forms, webhooks, API imports, CRM syncs — validates each record against your schema, repairs the safe issues, and returns a clear per-record decision: pass, repair, review, or reject, each with reasons and confidence.
Endpoint & cost
POST /api/v1/guard
Metering is based on input records: 100 records sent to Guard draws down 100 records. The synchronous maximum is 500 records per request. Requests that fail validation are never charged.
The four decisions
- pass — the record is already valid; no changes needed.
- repair — safe issues were fixed automatically;
dataholds the repaired record andchangesthe audit trail. - review — something is off but not fatal; a human should look.
datais still returned. - reject — a required field is invalid and cannot be safely repaired;
dataisnullandissuesexplains why.
Per-record pipeline
- Check required fields are present.
- Validate each value against its declared type.
- Normalize and safely repair values that can be fixed with confidence.
- Optionally flag likely duplicates and anomalies across the batch.
- Apply your policy and return the decision, repaired data, reasons, and confidence.
Request fields
| Field | Type | Description |
|---|---|---|
| records* | object[] | Incoming records to guard (1-500). Values must be primitives (no nested objects/arrays). |
| schema* | object | The schema each record must satisfy. Each value is a type string ("string") or an object { type, required }. |
| policy.repair_safe_issues | boolean | Repair safe issues automatically. Default true. |
| policy.reject_invalid_required_fields | boolean | Reject records whose required fields are invalid and unrepairable. Default true. |
| policy.reject_low_confidence_repairs | boolean | Reject rather than apply low-confidence repairs. Default false. |
| policy.reject_unknown_fields | boolean | Reject records containing fields not in the schema. Default false. |
| policy.allow_null_optional_fields | boolean | Allow null/empty optional fields. Default true. |
| policy.detect_duplicates | boolean | Flag likely duplicate records for review. Default false. |
| policy.detect_anomalies | boolean | Flag anomalous records for review. Default false. |
| policy.strict | boolean | Only auto-apply high-confidence repairs; send the rest to review. Default false. |
Response
| Field | Type | Description |
|---|---|---|
| results | object[] | One result per input record: record_index, decision, confidence, issues_found, repairs_applied, data, changes, issues. |
| results[].data | object | null | The (possibly repaired) record for pass/repair/review; null for reject. |
| results[].changes | object[] | The audit trail of repairs applied to this record (field, from, to, reason, confidence). |
| results[].issues | object[] | Problems found: invalid fields, missing required fields, low-confidence repairs, duplicates, anomalies. |
| summary | object | Counts: records_received, passed, repaired, review, rejected. |
Policy
Policy controls the balance between automation and safety. The defaults repair safe issues and reject records whose required fields cannot be fixed. Set reject_invalid_required_fields: false to route those to review instead of rejecting them, or reject_low_confidence_repairs: true to refuse anything that would need a low-confidence fix. Turn on detect_duplicates or detect_anomalies to add cross-record review signals.
Errors & limits
400 invalid_request— empty records, a nested/non-primitive value, or an empty schema.400 invalid_request— a schema field declares an unknown type.413 payload_too_large— the body exceeds the size cap or more than 500 records.401 unauthorized/invalid_api_key— missing or invalid key.429 usage_limit_exceeded/rate_limit_exceeded— allowance or burst limit reached.
A record-level reject is a normal 200 result, not an HTTP error. Internal errors return a sanitized 500 internal_error and never leak record contents. See Errors.
Try it live
Pick a scenario or edit the JSON, then send it against the live engine. No API key required.
POST /api/v1/guard// Send the request to see the live response.
Live demo endpoint · no API key needed · rate-limited · not stored · runs the production engine
Example request
POST /api/v1/guard
Authorization: Bearer zap_live_...
Content-Type: application/json
{
"records": [
{ "email": " JOHN@ACME.COM ", "company": "Acme Inc", "revenue": "$1.2M" },
{ "email": "not-an-email", "company": "", "revenue": "1200000" },
{ "email": "jane@globex.com", "company": "Globex", "revenue": "450000" }
],
"schema": {
"email": { "type": "email", "required": true },
"company": { "type": "string", "required": true },
"revenue": { "type": "number" }
},
"policy": { "repair_safe_issues": true, "reject_invalid_required_fields": true }
}Example response
{
"request_id": "req_xxx",
"success": true,
"results": [
{
"record_index": 0,
"decision": "repair",
"confidence": 0.98,
"issues_found": 0,
"repairs_applied": 2,
"data": { "email": "john@acme.com", "company": "Acme Inc", "revenue": 1200000 },
"changes": [
{ "field": "email", "from": " JOHN@ACME.COM ", "to": "john@acme.com", "reason": "email trimmed and lowercased", "confidence": 0.99 },
{ "field": "revenue", "from": "$1.2M", "to": 1200000, "reason": "currency value parsed to a numeric amount", "confidence": 0.97 }
],
"issues": []
},
{
"record_index": 1,
"decision": "reject",
"confidence": 1,
"issues_found": 2,
"repairs_applied": 0,
"data": null,
"changes": [],
"issues": [
{ "field": "email", "issue": "invalid_email", "reason": "\"not-an-email\" is not a valid email for \"email\" and cannot be safely repaired." },
{ "field": "company", "issue": "missing_required_field", "reason": "Required field \"company\" is missing or empty." }
]
},
{
"record_index": 2,
"decision": "pass",
"confidence": 1,
"issues_found": 0,
"repairs_applied": 0,
"data": { "email": "jane@globex.com", "company": "Globex", "revenue": "450000" },
"changes": [],
"issues": []
}
],
"summary": { "records_received": 3, "passed": 1, "repaired": 1, "review": 0, "rejected": 1 },
"usage": { "records_processed": 3, "credits_used": 3, "credits_remaining": 997 }
}Code examples
curl -X POST https://zapinner.com/api/v1/guard \
-H "Authorization: Bearer $ZAPINNER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"records": [
{ "email": " JOHN@ACME.COM ", "company": "Acme Inc", "revenue": "$1.2M" }
],
"schema": {
"email": { "type": "email", "required": true },
"company": { "type": "string", "required": true },
"revenue": { "type": "number" }
},
"policy": { "repair_safe_issues": true, "reject_invalid_required_fields": true }
}'