Build with agents

ReachPill is API- and MCP-native — everything on this page runs from code, no dashboard required. Hand the whole integration to a Claude or Cursor agent: it can set it up, run the test-first workflow below, and verify the loop end to end on its own, before a human ever touches a live key.

The whole guide as one file, for pasting straight into an agent's context: reachpill-agent-guide.md. Agents that check /llms.txt first will find both this page and the raw guide linked from reachpill.com/llms.txt.

The basics

  • Base URL: https://app.reachpill.com/v1
  • Auth: Authorization: Bearer <api_key> on every request.
  • MCP server: https://app.reachpill.com/mcp (OAuth 2.1, or an mg_live_/mg_test_ key as a bearer token). Every capability below is also an MCP tool — prefer MCP when operating as an agent.
  • OpenAPI spec: https://app.reachpill.com/openapi.yaml

The golden rule: build and test with a test key first

Test keys are free, instant, and deterministic — no credits, no real posts. Only swap to a live key once the loop works end to end.

The test-first workflow

  1. Get a test key

    One-time, by a human: mint an mg_test_ key in Settings → Billing → API keys.

  2. Derive the brand

    Point brand-derivation at the product's own site instead of hand-authoring a brand kit.

  3. Dry-run an image

    See the grounded prompt, references and cost estimate — spend nothing.

  4. Generate for real, free

    The same call, without dry_run: an instant deterministic placeholder, zero credits.

  5. Publish to a sandbox channel

    No OAuth: schedule a post to a simulated connection and watch it reach published.

  6. Wire up release autopilot

    Announce a release and get on-brand posts and a blog post automatically.

  7. Go live

    Swap mg_test_ for mg_live_, connect real channels, drop dry_run. Everything else is identical.

0. Get keys (the human does this once)

Ask the user to create two API keys in ReachPill → Settings → Billing → API keys:

  • a test key (mg_test_…) — mint it with the "test" toggle,
  • a live key (mg_live_…) for production.

Test keys are the whole point of a friction-free setup: a mg_test_ key runs generations against instant deterministic placeholders and publishes to a simulated channel — free, no side effects.

1. Define the brand (from a URL, not by hand)

# Kick off derivation from the product's own site.
curl -s https://app.reachpill.com/v1/brand-derivation \
  -H "Authorization: Bearer $RP_TEST_KEY" -H "Content-Type: application/json" \
  -d '{"url":"https://theproduct.com"}'
# → { "id": "...", "status": "pending" }

# Poll until completed.
curl -s https://app.reachpill.com/v1/brand-derivation/latest \
  -H "Authorization: Bearer $RP_TEST_KEY"
# → status: completed, plus voice, palette, imagery_style, logo candidates

MCP: derive_brand({url})get_brand_derivation({}).

Then save what you want to keep:

curl -s -X PUT https://app.reachpill.com/console/... /brand-kit   # or MCP:
# update_brand_kit({ imagery_style, color_scheme, fonts, logo:[...] })

update_brand_kit sets the entire visual identity from code — imagery style, hex palette, font directives, up to 4 logo variants, mascot reference images (all URL-based). Note: its array fields (logo, references, terminology, facts) are full-replacement— read-modify-write, don't send a partial.

2. Dry-run an image (see the grounded prompt, spend nothing)

curl -s https://app.reachpill.com/v1/generations \
  -H "Authorization: Bearer $RP_TEST_KEY" -H "Content-Type: application/json" \
  -d '{"type":"image","tier":"standard","prompt":"our launch announcement","brand":true,"dry_run":true}'
# → { "dry_run": true, "resolved_prompt": "...brand DNA folded in...",
#     "reference_image_urls": [...], "brand_mark_composited": true,
#     "estimated_credits": N }

dry_run:true resolves everything — the brand-grounded prompt, the exact references and brand mark, the model, the estimate — and generates nothing. Use it to verify the brand setup and to show the user how their DNA grounds a prompt.

MCP: create_generation({ ..., brand: true, dry_run: true }).

3. Generate for real — free — with the test key

