LeadPanther API Agency Mode#

Agency mode lets an approved agency API key work with client accounts through nested client routes.

Base URL:

https://app.leadpanther.ai/api/v1

LeadPanther API v1 is available to accounts with active billing. API keys are bearer tokens. Keep them server-side and never expose them in browser code.

Core Rule#

Agency client work uses /clients/{clientId}/....

Use:

/clients/{clientId}/posts
/clients/{clientId}/posts/{id}/boost
/clients/{clientId}/lead-magnets
/clients/{clientId}/leads
/clients/{clientId}/activity

Do not use direct routes such as /posts, /lead-magnets, /leads, or /activity when the operation is for a client account.

A valid agency API key alone is not enough; the agency must also have an active grant for the target client account.

Find Accessible Clients#

Required scope: clients:read

curl "https://app.leadpanther.ai/api/v1/clients" \
  -H "Authorization: Bearer lp_live_REDACTED"

Example response:

{
  "data": [
    {
      "user_id": "00000000-0000-4000-8000-000000000001",
      "full_name": "Client A",
      "business_name": "Client A Company",
      "account_status": "active",
      "grant": {
        "id": "00000000-0000-4000-8000-000000000006",
        "label": "Client A",
        "status": "active",
        "permissions": ["posts:read", "posts:write"],
        "created_at": "2026-05-25T00:00:00.000Z",
        "updated_at": "2026-05-25T00:00:00.000Z"
      }
    }
  ],
  "pagination": {
    "limit": 1,
    "offset": 0,
    "has_more": false
  },
  "request_id": "req_000000000000000000000001"
}

In API v1, clientId is the client account user_id returned by GET /clients. Do not use account table IDs, API key IDs, key hashes, or private database fields.

Get One Client#

Required scope: clients:read

curl "https://app.leadpanther.ai/api/v1/clients/00000000-0000-4000-8000-000000000001" \
  -H "Authorization: Bearer lp_live_REDACTED"

The response includes the client account summary and, for agency keys, grant visibility when applicable.

Client Posts#

Required scopes:

  • List or retrieve posts: posts:read
  • Create, update, or delete eligible posts: posts:write
  • Read post engagement: analytics:read
curl "https://app.leadpanther.ai/api/v1/clients/00000000-0000-4000-8000-000000000001/posts?limit=10&offset=0" \
  -H "Authorization: Bearer lp_live_REDACTED"

Create a client draft post:

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

Scheduled posts require a future scheduled_at ISO datetime. Publishing posts cannot be mutated.

Modify A Client's Published LinkedIn Post#

First fetch the client post:

curl "https://app.leadpanther.ai/api/v1/clients/00000000-0000-4000-8000-000000000001/posts/00000000-0000-4000-8000-000000000002" \
  -H "Authorization: Bearer lp_live_REDACTED"

Proceed only when data.published_mutation_capabilities.can_edit is true. Copy its opaque etag exactly into X-LeadPanther-Post-ETag:

curl "https://app.leadpanther.ai/api/v1/clients/00000000-0000-4000-8000-000000000001/posts/00000000-0000-4000-8000-000000000002" \
  -X PATCH \
  -H "Authorization: Bearer lp_live_REDACTED" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 00000000-0000-4000-8000-000000000003" \
  -H 'X-LeadPanther-Post-ETag: lp-post-REDACTED' \
  -d '{"text":"Updated client LinkedIn post text."}'

The text update does not add, replace, reorder, or remove attached media.

Delete A Client's Published LinkedIn Post#

Proceed only when data.published_mutation_capabilities.can_delete is true. Require explicit user confirmation, then call:

curl "https://app.leadpanther.ai/api/v1/clients/00000000-0000-4000-8000-000000000001/posts/00000000-0000-4000-8000-000000000002" \
  -X DELETE \
  -H "Authorization: Bearer lp_live_REDACTED" \
  -H "Idempotency-Key: 00000000-0000-4000-8000-000000000004"

This permanently deletes the LinkedIn post, including comments and reactions, and removes its LeadPanther record, tracking, and active automation.

Both operations require posts:write, an active agency-client grant and activation, and a mutation capability returned for the target client. LeadPanther resolves the post under the client account identified by clientId; the agency actor never becomes the post owner.

Reuse an idempotency key only for an exact replay of the same request. On provider_state_refreshed or stale_provider_version, fetch the client post again and require a new review before retrying.

Client Team Boost#

Required scopes:

  • Read a boost plan: pods:read
  • Create or stop a boost plan: pods:write

Team Boost for a client post uses /clients/{clientId}/posts/{id}/boost. The post must belong to the client, must still be scheduled (not yet published), must have a live lead magnet template, and the client must be an active member of the target workspace. The plan records the client as the post author and the agency owner as the requester.

curl "https://app.leadpanther.ai/api/v1/clients/00000000-0000-4000-8000-000000000001/posts/00000000-0000-4000-8000-000000000002/boost" \
  -X POST \
  -H "Authorization: Bearer lp_live_REDACTED" \
  -H "Content-Type: application/json" \
  -d '{
    "workspace_id": "00000000-0000-4000-8000-000000000003",
    "scope": "team",
    "bundle": "full",
    "window_minutes": 15
  }'

Read plan status and progress with GET, and stop a plan (cancels queued actions only; idempotent) with DELETE on the same path. Nested team_boost on client post create and update is also supported and requires pods:write.

