The scrub endpoint accepts phone arrays and returns registry verdicts. A separate controlled-pilot endpoint exercises the real-estate owner-resolution contract with synthetic fixtures only. Both use the same bearer-key boundary.
Every request carries an API key in the Authorization header. Keys are created and revoked in the dashboard under API keys — shown once at creation, stored hashed. Treat a key like a credential, because it is one: it can spend credits.
Authorization: Bearer <api key>
Submits one scrub job synchronously. Credits are debited at one flat rate per input row, however many scopes the job runs — the current rate is on the pricing page. Duplicate numbers are deduplicated before any vendor call is made.
POST /api/v1/scrub HTTP/1.1
Host: bastro.ai
Authorization: Bearer <api key>
Content-Type: application/json
{
"phones": [
"+14155550142",
"+12065550117",
"+14155550142"
],
"scopes": [
"litigator",
"dnc",
"relocated"
]
}{
"job_id": "job_01J9ZX4R8QW2",
"row_count": 3,
"unique_count": 2,
"matches": [
{
"phone": "+12065550117",
"scope": "dnc",
"source": "vendor",
"reason": "Federal DNC registration"
}
],
"credits_used": 30
}BASTRO_AUTH="Bearer $BASTRO_API_KEY"
curl -X POST \
https://bastro.ai/api/v1/scrub \
-H "Authorization: $BASTRO_AUTH" \
-H "Content-Type: application/json" \
-d '{
"phones": ["+14155550142"],
"scopes": ["litigator", "dnc"]
}'This controlled-pilot endpoint is pinned to deterministic Bastro-owned fixtures when synthetic execution is enabled. It does not search a real person, and a deployment may reject execution with NOT_ELIGIBLE. Do not submit real-person data expecting live enrichment. No public price, availability, or performance claim applies to this contract.
The endpoint accepts one strict current-property-owner request. Unknown fields are rejected. In addition to bearer authentication, every request requires an idempotency key containing 8–200 letters, numbers, periods, underscores, colons, or dashes. Replaying the same key and canonical request returns the original job instead of creating another one.
POST /api/v1/skip-trace/resolve HTTP/1.1
Host: bastro.ai
Authorization: Bearer <api key>
Idempotency-Key: owner-demo-0001
Content-Type: application/json
{
"purpose_code": "real_estate_owner_outreach",
"target_role": "current_property_owner",
"property": {
"address": {
"line1": "100 Example Way",
"line2": "Suite 200",
"city": "Testville",
"region": "MI",
"postalCode": "48000",
"countryCode": "US"
}
},
"owner_hint": {
"name": "Synthetic Example"
},
"channels": ["phone", "email"],
"max_candidates_per_channel": 3
}{
"request_id": "<job id>",
"status": "MATCH",
"as_of": "<ISO-8601 timestamp>",
"requested_target_role": "current_property_owner",
"synthetic": true,
"replayed": false,
"contacts": [
{
"id": "<synthetic contact id>",
"channel": "phone",
"value": "+12025550100",
"rank": 1,
"evidence_state": "candidate",
"confidence": {
"p_identity": null,
"p_current": null,
"p_reachable": null,
"p_right_party_current": null
},
"synthetic": true
}
],
"policy": {
"one_shot_design_target_ms": 5000,
"current_timeout_scope": "provider_execution_only",
"end_to_end_sla": false
},
"billing": {
"mode": "synthetic_no_charge",
"credits_reserved": 0,
"credits_captured": 0,
"credits_released": 0
},
"warning": "Synthetic fixture output only; no real person was searched."
}Always inspect the response-level and contact-level synthetic flags and the warning. A candidate is not proof of consent, deliverability, or verified right-party identity. The response also includes policy versions, the one-shot design target, credit settlement fields, and measured request latency; those fields describe this execution and do not establish a hard end-to-end SLA, public pricing, or production performance.
curl -X POST https://bastro.ai/api/v1/skip-trace/resolve -H "Authorization: Bearer $BASTRO_API_KEY" -H "Idempotency-Key: owner-demo-0001" -H "Content-Type: application/json" -d '{
"purpose_code": "real_estate_owner_outreach",
"target_role": "current_property_owner",
"property": {
"address": {
"line1": "100 Example Way",
"city": "Testville",
"region": "MI",
"postalCode": "48000",
"countryCode": "US"
}
},
"owner_hint": { "name": "Synthetic Example" },
"channels": ["phone", "email"],
"max_candidates_per_channel": 3
}'The v1 endpoint is limited to 10 requests per minute per key. Batch accordingly — one request with many numbers beats many requests with one. Errors are returned as JSON with a stable machine-readable code.
| Status | Code | Meaning |
|---|---|---|
| 401 | invalid_api_key | Authorization header missing, malformed, or the key has been revoked. No job is created. |
| 402 | insufficient_credits | The wallet cannot cover the job at current rates. No partial scrubs — the job is rejected whole. |
| 429 | rate_limited | More than 10 requests in a minute. Retry after the interval in the Retry-After header. |
The same pipeline backs the dashboard uploader, so a job submitted by API appears in job history with the same verdicts, files, and audit trail as one submitted by hand.