INTEGRATION GUIDE

Landing page API

Create a PG Hero landing page from your own tools: an email sequencer, your CRM, Zapier, Clay, n8n, or Claude. Send a prospect's website and, if you have them, the person and their role. PG Hero researches the company and writes a page for that buyer in your brand, the same way it does in the app, and gives you back a link to put in your email.

Pages made through the API carry your AE's name and booking link, show up in PG Hero like any other page, and send the same view, click and follow-up alerts.

1. Get an API key

An owner or admin creates keys under Settings → Organization → API keys. The key is shown once, so store it somewhere safe, like your tool's secrets. Give each tool its own key and revoke any you stop using. A key works until it's revoked, or until the person who created it leaves your company or stops being an admin, so nobody keeps access after they've gone.

Send the key on every request:

Authorization: Bearer pgh_live_…

If your tool can only set a plain header, X-API-Key: pgh_live_… works too. Check a key with GET /api/v1/me:

curl https://pghero.co.uk/api/v1/me -H "Authorization: Bearer $PGHERO_API_KEY"

{
  "organization": { "id": "…", "name": "Your Company" },
  "key": { "name": "Outreach sequence", "prefix": "pgh_live_ab12" },
  "limits": { "pages_per_24h": 500, "pages_used_24h": 37, "pages_remaining_24h": 463, "review_required": false }
}

2. Create a page

POST /api/v1/pages

curl https://pghero.co.uk/api/v1/pages \
  -H "Authorization: Bearer $PGHERO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "company": { "website": "fernhollow.coffee" },
    "contact": {
      "name": "Jess Moore",
      "email": "jess@fernhollow.coffee",
      "role": "Head of Operations"
    },
    "owner_email": "sam@yourcompany.com",
    "cta_url": "https://cal.com/sam/20min",
    "external_id": "outreach-prospect-48213"
  }'
FieldDescription
company.websiteRequired. The prospect company's website. An account you already have for that domain is reused; otherwise a new one is created and researched.
company.nameOptional. Read from their site when you leave it out.
contactOptional: name, email, role, linkedin_url. Needs a name or an email. The page is written for this person's role. Matched to an existing contact by email, then by name.
buyer_roleOptional. Who to write for when there's no specific person, e.g. "Head of Operations". Matched to a buyer type in your brand, or added as one.
persona_idOptional. A buyer type id from your brand, instead of buyer_role.
owner_emailOptional. The AE who owns the account: their name, photo and booking link go on the page and they get its alerts. Defaults to the account's owner in PG Hero, then to whoever created the key.
cta_urlOptional. Where the page's main button goes, e.g. the AE's booking link. https:, mailto: or tel:.
feature_idsOptional. Limit the page to these features of your product.
layoutOptional. clean, split, showcase, bold or editorial. Chosen from your brand when left out.
reviewOptional, default false. true holds the page until its AE approves it in PG Hero.
external_idOptional, recommended. Your own id for this page, such as the prospect id in your sequencer. Sending the same external_id again returns the existing page (status 200) instead of making a second one, so retries are safe.
titleOptional. The page's name inside PG Hero.

The response comes back straight away with 201 Created and the page's url:

HTTP/1.1 201 Created

{
  "id": "6f0c2d1e-…",
  "object": "page",
  "url": "https://pghero.co.uk/v/fernhollow-coffee-jess-moore-x1k29d0a",
  "status": "writing",
  "review_required": false,
  "title": "Fernhollow Coffee · Jess Moore",
  "headline": null,
  "error": null,
  "company": { "id": "9a1b…", "name": "Fernhollow Coffee", "website": "https://fernhollow.coffee" },
  "contact": { "id": "c2d3…", "name": "Jess Moore", "email": "jess@fernhollow.coffee", "role": "Head of Operations" },
  "owner": { "name": "Sam Carter", "email": "sam@yourcompany.com" },
  "external_id": "outreach-prospect-48213",
  "source": "api",
  "app_url": "https://pghero.co.uk/variant/6f0c2d1e-…",
  "created_at": "2026-09-29T09:14:03+00:00",
  "updated_at": "2026-09-29T09:14:03+00:00"
}

3. Wait for it to be ready

Writing a page usually takes a minute or two. The url works from the start: until the page is written it shows a short holding screen that refreshes itself, so a prospect who clicks early isn't met by an error. Still, send the link once the page is ready.

statusMeaning
writingQueued or being written. The URL shows the holding screen.
awaiting_reviewWritten, and waiting for its AE to approve it in PG Hero. Only when review was asked for.
readyWritten and live. Send the link. Views, clicks and alerts are tracked from now on.
failedCouldn't be written; error says why. Try again with a new external_id, or regenerate it in PG Hero.

