Quickstart
Create an account via Stripe checkout, add your brand, run the pipeline, and see ranked content opportunities — from your terminal in under 10 minutes.
Five steps. No decisions. Copy each command, paste it, move to the next.
By the end you will have a registered brand with ranked content opportunities telling you exactly what to write and why.
Human setting this up in a browser? Skip the checkout curl and start at dashboard.boringmarketing.com. Same Stripe flow, same API key — just with a UI.
Call /auth/checkout with your email and desired tier. The server emails you a Stripe checkout link. Pay, then retrieve your API key from the dashboard.
curl -s -X POST \
https://api.boringmarketing.com/auth/checkout \
-H "Content-Type: application/json" \
-d '{
"email": "you@example.com",
"name": "Your Name",
"tier": "builder"
}'Expected response:
{
"status": "email_sent",
"session_id": "bmc_k7f3...",
"poll_url": "https://api.boringmarketing.com/auth/checkout/bmc_k7f3.../status",
"sent_at": "2026-04-08T18:42:11.123Z"
}Check your inbox. You will receive an email from Boring Marketing with a Stripe checkout link. Click the link, complete payment, then come back to your terminal.
After payment, poll poll_url until the status flips to completed:
# Poll every 5 seconds until payment is confirmed
SESSION_ID="bmc_k7f3..." # from the response above
while true; do
RESP=$(curl -s "https://api.boringmarketing.com/auth/checkout/$SESSION_ID/status")
STATUS=$(echo "$RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['status'])")
echo "Status: $STATUS"
if [ "$STATUS" = "completed" ]; then
echo "$RESP" | python3 -m json.tool
break
fi
sleep 5
doneCompleted response:
{
"status": "completed",
"dashboard_url": "https://dashboard.boringmarketing.com"
}The poll endpoint does not return an API key. To retrieve your key:
- Open the
dashboard_urlin a browser. - Enter the email you used during checkout → you'll receive a magic-link.
- Click the link → land in the dashboard.
- Copy your key from Settings → API Access.
- Export it:
export BM_API_KEY="bm_your_key_here"You can return to the dashboard at any time to view or rotate your key.
Tell the API about your domain. Only two fields required.
curl -s -X POST \
https://api.boringmarketing.com/brands \
-H "Content-Type: application/json" \
-H "X-API-Key: $BM_API_KEY" \
-d '{
"domain": "yourdomain.com",
"name": "Your Brand"
}'Expected response (201 Created):
{
"id": "ea502f67-338b-47e4-a245-5c4eea8bd8d2",
"domain": "yourdomain.com",
"name": "Your Brand",
"state": "new"
}If the domain is already registered on your account, the response will include "existing": true. Export the brand ID for the next steps:
export BRAND_ID="ea502f67-338b-47e4-a245-5c4eea8bd8d2"This single call triggers the entire intelligence pipeline: competitor discovery, brand enrichment, keyword universe, evidence collection, and leverage scoring.
curl -s -X POST \
https://api.boringmarketing.com/brands/$BRAND_ID/analyze \
-H "X-API-Key: $BM_API_KEY"Expected response (202 Accepted):
{
"run_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "queued"
}Export the run ID:
export RUN_ID="a1b2c3d4-e5f6-7890-abcd-ef1234567890"The full pipeline takes 15-30 minutes. Poll the run status to watch it progress. Stage progress is exposed under meta.current_stage, not at the top level.
# Poll every 15 seconds
while true; do
RESULT=$(curl -s \
-H "X-API-Key: $BM_API_KEY" \
"https://api.boringmarketing.com/brands/$BRAND_ID/runs/$RUN_ID")
STATUS=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin)['status'])")
STAGE=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('meta',{}).get('current_stage',''))")
DETAIL=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin).get('meta',{}).get('stage_detail',''))")
echo "[$STATUS] $STAGE — $DETAIL"
[ "$STATUS" = "done" ] || [ "$STATUS" = "failed" ] && break
sleep 15
doneYou will see stages progress through these six values:
[running] brand_enrichment — crawling brand site + extracting identity
[running] competitor_discovery — finding competitors via Tavily
[running] family_discovery — building keyword universe
[running] evidence_collection — analyzing SERPs per family
[running] leverage_scoring — cross-referencing brand gaps with opportunities
[running] queue_building — assembling ranked action queue
[done]
While the pipeline runs, this is a good time to read the Pipeline Overview to understand what each stage does.
Once the run completes, fetch your ranked content opportunities.
curl -s \
-H "X-API-Key: $BM_API_KEY" \
"https://api.boringmarketing.com/brands/$BRAND_ID/opportunities" \
| python3 -m json.toolExample response:
{
"brand_id": "ea502f67-338b-47e4-a245-5c4eea8bd8d2",
"total": 42,
"opportunities": [
{
"id": "opp-uuid-1",
"family": "Marketing Automation",
"play": "AI Marketing Tools Comparison Guide",
"summary": "No ranking content for high-intent 'ai marketing tools' cluster",
"keywords": ["ai marketing tools", "best ai marketing software", "ai content marketing"],
"priority": 0.92,
"immediacy": 0.85,
"ceiling": 0.78,
"total_volume": 45000,
"recommended_format": "comparison_post"
}
]
}You now have a ranked list of content opportunities, each with a priority score, target keywords, and a recommended format. The API told you exactly what to write and why.
What just happened
In five steps, the API:
- Discovered competitors in your space automatically
- Built a keyword universe grouped into topic families
- Collected evidence from SERPs, AI Overviews, and LLM citations for each family
- Synthesized opportunities — scored by immediacy (how easy to win) and ceiling (how big the prize)
- Built an action queue — ranked by priority, ready for brief generation
What's next
Troubleshooting
Your X-API-Key header is missing or malformed. Make sure you exported it:
export BM_API_KEY="bm_your_key_here"The key must start with bm_.
You have hit the daily call limit for your tier. Upgrade via the billing portal:
curl -s -X POST \
https://api.boringmarketing.com/auth/billing-portal \
-H "X-API-Key: $BM_API_KEY"Or sign into the dashboard to change plans.
A pipeline run is already in progress for this brand. Check the X-Running-Run-Id response header for the existing run ID, then poll that instead.
curl -s \
-H "X-API-Key: $BM_API_KEY" \
"https://api.boringmarketing.com/brands/$BRAND_ID/runs"The full pipeline takes 15-30 minutes depending on your keyword universe size. Check meta.current_stage and meta.stage_started_at in the run status — if the stage has been running for more than ~15 minutes, the run may be stuck. Cancel it with POST /brands/{brand_id}/runs/{run_id}/cancel and re-trigger.