Docs/Public API Reference
All Docs
6 min read

Public API Reference

Parsley's public REST API. Manage webhook subscriptions, verify auth, and receive real-time intent events from chatbot conversations.

Parsley exposes a small public REST API for managing webhook subscriptions and receiving real-time intent events. It is the same surface that powers the Zapier, Pabbly, Make, n8n, and Clay integrations - so anything those platforms can do, your own code can do too.

The model is event-driven: you create webhook subscriptions, Parsley POSTs events to your URL when things happen on your profile, you respond with a 2xx. There are no polling endpoints today.

Base URL

https://www.parsley.id/api/v1

All requests must use HTTPS. HTTP requests are rejected.

Authentication

Parsley uses long-lived API keys with the pk_live_ prefix. Generate one from Hub > API Keys in your dashboard. Keys are shown once at creation - store them in a secret manager.

Send the key on every request via the X-API-Key header:

curl https://www.parsley.id/api/v1/me \
  -H "X-API-Key: pk_live_yourkeyhere"

For tools that prefer the OAuth-style header, Authorization: Bearer pk_live_... is also accepted.

Keys are scoped to the user and organisation that created them. Revoking a key from the UI takes effect on the next request.

Rate limits

100 requests per minute per API key. Exceeding it returns 429 Too Many Requests with these response headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
Retry-After: 60

Webhook deliveries from Parsley to your endpoints are not subject to this limit.

Event access

profile.viewed is available on all plans. The four high-signal events - chatbot.conversation.completed, lead.captured, lead.scored, signal.detected - require a paid plan or credit balance. Pricing is usage-based: 10¢ per AI conversation, no subscription. View pricing.

Anyone can create API keys and webhook subscriptions. A subscription that includes a high-signal event without a credit balance returns 403. The same gate applies at delivery time: events fired while you're out of credits are dropped silently rather than queued.

Endpoints

GET /me

Returns identity info for the authenticated key. Useful as an auth-test endpoint when wiring up a new client.

curl https://www.parsley.id/api/v1/me \
  -H "X-API-Key: pk_live_yourkeyhere"
{
  "userId": "user_abc123",
  "email": "you@yourcompany.com",
  "name": "Your Name",
  "organisation": "Your Company",
  "tier": "business",
  "availableEvents": [
    "profile.viewed",
    "chatbot.conversation.completed",
    "lead.captured",
    "lead.scored",
    "signal.detected"
  ]
}

POST /webhooks

Create a new webhook subscription. The secret field in the response is shown only once - store it for HMAC signature verification.

Body:

{
  "url": "https://hooks.example.com/parsley",
  "events": ["lead.scored", "signal.detected"]
}

Response (201):

{
  "id": "sub_abc123",
  "url": "https://hooks.example.com/parsley",
  "events": ["lead.scored", "signal.detected"],
  "secret": "whsec_a1b2c3...",
  "active": true,
  "createdAt": "2026-05-07T14:30:00Z"
}

GET /webhooks

List all active webhook subscriptions for the authenticated key. The full secret is not returned - only its prefix.

PATCH /webhooks/{subId}

Update a subscription's url, events, or active flag.

{ "active": false }

DELETE /webhooks/{subId}

Permanently delete a subscription.

POST /webhooks/{subId}/test

Send a synthetic event to your URL using the subscription's first registered event type. Use this to verify your endpoint is reachable and your signature verification is correct.

Webhook events

All events share the same envelope:

{
  "id": "evt_abc123",
  "type": "lead.scored",
  "createdAt": "2026-05-07T14:30:00Z",
  "data": { ... }
}

The five event types and their payloads are documented in detail in the Clay setup guide, the Zapier setup guide, and the Pabbly Connect guide. The shapes are identical across every consumer.

EventAccessFires when
profile.viewedAll plansA visitor lands on your profile
chatbot.conversation.completedPaid/creditsA chatbot conversation ends
lead.capturedPaid/creditsA visitor shares contact details
lead.scoredPaid/creditsA lead receives a Hot, Warm, or Cold quality score
signal.detectedPaid/creditsA MEDDIC buying signal is detected during a conversation

lead.scored fires on every conversation turn after scoring. Filter on data.leadEmail != null if you only want enrichable rows.

Signature verification

Every webhook request includes these headers:

X-Parsley-Signature: sha256=<hex hmac>
X-Parsley-Event: lead.scored
X-Parsley-Delivery: evt_abc123
User-Agent: Parsley-Webhooks/1.0

The signature is HMAC-SHA256(rawRequestBody, subscription.secret) hex-encoded. Verify before trusting the payload:

import crypto from "crypto"

function verifyParsley(rawBody: string, header: string, secret: string) {
  const provided = header.replace(/^sha256=/, "")
  const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex")
  return crypto.timingSafeEqual(Buffer.from(provided), Buffer.from(expected))
}

Always compare the signature against the raw request body before any JSON parsing or middleware re-serialisation.

Delivery and retries

  • Each delivery times out after 10 seconds.
  • Non-2xx responses (or timeouts) are retried up to 3 times with exponential backoff: 1s, 5s, 30s.
  • After 3 failures the delivery is marked failed and dropped. Persistent failures will be surfaced in Hub > API Keys in a future release.
  • Deliveries are fire-and-forget from Parsley's side - your endpoint failing never blocks the chatbot or lead pipeline.

To stay reliable: respond 2xx immediately and process the payload asynchronously. Idempotency on your side keyed on id (the event ID) is the safest pattern - we may re-deliver after a transient failure.

Errors

StatusMeaning
200OK
201Created
400Validation error (see details in response)
401Missing, malformed, or revoked API key
403Event requires a paid plan or credit balance
404Subscription not found (or not yours)
429Rate limit exceeded
500Server error - safe to retry

Error responses always have this shape:

{ "error": "Invalid or revoked API key." }

Validation errors include a details object keyed by field name.

Use with Clay

A common pattern: use Clay HTTP columns to enrich a Parsley contact off the back of a webhook event. After your Clay table receives a lead.scored row, an HTTP column can call back into your own systems, or use the data.profileUserId to correlate.

For Clay-side setup (creating the webhook table and writing recipes against the events), see the Clay integration guide. The /api/v1 endpoints documented here are what you'd call from a Clay HTTP column for the rare reverse-direction case.

What's Next


Questions? Contact us or email peter@parsley.id.

Ready to connect your CRM?