Pod company-actor routes, organization refresh, and takedown remain direct-owner only.

Client Lead Magnets#

Required scopes:

  • List or retrieve lead magnets: lead_magnets:read
  • Create, update, or archive lead magnets: lead_magnets:write
  • Read lead magnet analytics: analytics:read
curl "https://app.leadpanther.ai/api/v1/clients/00000000-0000-4000-8000-000000000001/lead-magnets?limit=10&offset=0" \
  -H "Authorization: Bearer lp_live_REDACTED"

Create a client lead magnet:

curl "https://app.leadpanther.ai/api/v1/clients/00000000-0000-4000-8000-000000000001/lead-magnets" \
  -X POST \
  -H "Authorization: Bearer lp_live_REDACTED" \
  -H "Content-Type: application/json" \
  -d '{
    "delivery_mode": "external_link",
    "keyword": "GUIDE",
    "resource_name": "Example Guide",
    "resource_link": "https://example.com/resource.pdf",
    "description": "Short public-safe description.",
    "text_template": "Here is the guide: {{resource_link}}",
    "linked_posts": []
  }'

Hosted content and gated external lead magnets require a hosted_page object. Published hosted content requires non-empty Markdown content. Published gated external content requires a valid external resource URL.

Client magnet defaults#

While operating as a client in Agency Mode, open Lead Magnets → Defaults to manage that client's named presets: private DMs, public comment replies, and one-pathway follow-up sequences. New magnets created for that client start from the presets marked default. Agency viewers can read presets but cannot change them.

The same presets are available to agency API keys at /clients/{clientId}/playbook-presets (list, create, get, update, delete) and the resolved follow-up defaults at GET/PATCH /clients/{clientId}/playbook-defaults. Both require the lead_magnets:read or lead_magnets:write scope and an active grant for that client. See Workflows → Magnet default presets. Lead-magnet create and update payloads still copy rules explicitly; presets are never referenced by a magnet.

curl "https://app.leadpanther.ai/api/v1/clients/00000000-0000-4000-8000-000000000001/playbook-presets?kind=private_dm" \
  -H "Authorization: Bearer lp_live_REDACTED"

Company defaults. In the agency dashboard, client accounts can be grouped into a client company (Inventory → New company, then Move to company on each account). A company has its own default presets, managed on the company's Defaults page. When a managed account has no default of its own for a kind or pathway, the company default applies; GET /clients/{clientId}/playbook-defaults reports it as company_preset in sources. Company presets are dashboard-managed and do not appear in /clients/{clientId}/playbook-presets, which lists only the account's own presets.

Client Media#

Required scope: media:write

Create a signed upload URL:

curl "https://app.leadpanther.ai/api/v1/clients/00000000-0000-4000-8000-000000000001/media/upload-url" \
  -X POST \
  -H "Authorization: Bearer lp_live_REDACTED" \
  -H "Content-Type: application/json" \
  -d '{
    "filename": "example-image.png",
    "content_type": "image/png",
    "file_size": 102400
  }'

Example response:

{
  "data": {
    "upload_url": "https://example.com/redacted-upload-url",
    "token": "REDACTED_UPLOAD_TOKEN",
    "path": "uploads/redacted/example-image.png",
    "public_url": "https://example.com/redacted-public-url",
    "bucket": "content-images",
    "content_type": "image/png"
  },
  "request_id": "req_000000000000000000000002"
}

Allowed content types are image/jpeg, image/png, image/gif, image/webp, and application/pdf. Maximum sizes are 5 MB for images and 20 MB for PDFs. Treat upload_url and token values as short-lived sensitive values.

Client Leads And Activity#

Required scopes:

  • List leads: leads:read
  • List inbound activity: activity:read
curl "https://app.leadpanther.ai/api/v1/clients/00000000-0000-4000-8000-000000000001/leads?limit=10&has_email=true" \
  -H "Authorization: Bearer lp_live_REDACTED"
curl "https://app.leadpanther.ai/api/v1/clients/00000000-0000-4000-8000-000000000001/activity?limit=10&source=comments" \
  -H "Authorization: Bearer lp_live_REDACTED"

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

Pagination#

All list endpoints use limit and offset pagination. Unless otherwise documented, limit defaults to 50 and is capped at 100. For full exports, start at offset=0, keep filters stable, advance by the returned pagination.limit while pagination.has_more is true, and retry the same offset if a page fails.

Client list examples:

/clients/{clientId}/posts?limit=25&offset=0
/clients/{clientId}/lead-magnets?limit=25&offset=0
/clients/{clientId}/leads?limit=25&offset=0
/clients/{clientId}/activity?limit=25&offset=0

Troubleshooting#

If a client route returns 403, check both conditions:

  • The API key has the required endpoint scope.
  • The agency has an active grant for the target client account.

If a route returns 404, verify that the path is documented and that the client identifier came from GET /clients.

Use the response request_id when contacting LeadPanther support about an API call.

Current Limitations#

Agency grant permissions may be returned for visibility. API route authorization is enforced by API key scopes plus active agency-client grant status.

Rate limits are not yet a published contract. Idempotency keys are documented only where explicitly specified, including published post mutations, Fast Response starts, and POST /workspaces/{workspaceId}/social-actions. Webhook endpoints and generated SDKs are planned, not currently available.