LeadPanther API Quickstart#

This guide shows the shortest path from a valid API key to common API v1 calls.

Base URL:

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

LeadPanther API v1 is available to accounts with active billing. API keys can be created and managed from Dashboard Settings -> Developer. Suspended, past-due, canceled, unpaid, and incomplete accounts cannot create or use API keys. API keys are bearer tokens. Keep them server-side and never expose them in browser code.

1. Set Your API Key#

Use a redacted placeholder in scripts and examples:

export LEADPANTHER_API_KEY="lp_live_REDACTED"
export LEADPANTHER_BASE_URL="https://app.leadpanther.ai/api/v1"

2. Check API Metadata#

GET / does not require a scope.

curl "$LEADPANTHER_BASE_URL"

Example response:

{
  "data": {
    "name": "LeadPanther API",
    "version": "v1"
  },
  "request_id": "req_000000000000000000000001"
}

3. Check The Authenticated Subject#

GET /me requires a valid API key.

curl "$LEADPANTHER_BASE_URL/me" \
  -H "Authorization: Bearer $LEADPANTHER_API_KEY"

Example response:

{
  "data": {
    "owner": {
      "user_id": "00000000-0000-4000-8000-000000000001",
      "full_name": "Client A",
      "business_name": "Client A Company",
      "account_status": "active"
    },
    "actor_type": "direct_user",
    "scopes": ["posts:read", "posts:write", "lead_magnets:read"],
    "subject": {
      "user_id": "00000000-0000-4000-8000-000000000001"
    }
  },
  "request_id": "req_000000000000000000000002"
}

4. List Posts#

Direct-user post listing uses GET /posts.

Required scope: posts:read

curl "$LEADPANTHER_BASE_URL/posts?limit=10&offset=0" \
  -H "Authorization: Bearer $LEADPANTHER_API_KEY"

Example response:

{
  "data": [
    {
      "id": "00000000-0000-4000-8000-000000000002",
      "text": "Public-safe example post copy.",
      "status": "draft",
      "scheduled_at": null,
      "metrics": null,
      "theme": null,
      "followups": null
    }
  ],
  "pagination": {
    "limit": 10,
    "offset": 0,
    "has_more": false
  },
  "request_id": "req_000000000000000000000003"
}

All list endpoints use limit and offset pagination. Unless otherwise documented, limit defaults to 50 and is capped at 100. For full exports, keep filters stable, start with offset=0, and continue while the response returns pagination.has_more: true. Advance by the returned pagination.limit each time. If a page fails, retry the same offset and include the response request_id when contacting support.

5. Create A Draft Post#

Required scope: posts:write

curl "$LEADPANTHER_BASE_URL/posts" \
  -X POST \
  -H "Authorization: Bearer $LEADPANTHER_API_KEY" \
  -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": "Internal note for this draft.",
    "followups": null
  }'

Scheduled posts use "status": "scheduled" and require a future scheduled_at ISO datetime.

6. Modify Or Delete A Published Post#

First fetch the post and read its caller-specific mutation capability:

curl "$LEADPANTHER_BASE_URL/posts/00000000-0000-4000-8000-000000000002" \
  -H "Authorization: Bearer $LEADPANTHER_API_KEY"

Proceed only when data.published_mutation_capabilities.can_edit or can_delete is true. For a published text update, copy the returned opaque etag exactly:

curl "$LEADPANTHER_BASE_URL/posts/00000000-0000-4000-8000-000000000002" \
  -X PATCH \
  -H "Authorization: Bearer $LEADPANTHER_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 00000000-0000-4000-8000-000000000003" \
  -H 'X-LeadPanther-Post-ETag: lp-post-REDACTED' \
  -d '{"text":"Updated LinkedIn post text."}'

For a published deletion, require explicit user confirmation and send a different idempotency key:

curl "$LEADPANTHER_BASE_URL/posts/00000000-0000-4000-8000-000000000002" \
  -X DELETE \
  -H "Authorization: Bearer $LEADPANTHER_API_KEY" \
  -H "Idempotency-Key: 00000000-0000-4000-8000-000000000004"

Both calls require posts:write. Attached media remains read-only during text updates. A successful published delete also removes LeadPanther tracking and active automation.

7. Create A Lead Magnet#

Required scope: lead_magnets:write

curl "$LEADPANTHER_BASE_URL/lead-magnets" \
  -X POST \
  -H "Authorization: Bearer $LEADPANTHER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "delivery_mode": "hosted_content",
    "keyword": "GUIDE",
    "resource_name": "Example Guide",
    "description": "Short public-safe description.",
    "text_template": "Here is the guide: {{resource_link}}",
    "linked_posts": [],
    "confirm_missing_magnet_url": false,
    "confirm_legacy_placeholder": false,
    "hosted_page": {
      "title": "Example Guide",
      "markdown_content": "# Example Guide\n\nPublic-safe hosted content.",
      "external_resource_url": null,
      "cta_label": null,
      "cta_url": null,
      "status": "draft"
    }
  }'

Create and update responses return both the saved lead_magnet and a result object:

{
  "data": {
    "lead_magnet": {
      "id": "00000000-0000-4000-8000-000000000003",
      "keyword": "GUIDE",
      "delivery_mode": "hosted_content"
    },
    "result": {
      "status": "saved"
    }
  },
  "request_id": "req_000000000000000000000004"
}

8. Use Agency Client Routes#

If you are posting, reading leads, or managing lead magnets for a client, use the nested route form.

Required scope for listing clients: clients:read

curl "$LEADPANTHER_BASE_URL/clients" \
  -H "Authorization: Bearer $LEADPANTHER_API_KEY"

Then call client-scoped resources with the returned client user_id:

curl "$LEADPANTHER_BASE_URL/clients/00000000-0000-4000-8000-000000000001/posts?limit=10" \
  -H "Authorization: Bearer $LEADPANTHER_API_KEY"

For agency access, use the nested client routes. A valid agency API key alone is not enough; the agency must also have an active grant for the target client account.

To update or delete a client's eligible published post, repeat step 6 with these paths:

PATCH  /clients/{clientId}/posts/{id}
DELETE /clients/{clientId}/posts/{id}

Fetch GET /clients/{clientId}/posts/{id} first and use the mutation capabilities returned for that client subject.

9. Handle Errors#

Example error response:

{
  "error": {
    "code": "forbidden",
    "message": "API key is missing a required scope."
  },
  "request_id": "req_000000000000000000000005"
}

Use the response request_id when contacting LeadPanther support about an API call. If a call returns 403, check both the API key scope and the agency-client grant.

Scope Checklist#

  • Read accessible clients: clients:read
  • Read posts: posts:read
  • Create, update, or delete posts: posts:write
  • Read lead magnets: lead_magnets:read
  • Create, update, or archive lead magnets: lead_magnets:write
  • Create upload URLs or delete media: media:write
  • Read post engagement or lead magnet analytics: analytics:read
  • Read leads: leads:read
  • Read inbound activity: activity:read

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.

Rate limits are not yet a published public contract. Do not build behavior that depends on a specific limit or retry window.