LeadPanther API LLM Guide

Status: initial public guide for current API v1 behavior. Last updated: 2026-05-25.

Purpose

This guide is for LLMs, agents, and code-generation tools that help users call the LeadPanther API. Follow these rules exactly. Do not infer endpoints, hosts, scopes, or account behavior from common SaaS API patterns.

Non-Negotiable Rules

  1. Use only this current API v1 base URL:
https://app.leadpanther.ai/api/v1
  1. Do not use this host as the app API base URL:
https://api.leadpanther.ai/v1
  1. Do not guess endpoint names. Use only documented paths under https://app.leadpanther.ai/api/v1.

  2. If the user says they are posting for a client, use:

/clients/{clientId}/posts

Do not use /posts for agency-client work.

  1. If the user says they are managing lead magnets for a client, use:
/clients/{clientId}/lead-magnets

Do not use /lead-magnets for agency-client work.

  1. If the user says they are reading leads or activity for a client, use:
/clients/{clientId}/leads
/clients/{clientId}/activity

Do not use direct /leads or /activity routes for agency-client work.

  1. If a call returns 403, check both:
  • the API key scope
  • the agency-client grant
  1. Do not use Supabase REST, Supabase storage URLs, service-role keys, key hashes, internal database IDs, or private operational docs unless the user explicitly asks for internal implementation work and has authorization.

  2. Never place API keys in browser code, frontend bundles, mobile apps, public repositories, generated docs, screenshots, or logs.

  3. Treat leads:read and activity:read as sensitive scopes. They can expose personal data, message/comment content, LinkedIn profile URLs, platform identifiers, and intent metadata.

Current API Surface

Use only these current API v1 routes.

TaskDirect-user pathAgency-client pathScope
API metadataGET /api/v1n/anone
Current API subjectGET /api/v1/men/avalid API key
List clientsGET /api/v1/clientsn/aclients:read
Get clientGET /api/v1/clients/{clientId}n/aclients:read
List postsGET /api/v1/postsGET /api/v1/clients/{clientId}/postsposts:read
Create postPOST /api/v1/postsPOST /api/v1/clients/{clientId}/postsposts:write
Get postGET /api/v1/posts/{id}GET /api/v1/clients/{clientId}/posts/{id}posts:read
Update postPATCH /api/v1/posts/{id}PATCH /api/v1/clients/{clientId}/posts/{id}posts:write
Delete postDELETE /api/v1/posts/{id}DELETE /api/v1/clients/{clientId}/posts/{id}posts:write
Get post engagementGET /api/v1/posts/{id}/engagementGET /api/v1/clients/{clientId}/posts/{id}/engagementanalytics:read
List lead magnetsGET /api/v1/lead-magnetsGET /api/v1/clients/{clientId}/lead-magnetslead_magnets:read
Create lead magnetPOST /api/v1/lead-magnetsPOST /api/v1/clients/{clientId}/lead-magnetslead_magnets:write
Get lead magnetGET /api/v1/lead-magnets/{id}GET /api/v1/clients/{clientId}/lead-magnets/{id}lead_magnets:read
Update lead magnetPATCH /api/v1/lead-magnets/{id}PATCH /api/v1/clients/{clientId}/lead-magnets/{id}lead_magnets:write
Archive lead magnetDELETE /api/v1/lead-magnets/{id}DELETE /api/v1/clients/{clientId}/lead-magnets/{id}lead_magnets:write
Lead magnet analyticsGET /api/v1/lead-magnets/{id}/analyticsGET /api/v1/clients/{clientId}/lead-magnets/{id}/analyticsanalytics:read
Create media upload URLPOST /api/v1/media/upload-urlPOST /api/v1/clients/{clientId}/media/upload-urlmedia:write
Delete mediaDELETE /api/v1/mediaDELETE /api/v1/clients/{clientId}/mediamedia:write
List leadsGET /api/v1/leadsGET /api/v1/clients/{clientId}/leadsleads:read
List activityGET /api/v1/activityGET /api/v1/clients/{clientId}/activityactivity:read

When constructing a URL from the table, do not duplicate /api/v1. For example:

https://app.leadpanther.ai/api/v1/me
https://app.leadpanther.ai/api/v1/clients/00000000-0000-4000-8000-000000000001/posts

Unsupported Guessed Routes

Do not generate calls to these routes unless future docs explicitly add them:

/accounts
/users
/lists
/campaigns
/organizations
/team
/workspaces
/lead-magnet-posts
/webhooks

Unsupported guessed endpoints may return 404, method_not_allowed, or other invalid path behavior.

Account Model

Direct-user routes operate on the API key owner's account.

Agency-client routes operate on a target client account and require an active agency-client grant:

/api/v1/clients/{clientId}/...

The public clientId currently refers to the client account user_id returned by GET /clients. Do not expose or request private implementation identifiers such as account table IDs, API key IDs, privileged backend data, key hashes, or production database IDs.

Use placeholder IDs in examples:

00000000-0000-4000-8000-000000000001
00000000-0000-4000-8000-000000000002
00000000-0000-4000-8000-000000000003

Authentication Pattern

Use a server-side bearer token:

curl -sS \
  -H "Authorization: Bearer $LEADPANTHER_API_KEY" \
  "https://app.leadpanther.ai/api/v1/me"

Use environment variables in generated code:

LEADPANTHER_API_KEY=lp_live_REDACTED

Do not hard-code a key. Do not invent a key. Do not ask users to paste real keys into prompts.

Request ID Pattern

For troubleshooting examples, include X-Request-Id:

curl -sS \
  -H "Authorization: Bearer $LEADPANTHER_API_KEY" \
  -H "X-Request-Id: req_example_001" \
  "https://app.leadpanther.ai/api/v1/me"

