curl -X POST "https://app.lance.so/api/v1/operations/enrichment/550e8400-e29b-41d4-a716-446655440000?field=emails" \
-H "Authorization: Bearer <token>"
const response = await fetch(
"/api/v1/operations/enrichment/550e8400-e29b-41d4-a716-446655440000?field=emails",
{
method: "POST",
headers: {
Authorization: "Bearer <token>",
},
}
);
const enrichment = await response.json();
interface Enrichment {
id: string;
createdAt: string;
updatedAt: string;
entityId: string;
entityType: "person" | "company" | "leadlist";
field: "phones" | "emails";
status: "pending" | "finished" | "failed" | "timeout" | "cancelled";
error: string | null;
dataFound: boolean | null;
createdBy: string;
orgId: string;
globalEnrichmentId: string | null;
creditTransactionId: string | null;
}
const personId = "550e8400-e29b-41d4-a716-446655440000";
const field = "emails";
const response = await fetch(
`/api/v1/operations/enrichment/${personId}?field=${field}`,
{
method: "POST",
headers: {
Authorization: "Bearer <token>",
},
}
);
const enrichment: Enrichment = await response.json();
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z",
"entityId": "550e8400-e29b-41d4-a716-446655440000",
"entityType": "person",
"field": "emails",
"status": "pending",
"error": null,
"dataFound": null,
"createdBy": "user_2abc123def456",
"orgId": "org_xyz789",
"globalEnrichmentId": null,
"creditTransactionId": null
}
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:35:00.000Z",
"entityId": "550e8400-e29b-41d4-a716-446655440000",
"entityType": "person",
"field": "emails",
"status": "finished",
"error": null,
"dataFound": true,
"createdBy": "user_2abc123def456",
"orgId": "org_xyz789",
"globalEnrichmentId": "g1h2i3j4-k5l6-7890-mnop-qr1234567890",
"creditTransactionId": "c1d2e3f4-g5h6-7890-ijkl-mn1234567890"
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Field query parameter is required and must be \"phones\" or \"emails\""
}
}
{
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Insufficient credits for enrichment_email. Required: 1 credits.",
"details": {
"operationType": "enrichment_email",
"count": 1,
"required": 1
}
}
}
Enrichment
Person Enrichment
Trigger and retrieve contact enrichment (phone numbers or emails) for a specific person
POST
/
api
/
v1
/
operations
/
enrichment
/
{personId}
curl -X POST "https://app.lance.so/api/v1/operations/enrichment/550e8400-e29b-41d4-a716-446655440000?field=emails" \
-H "Authorization: Bearer <token>"
const response = await fetch(
"/api/v1/operations/enrichment/550e8400-e29b-41d4-a716-446655440000?field=emails",
{
method: "POST",
headers: {
Authorization: "Bearer <token>",
},
}
);
const enrichment = await response.json();
interface Enrichment {
id: string;
createdAt: string;
updatedAt: string;
entityId: string;
entityType: "person" | "company" | "leadlist";
field: "phones" | "emails";
status: "pending" | "finished" | "failed" | "timeout" | "cancelled";
error: string | null;
dataFound: boolean | null;
createdBy: string;
orgId: string;
globalEnrichmentId: string | null;
creditTransactionId: string | null;
}
const personId = "550e8400-e29b-41d4-a716-446655440000";
const field = "emails";
const response = await fetch(
`/api/v1/operations/enrichment/${personId}?field=${field}`,
{
method: "POST",
headers: {
Authorization: "Bearer <token>",
},
}
);
const enrichment: Enrichment = await response.json();
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z",
"entityId": "550e8400-e29b-41d4-a716-446655440000",
"entityType": "person",
"field": "emails",
"status": "pending",
"error": null,
"dataFound": null,
"createdBy": "user_2abc123def456",
"orgId": "org_xyz789",
"globalEnrichmentId": null,
"creditTransactionId": null
}
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:35:00.000Z",
"entityId": "550e8400-e29b-41d4-a716-446655440000",
"entityType": "person",
"field": "emails",
"status": "finished",
"error": null,
"dataFound": true,
"createdBy": "user_2abc123def456",
"orgId": "org_xyz789",
"globalEnrichmentId": "g1h2i3j4-k5l6-7890-mnop-qr1234567890",
"creditTransactionId": "c1d2e3f4-g5h6-7890-ijkl-mn1234567890"
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Field query parameter is required and must be \"phones\" or \"emails\""
}
}
{
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Insufficient credits for enrichment_email. Required: 1 credits.",
"details": {
"operationType": "enrichment_email",
"count": 1,
"required": 1
}
}
}
This endpoint manages the enrichment process for a person’s contact information. Use the POST method to trigger a new enrichment and the GET method to check the status of an existing enrichment request.
Long-Running Operation
This endpoint supports a maximum execution time of 800 seconds (~13
minutes). Enrichment involves calling multiple external providers which can
take time to process.
Credit Consumption
Triggering enrichment consumes credits from your organization’s balance. Email
enrichment and phone enrichment have different credit costs. Ensure you have
sufficient credits before making requests.
Trigger Enrichment
POST /api/v1/operations/enrichment/{personId}
Triggers the enrichment process for a person’s phone numbers or email
addresses. If a pending or completed enrichment already exists, returns the
existing enrichment without consuming additional credits.
Path Parameters
string
required
The unique identifier (UUID) of the person to enrich. Example:
550e8400-e29b-41d4-a716-446655440000Query Parameters
string
required
The type of contact information to enrich. Allowed values:
phones |
emails - phones - Enrich phone numbers for the person - emails - Enrich
email addresses for the personResponse
string
required
The unique identifier (UUID) of the enrichment record.
string
required
ISO 8601 timestamp of when the enrichment was created.
string
required
ISO 8601 timestamp of when the enrichment was last updated.
string
required
The UUID of the person being enriched (matches the
personId path parameter).string
required
The type of entity being enriched. Always
person for this endpoint.string
required
The field being enriched. Either
phones or emails.string
required
The current status of the enrichment request. Possible values: -
pending- Enrichment is in progress -
finished- Enrichment completed successfully -failed- Enrichment failed due to an error -timeout- Enrichment exceeded the maximum processing time -cancelled- Enrichment was cancelled
string | null
required
Error message if the enrichment failed.
null for successful or pending
enrichments.boolean | null
required
Indicates whether contact data was found during enrichment. -
true - Data
was found and added to the person - false - No data was found - null -
Enrichment is pending or status unknownstring
required
The Clerk user ID of the user who triggered the enrichment.
string
required
The organization ID associated with this enrichment.
string | null
required
Reference to the global enrichment record if data was cached from a previous
enrichment.
string | null
required
Reference to the credit transaction if credits were consumed for this
enrichment.
curl -X POST "https://app.lance.so/api/v1/operations/enrichment/550e8400-e29b-41d4-a716-446655440000?field=emails" \
-H "Authorization: Bearer <token>"
const response = await fetch(
"/api/v1/operations/enrichment/550e8400-e29b-41d4-a716-446655440000?field=emails",
{
method: "POST",
headers: {
Authorization: "Bearer <token>",
},
}
);
const enrichment = await response.json();
interface Enrichment {
id: string;
createdAt: string;
updatedAt: string;
entityId: string;
entityType: "person" | "company" | "leadlist";
field: "phones" | "emails";
status: "pending" | "finished" | "failed" | "timeout" | "cancelled";
error: string | null;
dataFound: boolean | null;
createdBy: string;
orgId: string;
globalEnrichmentId: string | null;
creditTransactionId: string | null;
}
const personId = "550e8400-e29b-41d4-a716-446655440000";
const field = "emails";
const response = await fetch(
`/api/v1/operations/enrichment/${personId}?field=${field}`,
{
method: "POST",
headers: {
Authorization: "Bearer <token>",
},
}
);
const enrichment: Enrichment = await response.json();
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z",
"entityId": "550e8400-e29b-41d4-a716-446655440000",
"entityType": "person",
"field": "emails",
"status": "pending",
"error": null,
"dataFound": null,
"createdBy": "user_2abc123def456",
"orgId": "org_xyz789",
"globalEnrichmentId": null,
"creditTransactionId": null
}
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:35:00.000Z",
"entityId": "550e8400-e29b-41d4-a716-446655440000",
"entityType": "person",
"field": "emails",
"status": "finished",
"error": null,
"dataFound": true,
"createdBy": "user_2abc123def456",
"orgId": "org_xyz789",
"globalEnrichmentId": "g1h2i3j4-k5l6-7890-mnop-qr1234567890",
"creditTransactionId": "c1d2e3f4-g5h6-7890-ijkl-mn1234567890"
}
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Field query parameter is required and must be \"phones\" or \"emails\""
}
}
{
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "Insufficient credits for enrichment_email. Required: 1 credits.",
"details": {
"operationType": "enrichment_email",
"count": 1,
"required": 1
}
}
}
Get Enrichment Status
GET /api/v1/operations/enrichment/{personId}
Retrieves the current status of an enrichment request for a person.
Path Parameters
string
required
The unique identifier (UUID) of the person whose enrichment status to
retrieve. Example:
550e8400-e29b-41d4-a716-446655440000Query Parameters
string
required
The type of contact enrichment to check. Allowed values:
phones |
emailsResponse
Returns the same enrichment object structure as the POST method.curl -X GET "https://app.lance.so/api/v1/operations/enrichment/550e8400-e29b-41d4-a716-446655440000?field=emails" \
-H "Authorization: Bearer <token>"
const response = await fetch(
"/api/v1/operations/enrichment/550e8400-e29b-41d4-a716-446655440000?field=emails",
{
method: "GET",
headers: {
Authorization: "Bearer <token>",
},
}
);
const enrichment = await response.json();
const personId = "550e8400-e29b-41d4-a716-446655440000";
const field = "emails";
const response = await fetch(
`/api/v1/operations/enrichment/${personId}?field=${field}`,
{
method: "GET",
headers: {
Authorization: "Bearer <token>",
},
}
);
const enrichment: Enrichment = await response.json();
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:35:00.000Z",
"entityId": "550e8400-e29b-41d4-a716-446655440000",
"entityType": "person",
"field": "emails",
"status": "finished",
"error": null,
"dataFound": true,
"createdBy": "user_2abc123def456",
"orgId": "org_xyz789",
"globalEnrichmentId": "g1h2i3j4-k5l6-7890-mnop-qr1234567890",
"creditTransactionId": "c1d2e3f4-g5h6-7890-ijkl-mn1234567890"
}
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-15T10:30:00.000Z",
"entityId": "550e8400-e29b-41d4-a716-446655440000",
"entityType": "person",
"field": "phones",
"status": "pending",
"error": null,
"dataFound": null,
"createdBy": "user_2abc123def456",
"orgId": "org_xyz789",
"globalEnrichmentId": null,
"creditTransactionId": null
}
{
"error": {
"code": "NOT_FOUND",
"message": "Enrichment not found"
}
}
Error Codes
| Status Code | Error Code | Description |
|---|---|---|
400 | VALIDATION_ERROR | Missing or invalid personId or field parameter |
401 | UNAUTHORIZED | Missing or invalid authentication token |
402 | INSUFFICIENT_CREDITS | Organization does not have enough credits for the enrichment |
404 | NOT_FOUND | Enrichment not found (GET only) |
500 | INTERNAL_ERROR | Server error during enrichment processing |
Enrichment Behavior
Idempotency
The POST endpoint is idempotent for active enrichments:- If a pending or finished enrichment exists for the same person and field, it returns the existing enrichment without consuming credits
- If a failed, timeout, or cancelled enrichment exists, a new enrichment is created
Asynchronous Processing
Enrichment runs asynchronously after the initial response:- POST immediately returns with a
pendingstatus - The enrichment process runs in the background
- Use GET to poll for completion status
Timeout Handling
Enrichments that remain inpending status beyond the maximum age are automatically marked as timeout when queried via GET.
Notes
- Authentication is required via Clerk (both user and organization must be authenticated)
- Each enrichment consumes credits based on the field type (
enrichment_emailorenrichment_phone) - Enriched data is cached globally to avoid redundant API calls for the same person
- The endpoint reuses existing enrichments to minimize credit consumption