API REFERENCE · V1

Send a website lead to the pending inbox.

Create a lead with POST /api/v1/leads from your server. Authenticate with the site key, send email and message, and use a stable Idempotency-Key so a retry cannot create a duplicate.

POST /api/v1/leads

Create lead

The key identifies both the site and organization. Content-Type must be application/json and the total request body must be 64 KB or less.

cURL
curl --request POST \
  --url https://api.leadpending.com/api/v1/leads \
  --header "Authorization: Bearer lp_live_<secret>" \
  --header "Content-Type: application/json" \
  --header "Idempotency-Key: contact_018f47f2" \
  --data '{
    "external_id": "contact-form-018f47f2",
    "name": "Jane Doe",
    "email": "[email protected]",
    "company": "Example Inc",
    "subject": "SEO audit",
    "message": "Can you help us with three websites?",
    "page_url": "https://example.org/pricing",
    "locale": "en",
    "metadata": { "utm_source": "google" }
  }'

Fields

FieldTypeRuleDescription
emailstringRequiredLead email address.
messagestringRequiredRequest text, up to 20,000 characters.
external_idstringOptionalStable ID unique inside this site.
name · phone · companystringOptionalContact details shown to the operator.
subjectstringOptionalDefaults to “Inquiry from {site name}”.
page_urlURLOptionalThe page where the request was submitted.
localestringOptionalPreferred reply language, for example en or ru.
metadataobjectOptionalExtra JSON such as UTM or budget range, up to 20 KB.

Make every form submission retry-safe

Send a stable Idempotency-Key for the same browser submission. Repeating the same key and payload returns the original lead with 200. Reusing the key with different content returns 409.

Responses

201 creates a new lead. An idempotent repeat by Idempotency-Key or external_id returns the same resource with 200.

201 Created
HTTP/1.1 201 Created
Content-Type: application/json

{
  "data": {
    "id": "0198…",
    "status": "pending",
    "created_at": "2026-08-02T12:00:00Z"
  }
}

Error contract

HTTPCodeAction
400VALIDATION_FAILEDA field, payload size, or JSON value is invalid.
401INVALID_API_KEYThe site key is missing, revoked, or does not match an active site.
409IDEMPOTENCY_CONFLICTThe idempotency key was already used for a different payload.
429RATE_LIMITEDThe key exceeded its configured intake rate.
503SERVICE_UNAVAILABLEIntake is temporarily unavailable; retry with the same key.

Next.js server route

Validate the form and Turnstile before this call. Return success to the browser only after LeadPending responds with 200 or 201.

app/api/contact/route.ts
import { NextResponse } from 'next/server'

export async function POST(request: Request) {
  const form = await request.json()

  // Validate fields and Turnstile here first.
  const response = await fetch(
    'https://api.leadpending.com/api/v1/leads',
    {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.LEADPENDING_API_KEY}`,
        'Content-Type': 'application/json',
        'Idempotency-Key': form.submissionId,
      },
      body: JSON.stringify({
        external_id: form.submissionId,
        name: form.name,
        email: form.email,
        message: form.message,
        page_url: form.pageUrl,
      }),
    },
  )

  const payload = await response.json()
  if (response.status !== 200 && response.status !== 201) {
    return NextResponse.json(
      { error: payload?.error?.code ?? 'LEAD_NOT_ACCEPTED' },
      { status: response.status },
    )
  }

  return NextResponse.json({ accepted: true })
}

Production checklist

  1. 01Store LEADPENDING_API_KEY as a server secret.
  2. 02Generate one stable idempotency key per form submission.
  3. 03Log status and error code without logging email or message.
  4. 04Treat only 200 and 201 as accepted.
  5. 05Send a test lead before switching the live form.