Create Contact
Creates a new contact in the CRM for a specific funnel.
POST /v1/funnels/{funnelId}/contacts
Either email or phone must be provided. Each is optional on its own, but at least one of the two is required.
Authentication
Requires the x-perspective-api-key header. See Authentication for details.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
funnelId | string | Yes | The ID of the funnel to create the contact in. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Conditional | Contact's email address. Required if phone is not provided. |
phone | string | Conditional | Contact's phone number. Required if email is not provided. |
firstName | string | No | Contact's given name. |
lastName | string | No | Contact's family name. |
status | string | No | Contact lifecycle status. Must be one of the statuses configured for the funnel. |
website | string | No | Contact's website URL. |
birthday | string | No | Contact's birthday (typically an ISO date string). |
address | object | No | Structured address object. All sub-fields are optional. |
address.postalCode | string | No | Postal / ZIP code. |
address.city | string | No | City. |
address.state | string | No | State, province, or region. |
address.country | string | No | Country. |
address.street | string | No | Street line. |
address.houseNumber | string | No | House number. |
skipAutomationTrigger | boolean | No | When false (default), automation workflows configured for the contact's initial status execute on creation. Set to true to bypass automation triggers. |
Read-only fields: meta, utmParams, and properties cannot be set via this endpoint. Use Update Contact Value to write custom properties entries.
Example request body
{
"email": "jane.doe@example.com",
"phone": "+49151234567890",
"firstName": "Jane",
"lastName": "Doe",
"website": "https://janedoe.com",
"birthday": "1990-06-15",
"address": {
"postalCode": "10115",
"city": "Berlin",
"state": "Berlin",
"country": "DE",
"street": "Unter den Linden",
"houseNumber": "1"
},
"skipAutomationTrigger": false
}
Example request
- cURL
- JavaScript
curl -X POST https://api.perspective.co/v1/funnels/fnl_abc123/contacts \
-H "x-perspective-api-key: $PERSPECTIVE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "jane.doe@example.com",
"firstName": "Jane",
"lastName": "Doe"
}'
const funnelId = 'fnl_abc123';
const response = await fetch(
`https://api.perspective.co/v1/funnels/${funnelId}/contacts`,
{
method: 'POST',
headers: {
'x-perspective-api-key': process.env.PERSPECTIVE_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: 'jane.doe@example.com',
firstName: 'Jane',
lastName: 'Doe',
}),
}
);
const { data } = await response.json();
Response
Returns 201 Created with { data: Contact }. See the Contact object for a full description of every field.
Example response
{
"data": {
"id": "cnt_newxyz",
"status": "lead",
"email": "jane.doe@example.com",
"firstName": "Jane",
"lastName": "Doe",
"name": "Jane Doe",
"meta": {
"ps_converted_at": "2025-06-02T10:00:00.000Z",
"ps_source": "external-api"
}
}
}
Errors
See Errors for the full list of status codes and handling guidance.
| Status | Meaning |
|---|---|
400 | Missing both email and phone, invalid email format, or other validation failure. |
401 | Missing or invalid API key. |
403 | Your API key does not have crm:write permission. |
500 | Internal server error. |