Quickstart
1. Get a key
Create one in the LeadX web app under Settings → API, or mint one over the API if you already hold a key:
curl -X POST https://api.leadx.in/api/key/protected/api \
-H "apikey: $LEADX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"type":"permanent","ipRestriction":"open"}'
The full key is returned once, on creation. Every later read returns only maskedKey (*********** plus the last four characters) — the list endpoint projects key out entirely. Store it in a secret manager at the moment you create it.
2. Call the API
Send the key in the apikey header. There is no Bearer prefix and no Authorization header on this path.
curl https://api.leadx.in/api/key/protected/lead?p=1&n=25 \
-H "apikey: $LEADX_API_KEY"
{
"ok": true,
"success": true,
"message": null,
"data": [ { "_id": "665f...", "stage": "New", "status": "Hot" } ],
"totalCount": 1284,
"n": 25,
"p": 1,
"nextCursor": null,
"cursorPagination": false,
"sortBy": "createdAt",
"sortOrder": "desc"
}
3. Create something
curl -X POST https://api.leadx.in/api/key/protected/lead \
-H "apikey: $LEADX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Ada Lovelace",
"email": "ada@example.com",
"contactNumber": { "countryCode": "91", "number": "9876543210" },
"source": "Website",
"formData": { "stage": "New", "status": "Hot", "priority": "High" }
}'
Base URLs
| Environment | Base URL |
|---|---|
| Production | https://api.leadx.in/api/key/protected |
| Beta | https://beta-api.leadx.in/api/key/protected |
| Local dev | http://localhost:3000/api/key/protected |
:::note Local port
leadx-api ships PORT=3000 in .env.example, but several developer .env files run it on 8000. Check the port your service actually booted on.
:::
Language examples
const LEADX = "https://api.leadx.in/api/key/protected";
const leadx = async (path, init = {}) => {
const res = await fetch(LEADX + path, {
...init,
headers: {
apikey: process.env.LEADX_API_KEY,
"Content-Type": "application/json",
...init.headers,
},
});
const body = await res.json();
if (!res.ok) throw new Error(`${res.status}: ${body.message}`);
return body;
};
const { data, totalCount } = await leadx("/lead?p=1&n=50");
console.log(`${data.length} of ${totalCount} leads`);
import os, requests
BASE = "https://api.leadx.in/api/key/protected"
SESSION = requests.Session()
SESSION.headers.update({"apikey": os.environ["LEADX_API_KEY"]})
res = SESSION.get(f"{BASE}/contact", params={"p": 1, "n": 50})
res.raise_for_status()
body = res.json()
print(body["totalCount"], "contacts")
<?php
$ch = curl_init("https://api.leadx.in/api/key/protected/lead?p=1&n=25");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["apikey: " . getenv("LEADX_API_KEY")],
]);
$body = json_decode(curl_exec($ch), true);
echo $body["totalCount"];
Run a request without leaving the page
Every entry in the reference carries this same request in six
languages — cURL, fetch, axios, dependency-free Node, Python and PHP — filled
in with that endpoint's real path and body fields. Switch between them with the
tabs above each sample, and copy with the button in the corner.
Each one also has a Try it button: paste a key, fill in any path parameters,
and the request goes straight from your browser to the API. The key is held in
sessionStorage and goes nowhere else — it is gone when you close the tab.
:::warning Try it sends real requests
The base URL defaults to production, and the write endpoints really do write.
Change the base URL in the panel before running anything that is not a GET.
:::
Next
- API keys — lifecycle, scope, and the caveats that matter
- Response format — the envelope every endpoint returns
- Postman collection — the same 495 requests, importable