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

Starter200 reports a month

Failed reports are not counted against your allowance.

Create an account

Already 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_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Create 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" }
FieldRequiredNotes
urlyesThe prospect’s website. Public hosts only.
offeringyesWhat you sell. Vague input is refused with vague_offering rather than guessed at.
productnopitch (default) or brief for a meeting brief.
rolenoWho you are selling to.
tone, length, outreach, goalnoWriting preferences. Sensible defaults apply.
meetingType, meetingContextnoOnly 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.921Z

There 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" }
CodeHTTPMeaning
invalid_api_key401Missing, malformed, unknown or revoked key.
subscription_inactive402Subscription suspended, canceled or never paid for.
invalid_request400The URL or offering could not be read.
vague_offering422We cannot tell what you sell — be more specific.
quota_exceeded429Monthly report allowance spent. Resets next period.
cost_cap_exceeded429Usage ceiling for the period reached. Contact us to raise it.
rate_limited429Too many requests in a short window. See Retry-After.
idempotency_key_reuse422That Idempotency-Key was already used for a different request.
not_found404No such report, or it belongs to another subscription.
not_ready409The report has not finished yet.
service_unavailable503Report 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.