curl -s https://app.reachpill.com/v1/generations \
  -H "Authorization: Bearer $RP_TEST_KEY" -H "Content-Type: application/json" \
  -d '{"type":"image","tier":"standard","prompt":"our launch announcement","brand":true}'
# → { "job_id": "...", "status": "succeeded", "test": true }  (instant placeholder)

With a test key the job completes immediately against a deterministic placeholder image — no provider call, no credits. Poll GET /v1/generations/{job_id} for its output URL (works exactly like a live job).

4. Test the publish loop with a sandbox channel (no OAuth)

# Create a simulated channel — no OAuth, no real account.
curl -s https://app.reachpill.com/v1/social/sandbox-connections \
  -H "Authorization: Bearer $RP_TEST_KEY" -H "Content-Type: application/json" \
  -d '{"platform":"x"}'
# → a connection you can target

# Schedule a post to it → it "publishes" in simulation with a deterministic URL.
curl -s https://app.reachpill.com/v1/social/posts \
  -H "Authorization: Bearer $RP_TEST_KEY" -H "Content-Type: application/json" \
  -d '{"caption":"We just shipped v2!","media":["gen:<job_id>"],
       "targets":[{"connection_id":"<sandbox_conn_id>"}],"schedule":"now"}'

MCP: create_test_channel({platform}), then schedule_social_post(...). Poll get_social_post and watch it reach published — with zero real posting.

5. Wire up release-driven content (the headline use case)

Make every product release become on-brand posts automatically:

# Configure autopilot for a repo.
curl -s https://app.reachpill.com/v1/release-sources \
  -H "Authorization: Bearer $RP_LIVE_KEY" -H "Content-Type: application/json" \
  -d '{"repo_full_name":"acme/app","review_mode":"auto_publish",
       "platform_targets":[{"platform":"x"},{"platform":"linkedin"}],"produce_blog":true}'

Then either drop a GitHub Action into the repo that POSTs releases (you hold no GitHub access), poll the public releases feed, or install the read-only GitHub App. Or announce directly:

# MCP: announce_release({ repo_full_name, tag, title, body_markdown })
curl -s https://app.reachpill.com/v1/release-events \
  -H "Authorization: Bearer $RP_LIVE_KEY" -H "Content-Type: application/json" \
  -d '{"repo_full_name":"acme/app","tag":"v2.0.0","title":"v2","body_markdown":"...notes..."}'

The first release always waits for a human review; from the second on it's hands-off. Content leads with what changed vs. the previous version, and won't re-announce what already shipped.

GitHub Action snippet (drop in .github/workflows/reachpill.yml):

on: { release: { types: [published] } }
jobs:
  announce:
    runs-on: ubuntu-latest
    steps:
      - run: |
          curl -sf https://app.reachpill.com/v1/release-events \
            -H "Authorization: Bearer ${{ secrets.REACHPILL_KEY }}" \
            -H "Content-Type: application/json" \
            -d "$(jq -n --arg repo '${{ github.repository }}' \
                        --arg tag '${{ github.event.release.tag_name }}' \
                        --arg title '${{ github.event.release.name }}' \
                        --arg body '${{ github.event.release.body }}' \
                 '{repo_full_name:$repo,tag:$tag,title:$title,body_markdown:$body}')"

6. Go live

When the sandbox loop works: switch mg_test_mg_live_, have the user connect real channels (social OAuth, or a blog destination: GitHub repo / webhook / HubSpot), and drop dry_run. Everything else is identical.

Full MCP tool set

  • Brand: get_brand_kit, update_brand_kit, derive_brand, get_brand_derivation, get_project, update_project.
  • Generate: create_generation (supports brand, dry_run), create_composition, create_carousel, estimate_cost, list_models, get_generation.
  • Publish: schedule_social_post, update_social_post, list_social_posts, create_test_channel, create_blog_post, generate_blog_post, publish_blog_post.
  • Releases: create_release_source, list_release_sources, announce_release.
  • Campaigns: create_campaign, plan_campaign_arc, preview_campaign, list_campaign_occurrences, approve_occurrence.
  • Account: get_balance, get_usage_summary, get_spend_breakdown.
Next: Brand DNA