Playbooks API
Account intelligence for GTM engineers. Enrich any company with initiative-level signals, technology context, pressure points, and strategic gaps — sourced from job postings, team profiles, and public filings.
Playbooks goes beyond standard firmographic enrichment. Instead of flat data fields, you get structured intelligence about what a company is actively building, where their operational pressure is, and what initiatives they haven’t started yet. Each signal includes confidence levels, evidence sources, and explicit caveats about what the data does and doesn’t tell you.
https://api.playbooks.uk
Authentication
Authenticate by including your API key in the Authorization header of every request. Keys are prefixed with pb_ for easy identification.
curl https://api.playbooks.uk/v1/enrich \
-H "Authorization: Bearer pb_your_api_key" \
-H "Content-Type: application/json" \
-d '{"linkedin_url": "https://www.linkedin.com/company/example"}'
Your API key carries access privileges — keep it secure. Don’t share it in client-side code, public repositories, or URLs.
Rate limits
Rate limits are applied per API key. Current limits are included in response headers.
| Limit | Default | Header |
|---|---|---|
Per day | 100 requests | X-RateLimit-Remaining-Daily |
Per minute | 10 requests | X-RateLimit-Remaining-Minute |
Need higher limits? Contact us to discuss volume pricing.
Errors
Playbooks uses conventional HTTP status codes. All errors return a JSON body with error and message fields.
| Code | Meaning |
|---|---|
| 200 | Enrichment succeeded |
| 202 | Enrichment accepted — processing asynchronously |
| 400 | Bad request — missing or invalid parameters |
| 401 | No API key provided |
| 403 | Invalid API key |
| 429 | Rate limit exceeded |
| 502 | Enrichment pipeline error — retry the request |
// Error response format
{
"error": "invalid_linkedin_url",
"message": "Provide a valid LinkedIn company page URL.",
"example": "https://www.linkedin.com/company/general-dynamics"
}
Submit enrichment
POST /v1/enrich
Submit a company for enrichment. Returns a job ID immediately. Processing takes 3–5 minutes.
callback_url to receive results automatically.
Request body
| Parameter | Type | Description | |
|---|---|---|---|
linkedin_url | string | Required | LinkedIn company page URL |
callback_url | string | Optional | URL to receive results via webhook when processing completes. Results are POSTed as JSON. |
Example request
curl -X POST https://api.playbooks.uk/v1/enrich \
-H "Authorization: Bearer pb_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"linkedin_url": "https://www.linkedin.com/company/general-dynamics-mission-systems",
"callback_url": "https://your-app.com/webhook/playbooks"
}'
Response (202 Accepted)
{
"success": true,
"job_id": "job_a1b2c3d4e5f6...",
"status": "processing",
"linkedin_url": "https://www.linkedin.com/company/general-dynamics-mission-systems",
"message": "Enrichment started. Results will be sent to your callback URL when ready.",
"poll_url": "https://api.playbooks.uk/v1/enrich/job_a1b2c3d4e5f6..."
}
Callback delivery
If you provide a callback_url, Playbooks will POST the results to your URL when processing completes. The payload includes the full enrichment data, status, and metadata.
// Callback payload delivered to your URL
{
"job_id": "job_a1b2c3d4e5f6...",
"status": "success",
"message": "Enrichment completed successfully for https://...",
"linkedin_url": "https://www.linkedin.com/company/general-dynamics-mission-systems",
"created_at": "2026-03-04T14:32:00.000Z",
"completed_at": "2026-03-04T14:36:42.000Z",
"data": {
"tooling_in_context": { /* ... */ },
"current_state": { /* ... */ },
"initiatives": { /* ... */ }
}
}
Check enrichment status
GET /v1/enrich/{job_id}
Check the status of an enrichment job and retrieve results when complete.
Enrichment statuses
| Status | Meaning | Billable |
|---|---|---|
processing | Still running. Poll again in 30–60 seconds. | No |
success | Full intelligence report generated. | Yes |
insufficient_data | Completed but limited public data available. Partial results may be included. | Yes |
bad_url | LinkedIn URL could not be resolved to a valid company page. | No |
failed | Processing error. Retry the request. | No |
Example: Poll until complete
curl https://api.playbooks.uk/v1/enrich/job_a1b2c3d4e5f6... \
-H "Authorization: Bearer pb_your_api_key"
Response (still processing)
{
"job_id": "job_a1b2c3d4e5f6...",
"status": "processing",
"linkedin_url": "https://www.linkedin.com/company/general-dynamics-mission-systems",
"message": "Still processing. Try again in 30-60 seconds."
}
Response (completed)
{
"job_id": "job_a1b2c3d4e5f6...",
"status": "success",
"message": "Enrichment completed successfully for https://...",
"linkedin_url": "https://www.linkedin.com/company/general-dynamics-mission-systems",
"created_at": "2026-03-04T14:32:00.000Z",
"completed_at": "2026-03-04T14:36:42.000Z",
"data": {
"tooling_in_context": { /* ... */ },
"current_state": { /* ... */ },
"initiatives": { /* ... */ }
}
}
Response (bad URL)
{
"job_id": "job_a1b2c3d4e5f6...",
"status": "bad_url",
"message": "The LinkedIn URL provided could not be resolved to a valid company page. Please check the URL and resubmit.",
"linkedin_url": "https://www.linkedin.com/company/invalid-company"
}
Batch enrich
POST /v1/enrich/batch
Enrich up to 25 accounts in a single request. Each account is processed asynchronously and returns a job ID.
Request body
| Parameter | Type | Description | |
|---|---|---|---|
accounts | array | Required | Array of objects, each with a linkedin_url field. Max 25. |
callback_url | string | Optional | URL to receive results for each account as they complete. |
Example request
curl -X POST https://api.playbooks.uk/v1/enrich/batch \
-H "Authorization: Bearer pb_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"callback_url": "https://your-app.com/webhook/playbooks",
"accounts": [
{ "linkedin_url": "https://www.linkedin.com/company/ford-motor-company" },
{ "linkedin_url": "https://www.linkedin.com/company/verizon" },
{ "linkedin_url": "https://www.linkedin.com/company/boston-scientific" }
]
}'
Response (202 Accepted)
{
"success": true,
"message": "3 enrichment jobs started.",
"jobs": [
{ "linkedin_url": "https://www.linkedin.com/company/ford-motor-company", "job_id": "job_a1b2...", "status": "processing" },
{ "linkedin_url": "https://www.linkedin.com/company/verizon", "job_id": "job_c3d4...", "status": "processing" },
{ "linkedin_url": "https://www.linkedin.com/company/boston-scientific", "job_id": "job_e5f6...", "status": "processing" }
]
}
List jobs
GET /v1/jobs
List your most recent enrichment jobs (up to 50).
curl https://api.playbooks.uk/v1/jobs \
-H "Authorization: Bearer pb_your_api_key"
{
"jobs": [
{
"job_id": "job_a1b2c3d4e5f6...",
"status": "completed",
"linkedin_url": "https://www.linkedin.com/company/ford-motor-company",
"created_at": "2026-03-04T14:32:00.000Z",
"completed_at": "2026-03-04T14:36:42.000Z"
}
]
}
Usage stats
GET /v1/usage
View your current rate limits, credit usage, and recent requests.
curl https://api.playbooks.uk/v1/usage \
-H "Authorization: Bearer pb_your_api_key"
{
"customer": "Acme Corp",
"rate_limits": {
"today": {
"requests": 12,
"limit": 100,
"remaining": 88
}
},
"credits": {
"current_month": "2026-03",
"usage": {
"total": 47,
"success": 42,
"insufficient_data": 5
},
"history": [],
"persistent": true
},
"recentRequests": [ /* last 20 requests */ ]
}
Only success and insufficient_data statuses count as billable credits. failed and bad_url statuses are not billed.
Response schema
Every enrichment returns three intelligence layers, each designed for a specific question a GTM engineer needs answered.
tooling_in_context
What technologies and platforms are confirmed or indicated at this company. Each entry includes a confidence level and evidence sources.
| Field | Type | Description |
|---|---|---|
technology | string | Technology or platform name |
usageType | enum | confirmed_usage or required_expertise |
confidence | enum | high, medium, or low |
notes | string | Context on what the evidence does and doesn’t tell you |
evidenceUrls | array | Source URLs supporting this finding |
relationshipToTopic | string | How this technology relates to the topic lens |
current_state
Operational reality — pressure points, org signals, and critically, uncertainties and gaps. The gaps are often more valuable for outreach than the confirmed findings.
| Field | Type | Description |
|---|---|---|
environmentOverview | string | Narrative summary of the technology environment |
pressurePoints | array | Operational pressures and pain indicators with confidence |
organizationalSignals | array | Team structure, operating model, and scale signals |
operationalCharacteristics | array | How they operate — support models, deployment patterns |
uncertaintiesAndGaps | array | What we don’t know — and why that matters for your outreach |
initiatives
What they’re actively building toward and what they haven’t started. Includes initiative classification, evidence, key uncertainties, and explicit non-findings.
| Field | Type | Description |
|---|---|---|
initiatives[] | array | Active and emerging initiatives |
.initiative | string | Initiative name |
.initiativeType | enum | platform_build, capability_building, governance |
.scope | enum | org-wide, divisional, team-level |
.confidence | enum | high, medium, low |
.primaryEvidence | array | Source evidence with URLs and reasoning |
.keyUncertainties | array | What’s still unclear — conversation hooks |
explicitNonFindings | array | Things we looked for and did not find evidence of |
futureStateSummary | string | Narrative overview of where the company is heading |
Clay integration
Use Playbooks as an enrichment step in any Clay table via the HTTP API integration.
Sending enrichment requests
In your Clay table, add an HTTP API enrichment step:
| Setting | Value |
|---|---|
| Method | POST |
| URL | https://api.playbooks.uk/v1/enrich |
| Headers | Authorization: Bearer pb_your_api_keyContent-Type: application/json |
| Body | {"linkedin_url": "{{linkedin_company_url}}", "callback_url": "https://api.clay.com/v3/sources/webhook/your-webhook-id"} |
Receiving results
Create a second Clay table with a webhook source. Set the callback_url in your enrichment request to your Clay webhook URL. Results arrive automatically when processing completes — no polling needed.
Useful field mappings
| Clay column | JSON path |
|---|---|
| Environment Summary | data.current_state.environmentOverview |
| Top Pressure Point | data.current_state.pressurePoints[0].pressure |
| Top Initiative | data.initiatives.initiatives[0].initiative |
| Key Gaps | data.initiatives.explicitNonFindings |
| Future State | data.initiatives.futureStateSummary |
Quickstart
Python
import requests
response = requests.post(
"https://api.playbooks.uk/v1/enrich",
headers={
"Authorization": "Bearer pb_your_api_key",
"Content-Type": "application/json",
},
json={
"linkedin_url": "https://www.linkedin.com/company/ford-motor-company",
"callback_url": "https://your-app.com/webhook",
},
)
job = response.json()
print(f"Job started: {job['job_id']}")
print(f"Poll at: {job['poll_url']}")
# Poll for results
import time
while True:
result = requests.get(
f"https://api.playbooks.uk/v1/enrich/{job['job_id']}",
headers={"Authorization": "Bearer pb_your_api_key"},
).json()
if result["status"] != "processing":
break
time.sleep(30)
# Get the top initiative
top = result["data"]["initiatives"]["initiatives"][0]
print(f"Top initiative: {top['initiative']} ({top['confidence']})")
# Get gaps — your best outreach angles
gaps = result["data"]["initiatives"]["explicitNonFindings"]
for gap in gaps:
print(f"Gap: {gap}")
JavaScript / Node.js
// Submit enrichment
const response = await fetch("https://api.playbooks.uk/v1/enrich", {
method: "POST",
headers: {
"Authorization": "Bearer pb_your_api_key",
"Content-Type": "application/json",
},
body: JSON.stringify({
linkedin_url: "https://www.linkedin.com/company/ford-motor-company",
callback_url: "https://your-app.com/webhook",
}),
});
const job = await response.json();
console.log(`Job started: ${job.job_id}`);
// Poll for results
let result;
do {
await new Promise(r => setTimeout(r, 30000));
const res = await fetch(`https://api.playbooks.uk/v1/enrich/${job.job_id}`, {
headers: { "Authorization": "Bearer pb_your_api_key" },
});
result = await res.json();
} while (result.status === "processing");
// Pressure points — what's hurting them
result.data.current_state.pressurePoints.forEach(p =>
console.log(`${p.pressure} (${p.confidence})`)
);
// Explicit non-findings — your outreach angles
result.data.initiatives.explicitNonFindings.forEach(gap =>
console.log(`Gap: ${gap}`)
);
Need help? Contact us at vish@playbooks.uk for onboarding, custom integrations, or volume pricing.