Playbooks API primer for agents
Give a coding agent the minimum complete contract for creating, polling, and consuming a Playbooks job safely.
Use this page with the canonical OpenAPI document. OpenAPI is authoritative for exact schemas; this primer is authoritative for the integration sequence and operational decisions.
Contract at a glance#
- Base URL:
BLACKPEARL_API_BASE_URL, configured for the deployment. - Authentication:
Authorization: Bearer $BLACKPEARL_API_KEYon every/v1request. - Create:
POST /v1/playbooksusing operationcreate_playbook_v1_playbooks_postand schemaPlaybookInput. - Poll:
GET /v1/jobs/{job_id}using operationget_job_v1_jobs__job_id__get. - Create response:
202 Acceptedwith schemaPublicPlaybookJobResponse. - Create retry safety: send
Idempotency-Key; matching retries replay the original response for 24 hours. - Result: when the job succeeds,
resultis schemaPublicPlaybookResult. - Retention:
expires_atis 30 days after creation; store results needed after that time. - Errors: schema
ErrorResponse; branch onerror.code, not HTTP status alone.
Create separate projects and keys for development, staging, and production. Hosted development calls still perform real work and record real usage.
Minimal request#
Set the configured API URL and a server-side project key:
export BLACKPEARL_API_BASE_URL="https://api.blackpearl.com"
export BLACKPEARL_API_KEY="replace-with-your-project-key"
export BLACKPEARL_IDEMPOTENCY_KEY="playbook-$(date +%s)-$$"
curl --fail-with-body --silent --show-error \
--request POST "$BLACKPEARL_API_BASE_URL/v1/playbooks" \
--header "Authorization: Bearer $BLACKPEARL_API_KEY" \
--header "Idempotency-Key: $BLACKPEARL_IDEMPOTENCY_KEY" \
--header "Content-Type: application/json" \
--data '{"target_company_domain":"acme.example"}'Provide at least one of target_company or target_company_domain. A domain is a hostname without a scheme or path. Optional tone values are consultative, direct, and technical; model is currently default. Omit sections for the complete result.
Persist the idempotency key before the first request and the returned id immediately after success. If the connection is lost or a server response is ambiguous, repeat the exact POST with the same key within 24 hours. A matching request returns the original response without creating or billing another job. A changed request returns idempotency_key_reused; idempotency_in_progress means retry the same request and key after a short delay.
Poll every terminal state#
Wait 2 seconds before the first GET, then use exponential backoff with jitter capped at 10 seconds. Apply a caller deadline and retain the job ID so polling can resume later. A client timeout does not cancel server work.
| Status | Terminal | Action |
|---|---|---|
queued | No | Wait and poll again. |
running | No | Optionally show progress, then poll again. |
succeeded | Yes | Validate and consume the typed result. |
failed | Yes | Stop and surface the job error. |
canceled | Yes | Stop; there is no public cancel operation. |
On success, useful first outputs are result.business_summary and the first item in result.sales_angles. Collections are arrays. Research-derived scalar fields can be null; follow PublicPlaybookResult rather than inventing fallback fields.
Errors, retries, and usage#
rate_limit_exceededis transient. Wait at least theRetry-Aftervalue, then retry with bounded backoff and jitter.quota_exceededandbudget_exceededalso use status429, but require a reset or configuration change. Do not automatically retry them.- Authentication, entitlement, and validation codes require the caller to change credentials, project state, access, or input.
- A safe GET may be retried for a documented transient
5xx. Repeat an ambiguous create POST only with its original idempotency key and exact input. - Polling is rate-limited but does not start another billed Playbooks generation. Inspect the completed job's
usageand reconcile project totals throughGET /v1/usage. - A job or candidate read after
expires_atreturns410 job_expired. Create a new job if no client-stored result exists.
Do not assume#
- Do not assume a key prefix creates a sandbox.
- Do not assume a fixed completion-time SLA, fixed request-per-minute limit, or cancellation endpoint.
- Do not assume an idempotency key remains replayable after 24 hours or can be reused with different input.
- Do not wait only for
succeeded; all three terminal states stop polling. - Do not treat every
429or5xxas retryable. - Do not expose a project key in browser or mobile code.
For complete examples, use the Quickstart. For field interpretation and recovery details, use Playbooks, Jobs and resumable polling, Errors and retry decisions, and Limits, budgets, and usage.