Tell users to provide the response request_id to LeadPanther support when reporting an API issue.

Response Envelopes

Success responses use:

{
  "data": {},
  "request_id": "req_000000000000000000000000"
}

List responses use:

{
  "data": [],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "has_more": false
  },
  "request_id": "req_000000000000000000000000"
}

Error responses use:

{
  "error": {
    "code": "bad_request",
    "message": "Invalid payload."
  },
  "request_id": "req_000000000000000000000000"
}

Do not assume field-level validation details are available. Current validation errors may be general.

Pagination Rules

All list endpoints use limit and offset unless a specific endpoint documents otherwise. Default limit is generally 50; maximum is generally 100.

Good:

GET /api/v1/leads?limit=50&offset=0

Bad:

GET /api/v1/leads?page=1&page_size=50

Do not invent cursor pagination.

Privacy and Redaction Rules

Use anonymized values in all generated examples:

  • Client A
  • Example Agency
  • 00000000-0000-4000-8000-000000000001
  • 00000000-0000-4000-8000-000000000002
  • 00000000-0000-4000-8000-000000000003
  • person@example.com
  • REDACTED_MESSAGE_CONTENT
  • REDACTED_PLATFORM_MESSAGE_ID
  • REDACTED_SIGNED_UPLOAD_URL
  • REDACTED_UPLOAD_TOKEN

Never include:

  • real customer names
  • real customer emails
  • real API keys
  • real production UUIDs
  • real lead message text
  • real LinkedIn message IDs, chat IDs, or comment IDs
  • service-role keys
  • key hashes
  • Supabase REST examples for public API use

leads:read can return personal data. activity:read can return message/comment content and platform identifiers. Public examples are redacted and do not represent the full sensitivity of production data.

Safe Example: Direct User Lists Posts

curl -sS \
  -H "Authorization: Bearer $LEADPANTHER_API_KEY" \
  "https://app.leadpanther.ai/api/v1/posts?limit=10&offset=0"

Required scope: posts:read.

Safe Example: Agency Lists Client Posts

curl -sS \
  -H "Authorization: Bearer $LEADPANTHER_API_KEY" \
  "https://app.leadpanther.ai/api/v1/clients/00000000-0000-4000-8000-000000000001/posts?limit=10&offset=0"

Required scope: posts:read.

Also required: active agency-client grant for 00000000-0000-4000-8000-000000000001.

Safe Example: Agency Creates Client Post

curl -sS \
  -X POST \
  -H "Authorization: Bearer $LEADPANTHER_API_KEY" \
  -H "Content-Type: application/json" \
  "https://app.leadpanther.ai/api/v1/clients/00000000-0000-4000-8000-000000000001/posts" \
  -d '{
    "text": "Public-safe LinkedIn post copy.",
    "status": "draft",
    "scheduled_at": null,
    "theme_id": null,
    "template_id": null,
    "images": [],
    "document_url": null,
    "notes": "Example internal note."
  }'

Required scope: posts:write.

Safe Example: List Leads With Privacy Warning

curl -sS \
  -H "Authorization: Bearer $LEADPANTHER_API_KEY" \
  "https://app.leadpanther.ai/api/v1/clients/00000000-0000-4000-8000-000000000001/leads?limit=50&offset=0"

Required scope: leads:read.

Warn the user that this response can contain personal data, including names, LinkedIn profile URLs, submitted emails, work emails, personal emails, sources, intent signals, qualification status, and timestamps.

Safe Example: List Activity With Privacy Warning

curl -sS \
  -H "Authorization: Bearer $LEADPANTHER_API_KEY" \
  "https://app.leadpanther.ai/api/v1/clients/00000000-0000-4000-8000-000000000001/activity?limit=50&offset=0"

Required scope: activity:read.

Warn the user that this response can contain message/comment content, author information, LinkedIn profile URLs, source metadata, message IDs, chat IDs, comment IDs, and intent metadata.

Current vs Planned Boundaries

Current:

  • API v1 base URL is https://app.leadpanther.ai/api/v1.
  • API keys are provisioned privately for now.
  • API keys are bearer tokens and must stay server-side.
  • Current list pagination is limit and offset.
  • Agency client work uses /clients/{clientId}/....
  • /lead-magnet-posts is not currently implemented.

Planned or not currently guaranteed:

  • Published rate limits are not yet a public contract.
  • Idempotency keys are planned, not currently guaranteed.
  • Webhook endpoints are planned, not currently available.
  • SDKs are planned or future, not currently available.
  • webhooks:write may appear as a scope, but no public v1 webhook route is currently implemented.
  • OpenAPI and generated SDK contracts may be added later, but do not invent them now.

Troubleshooting Decision Tree

For 401 unauthorized:

  • Check the bearer token header.
  • Check that the key is active.
  • Keep the key server-side.

For 403 forbidden:

  • Check the endpoint's required scope.
  • If agency-client work is involved, check the active agency-client grant.
  • Confirm the route is nested under /clients/{clientId}/....

For 404 not_found:

  • Check the base URL.
  • Check the path against the documented endpoint list.
  • Do not switch to guessed routes.
  • For agency work, verify the client ID through an authorized workflow.

For 400 bad_request:

  • Check JSON syntax.
  • Check required fields.
  • Check query parameters.
  • Check current payload rules for posts, lead magnets, media, leads, or activity.

For 409 conflict:

  • Check resource state. Published or publishing posts have update and delete restrictions.

For 500 internal_error:

  • Retry later if appropriate.
  • Capture the response request_id.
  • Do not expose sensitive request or response data when reporting the issue.