Developer
API reference
Generate pitch packs and meeting briefs programmatically — the same research and writing the web app does, behind one HTTP call.
29.00 EUR / month
Starter — 200 reports a month
Failed reports are not counted against your allowance.
Create an accountAlready have one? Sign in.
Authentication
Every request carries a bearer key. Keys are shown once at creation and stored only as a hash, so a lost key is replaced rather than recovered. Use it server-side only — it spends your quota.
Authorization: Bearer spg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxCreate a report
POST /api/v1/reports — returns 202 immediately. A report takes up to about four minutes to write, so nothing blocks on it: poll the report until it is completed.
curl -X POST https://your-domain/api/v1/reports \
-H "Authorization: Bearer $SPG_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://prospect.com",
"offering": "We sell CRM software to B2B sales teams",
"role": "VP of Sales",
"product": "pitch"
}'
{ "id": "cmsx59w6q0001cb6s01djdgr4", "status": "queued" }| Field | Required | Notes |
|---|---|---|
url | yes | The prospect’s website. Public hosts only. |
offering | yes | What you sell. Vague input is refused with vague_offering rather than guessed at. |
product | no | pitch (default) or brief for a meeting brief. |
role | no | Who you are selling to. |
tone, length, outreach, goal | no | Writing preferences. Sensible defaults apply. |
meetingType, meetingContext | no | Only meaningful when product is brief. |
Fetch a report
GET /api/v1/reports/:id — poll every few seconds. status is one of queued, processing, completed or failed; the last two are terminal. pack is populated only on completed.
{
"id": "cmsx59w6q0001cb6s01djdgr4",
"status": "completed",
"url": "https://prospect.com",
"host": "prospect.com",
"companyName": "Prospect Inc",
"product": "pitch",
"offering": "We sell CRM software to B2B sales teams",
"role": "VP of Sales",
"stage": null,
"failure": null,
"pagesAnalyzed": 8,
"signalsFound": 4,
"analysisMs": 91000,
"createdAt": "2026-08-17T10:00:00.000Z",
"pack": { "companyName": "...", "signals": [], "recommendedPitch": "..." }
}A failed report carries a failure object instead of a pack — for example no_connection when we could not find a credible, evidence-based link between the site and what you sell. We would rather say so than invent one.
Download the deck
GET /api/v1/reports/:id/deck — the prospect-facing slides as a .pptx, once the report is completed.
Retries
Send an Idempotency-Key header and a retry of the same call returns the original report instead of creating — and charging for — a second one. Replays answer 200 with Idempotent-Replay: true and the report’s current status. Keys are remembered for 24 hours and are bound to the request they were first used for: reusing one for a different prospect answers 422 idempotency_key_reuse rather than handing back the earlier report. Maximum 200 characters.
-H "Idempotency-Key: 8f14e45f-ea2b-4b2c-9f0a-1d3c5e7a9b11"Quota
The response to a create call carries your allowance, so you can see one running out without polling anything. Failed reports are not counted against it.
X-Quota-Limit: 200
X-Quota-Remaining: 187
X-Quota-Reset: 2026-09-17T11:16:46.921ZThere is also a short-window burst limit of 20 requests per minute per key, separate from the monthly quota. Exceeding it answers 429 with Retry-After, as does spending the monthly allowance.
Errors
Every error carries a stable code to branch on. The error string is prose for a human reading a log and may be reworded.
{ "error": "Monthly report quota reached (200).", "code": "quota_exceeded" }| Code | HTTP | Meaning |
|---|---|---|
invalid_api_key | 401 | Missing, malformed, unknown or revoked key. |
subscription_inactive | 402 | Subscription suspended, canceled or never paid for. |
invalid_request | 400 | The URL or offering could not be read. |
vague_offering | 422 | We cannot tell what you sell — be more specific. |
quota_exceeded | 429 | Monthly report allowance spent. Resets next period. |
cost_cap_exceeded | 429 | Usage ceiling for the period reached. Contact us to raise it. |
rate_limited | 429 | Too many requests in a short window. See Retry-After. |
idempotency_key_reuse | 422 | That Idempotency-Key was already used for a different request. |
not_found | 404 | No such report, or it belongs to another subscription. |
not_ready | 409 | The report has not finished yet. |
service_unavailable | 503 | Report generation is temporarily unavailable. |
Billing
Subscriptions renew by payment link, not automatic debit — card networks require you to approve each charge, so we email a link before the period ends. Miss it and there is a seven-day grace period during which keys keep working; after that they answer 402 until the renewal is paid. Paying restores the same keys, so nothing needs re-issuing. Manage it under Billing.