Option A: the page.ready webhook

Set an events webhook URL under Settings → Organization → Notifications & integrations. When an API page is ready to send, PG Hero posts:

POST <your events webhook URL>
X-PGHero-Timestamp: 1759137243
X-PGHero-Signature-V2: sha256=<hex hmac over "<timestamp>.<body>">

{
  "event": "page.ready",
  "occurred_at": "2026-09-29T09:15:41+00:00",
  "page": { "id": "6f0c2d1e-…", "url": "https://pghero.co.uk/v/…", "status": "ready", "external_id": "outreach-prospect-48213", … }
}

page.failed is sent the same way. Both are signed like every other event; see verifying the signature. A page held for review fires page.ready when its AE approves it.

Option B: poll

curl https://pghero.co.uk/api/v1/pages/6f0c2d1e-… \
  -H "Authorization: Bearer $PGHERO_API_KEY"

Every 15 to 30 seconds is plenty. To find a page by your own id: GET /api/v1/pages?external_id=….

curl "https://pghero.co.uk/api/v1/pages?external_id=outreach-prospect-48213" \
  -H "Authorization: Bearer $PGHERO_API_KEY"

GET /api/v1/pages on its own lists your company's pages, newest first, including ones made in the app. It takes limit (up to 100) and offset.

Using it with a sequencer

The usual pattern, in Zapier, Make, n8n, Clay or your sequencer's own webhooks:

  1. When a prospect is added to a sequence, call POST /api/v1/pages with their company website, name, role and email, and their id as external_id.
  2. Save the returned url to a custom field on the prospect, such as pghero_page.
  3. Put that field in the email: "I put together a page for Fernhollow: {{pghero_page}}".
  4. Make the first step wait until the page is ready: either trigger it from page.ready, or start the sequence with a delay of five minutes or more.

When the prospect opens it, the AE gets the usual alert, and the events webhook can write the view back to your CRM.

Claude connector

PG Hero is also an MCP server, so Claude can make pages for you: "make a PG Hero page for the Head of Operations at fernhollow.coffee and give me the link." It uses the same API key and the same rules as the REST API. The server is at https://pghero.co.uk/mcp and offers four tools: create_landing_page, get_landing_page, list_landing_pages and get_page_allowance.

Claude Code

claude mcp add --transport http pghero https://pghero.co.uk/mcp \
  --header "Authorization: Bearer pgh_live_…"

Claude Desktop

Add this to claude_desktop_config.json (Settings → Developer → Edit config), then restart Claude:

{
  "mcpServers": {
    "pghero": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://pghero.co.uk/mcp", "--header", "Authorization:${PGHERO_AUTH}"],
      "env": { "PGHERO_AUTH": "Bearer pgh_live_…" }
    }
  }
}

Any other MCP client that can send an Authorization header can connect the same way. A listing in Claude's connector directory, where you'd sign in instead of pasting a key, is on the way.

Limits

  • Pages per day: 500 pages through the API and the Claude connector in any 24 hours, per company. GET /api/v1/me shows what's left. Ask PG Hero if you need more.
  • Requests: 60 page creations and 300 page reads a minute per key.
  • Going over either returns 429. Wait and retry; with an external_id, a retry can never make a duplicate.

Errors

Errors have a stable code and a message you can show a person:

HTTP/1.1 400 Bad Request

{ "error": { "code": "invalid_website", "message": "The company website should look like acme.com." } }
codeHTTPWhat to do
missing_api_key / invalid_api_key401Check the key is sent and hasn’t been revoked.
key_disabled401Its creator is no longer an admin. An admin creates a new key.
organization_inactive403Your PG Hero account is paused. Talk to PG Hero.
api_disabled403The API is switched off for your company. Ask PG Hero to turn it on.
invalid_website400Send a real, public website for the company.
invalid_cta_url400Use an https:, mailto: or tel: link.
unknown_owner400owner_email must be an active PG Hero user in your company.
unknown_persona / unknown_feature404Use ids from your brand in PG Hero.
page_not_found404No page with that id in your company.
brand_not_set_up409Finish your brand in PG Hero first; pages are written from it.
daily_limit / rate_limited429Wait and retry, or ask PG Hero to raise the daily limit.
(validation)422The body didn't match the schema; detail lists each field.

OpenAPI spec

The full spec is at https://pghero.co.uk/api/v1/openapi.json, for importing into Postman, Zapier, n8n or a custom GPT action.

Questions, or need an endpoint that isn't here? Ask your PG Hero contact.