Lead Capture Through 10xDotIn
Use lead capture when a 10x-hosted page needs to collect contact details, campaign interest, support requests, or lightweight intake data. Native forms store submissions on the handle, emit lead.captured events, and make the records available through the creator lead list and export APIs.
Prerequisites
- A 10x handle, for example
acme. - A deployed handle site or local HTML preview.
- For review/export: a JWT for a user with
CREATORor higher access on the handle. - Optional: webhook or notification subscriptions if you want downstream systems to receive
lead.captured.
Endpoint Summary
| Job | Method and path | Auth |
|---|---|---|
| Create lead | POST /v2/public/handles/{handle}/leads | None |
| Create image attachment upload | POST /v2/public/handles/{handle}/lead-attachments/uploads | None, browser origin-limited |
| Complete image attachment upload | POST /v2/public/handles/{handle}/lead-attachments/{attachmentId}/complete | None, browser origin-limited |
| List captured leads | GET /v2/handles/{handle}/leads | JWT, CREATOR+ |
| Export captured leads | GET /v2/handles/{handle}/leads/export | JWT, CREATOR+ |
Option A: Add a Native Form to a 10x-Hosted Page
Add data-10x-form to the form. When the page is deployed through 10x site deployment, the platform injects /_assets/sdk/lead-forms-sdk.js with the current handle and API base.
<form
data-10x-form="contact"
data-10x-source="pricing_page"
data-10x-pending="Sending..."
data-10x-success="Thanks. We received your request."
data-10x-error="We could not submit the form. Please try again."
>
<label>
Name
<input name="name" autocomplete="name" />
</label>
<label>
Work email
<input name="email" type="email" autocomplete="email" required />
</label>
<label>
Company
<input name="company" autocomplete="organization" />
</label>
<label>
Message
<textarea name="message"></textarea>
</label>
<input name="ten_x_hp" tabindex="-1" autocomplete="off" hidden />
<button type="submit">Request follow-up</button>
<div data-10x-form-status role="status"></div>
</form>
If you are hand-authoring a page that already runs on the handle public host and deployment normalization is not available, include the SDK before </body>:
Do not add this script to unrelated third-party domains unless the request is proxied through your server. Browser CORS will reject native form payloads outside the configured handle public hosts.
The SDK intercepts the submit event, disables the form while the request is pending, and posts a JSON payload to:
/v2/public/handles/{handle}/leads
The payload created by the SDK looks like this:
{
"form_id": "contact",
"source": "pricing_page",
"fields": {
"name": "Rishabh",
"email": "lead@example.com",
"company": "Acme",
"message": "We want to discuss implementation."
},
"page_url": "https://acme.10x.in/pricing",
"referrer": "https://google.com/"
}
Form Attributes
| Attribute | Required | Purpose |
|---|---|---|
data-10x-form | Yes | Stable form ID. Values are normalized to lowercase letters, numbers, _, and -. |
data-10x-source | No | Source label stored on the lead. Defaults to site_form. |
data-10x-pending | No | Status text while the request is in flight. |
data-10x-success | No | Status text after a successful submission. |
data-10x-error | No | Status text after a failed submission. |
data-10x-reset | No | Set to false to keep field values after success. Defaults to reset. |
Field names are stored under fields. The platform also promotes common fields to top-level lead columns:
| Lead column | Accepted field names |
|---|---|
email | email, email_address, contact_email |
name | name, full_name, fullname |
phone | phone, mobile, phone_number |
company | company, organization, organisation |
service | service, interest, plan |
message | message, notes, comments, comment |
Optional Image Attachments
Native forms can include image file inputs. The SDK creates an upload URL, uploads the file, completes the attachment, and then submits the lead with the finalized attachment IDs.
<form data-10x-form="support" data-10x-source="support_page">
<input name="email" type="email" required />
<textarea name="message"></textarea>
<input name="screenshot" type="file" accept="image/*" />
<button type="submit">Send</button>
</form>
Attachment limits:
| Limit | Value |
|---|---|
| Max attachments per lead | 5 |
| Max image size | 10 MB |
| Supported content types | image/* |
| Upload URL TTL | 15 minutes |
| Attachment record TTL before linked | 30 days |
Option B: Submit From a Server Integration
Server-side integrations can post directly to the public lead endpoint. Do not include an Origin header unless it is a 10x public handle origin.
export TENX_API_BASE="https://ai.10x.in"
export TENX_HANDLE="acme"
curl -sS -X POST "${TENX_API_BASE}/v2/public/handles/${TENX_HANDLE}/leads" \
-H "Content-Type: application/json" \
-d '{
"email": "lead@example.com",
"source": "partner_site",
"metadata": {
"partner": "northline",
"externalLeadId": "ext_12345"
}
}'
Created response:
{
"ok": true,
"deduplicated": false,
"handle": "acme",
"leadId": "lead_1717344000000_a1b2c3d4e5f6",
"createdAt": "2026-06-02T10:00:00.000Z"
}
If a non-native server submission repeats the same email for the same handle within 24 hours, the endpoint returns 200 with deduplicated: true and the existing leadId.
Campaign Attribution
If the page has a fresh 10x context token, include it as ctx in a server-side capture request. The native browser SDK stores source, page URL, referrer, and form fields; signed ctx attribution should be supplied by a server integration or another runtime that posts it as a top-level ctx value.
{
"email": "lead@example.com",
"source": "campaign_landing",
"ctx": "<signed-context-token>"
}
When the context resolves to a campaign, 10x stores campaignId, clickId, slug, country, and device on the lead. For LEAD_CAPTURE campaigns, the lead also counts as a conversion and can trigger campaign email rules.
Review Captured Leads
Use a JWT for a creator/operator/owner on the handle.
export TENX_API_BASE="https://ai.10x.in"
export TENX_JWT="<jwt-token>"
export TENX_HANDLE="acme"
curl -sS "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/leads?source=pricing_page" \
-H "Authorization: Bearer ${TENX_JWT}"
Response shape:
{
"handle": "acme",
"leads": [
{
"leadId": "lead_1717344000000_a1b2c3d4e5f6",
"email": "lead@example.com",
"formId": "contact",
"source": "pricing_page",
"name": "Rishabh",
"company": "Acme",
"message": "We want to discuss implementation.",
"fields": {
"email": "lead@example.com",
"company": "Acme"
},
"createdAt": "2026-06-02T10:00:00.000Z",
"updatedAt": "2026-06-02T10:00:00.000Z"
}
],
"summary": {
"period": "30d",
"total": 1,
"points": [],
"breakdowns": {
"form": [],
"source": [],
"campaign": [],
"country": [],
"device": []
},
"freshness": { "lastUpdatedAt": "2026-06-02T10:00:00.000Z" }
}
}
Supported filters:
| Query parameter | Purpose |
|---|---|
source | Return leads with an exact source match. |
email | Return a single lead email. |
campaignId | Return leads attributed to a campaign. |
Export Leads
JSON is the default export format:
curl -sS "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/leads/export?format=json" \
-H "Authorization: Bearer ${TENX_JWT}"
CSV export:
curl -sS "${TENX_API_BASE}/v2/handles/${TENX_HANDLE}/leads/export?format=csv&source=pricing_page" \
-H "Authorization: Bearer ${TENX_JWT}" \
-o leads.csv
CSV column presets are available with columns=all, columns=standard, columns=table, or columns=contact. The default all preset includes standard columns for email, source, country, device, referrer, campaign, timestamps, form ID, promoted contact fields, page URL, and any custom field names collected across the result set. Verification columns default to verification=auto, which adds status-only verification fields when exported leads contain confirmed verification data or a filtered campaignId uses email verification. Use verification=include to force status and detail fields such as verification ID and reply-from email, or verification=omit to hide all verification fields.
Events and Notifications
Every accepted lead emits:
lead.capturedwebhook event for configured webhook subscribers.lead.capturedowner-alert notification event.- Campaign email triggers when the lead is attached to a campaign.
Use Notifications and Alerting and Webhook Delivery and Failure Handling for downstream delivery setup.
Limits and Validation
| Area | Current behavior |
|---|---|
| Public lead capture rate limit | 25 submissions per source IP per hour |
| Attachment upload rate limit | 20 upload attempts per source IP per hour |
| Required field | email, either top-level or inside fields.email |
| Field count | Up to 50 fields |
| Field key format | Letters, numbers, _, ., :, and -, up to 64 characters |
| Field value size | Up to 2 KB after normalization |
| Browser CORS | POST and OPTIONS; content-type header only |
Troubleshooting
| Error | Meaning | Fix |
|---|---|---|
invalid_email | No valid email was found. | Add a required email, email_address, or contact_email field. |
origin_not_allowed | Browser form submitted from a host outside the handle public domain. | Deploy the page under the handle host or submit through your server. |
rate_limited | Too many submissions or attachment uploads from the same source IP. | Back off and retry later. Add your own bot controls before server proxying public forms. |
invalid_ctx | The signed context token cannot be parsed. | Refresh the tracked click/session and retry with a fresh token. |
attachment_not_ready | The lead references an upload that has not been completed. | Let the SDK finish upload and completion before posting the lead. |
attachment_already_used | The attachment was already linked to a lead. | Create a new upload for each submission. |
Shareable Checklist
- Add
data-10x-formto the HTML form. - Include a required email field.
- Add
data-10x-sourcefor reporting and exports. - Deploy the page under the handle public host.
- Submit one test lead.
- Verify with
GET /v2/handles/{handle}/leads. - Export with
GET /v2/handles/{handle}/leads/export?format=csv.
Updated Jun 19, 2026
