Documentation Index Fetch the complete documentation index at: https://docs.tented.ai/llms.txt
Use this file to discover all available pages before exploring further.
Endpoints
POST /v1/contacts
POST /v1/contacts/update
POST /v1/contacts/delete
DELETE /v1/contacts
Use these endpoints to sync CRM contacts from external systems. Each request accepts an items array with up to 25 records.
Contact writes support partial success. Tented processes each item independently and returns accepted or rejected results in request order.
Request Body
Field Type Required Notes itemsarrayYes Between 1 and 25 contacts
Create Item Fields
Field Type Required Notes emailstringConditionally Either email or phone is required phonestringConditionally Either email or phone is required client_item_idstringNo Your own per-item identifier for reconciliation display_namestringNo Maximum 255 characters first_namestringNo Maximum 255 characters last_namestringNo Maximum 255 characters companystringNo Maximum 255 characters job_titlestringNo Maximum 255 characters addressstringNo Maximum 500 characters address2stringNo Maximum 255 characters citystringNo Maximum 255 characters statestringNo Maximum 255 characters countrystringNo Maximum 255 characters zip_codestringNo Maximum 50 characters lead_statusstringNo Maximum 100 characters lifecycle_stagestringNo Maximum 100 characters tented_scorenumber | nullNo Optional contact score unsubscribedbooleanNo Defaults to false when omitted marketing_email_subscribedboolean | nullNo Email subscription state marketing_sms_subscribedboolean | nullNo SMS subscription state
Create Request Example
curl --request POST \
--url https://api.tented.ai/v1/contacts \
--header "Authorization: Bearer $TENTED_API_KEY " \
--header "Content-Type: application/json" \
--data '{
"items": [
{
"client_item_id": "crm-row-001",
"email": "jane@example.com",
"first_name": "Jane",
"last_name": "Doe",
"company": "Acme",
"job_title": "CEO"
},
{
"client_item_id": "crm-row-002",
"phone": "+15551234567",
"display_name": "Sam Rivera"
}
]
}'
Create Response Example
201 Created
{
"status" : "completed" ,
"created_count" : 2 ,
"rejected_count" : 0 ,
"items" : [
{
"index" : 0 ,
"client_item_id" : "crm-row-001" ,
"contact_id" : "11111111-1111-4111-8111-111111111111" ,
"status" : "created" ,
"contact" : {
"contact_id" : "11111111-1111-4111-8111-111111111111" ,
"display_name" : "Jane Doe" ,
"first_name" : "Jane" ,
"last_name" : "Doe" ,
"email" : "jane@example.com" ,
"phone" : null ,
"company" : "Acme" ,
"job_title" : "CEO" ,
"original_source" : "Public API" ,
"created_at" : "2026-04-30T12:00:00.000Z" ,
"updated_at" : "2026-04-30T12:00:00.000Z"
}
},
{
"index" : 1 ,
"client_item_id" : "crm-row-002" ,
"contact_id" : "22222222-2222-4222-8222-222222222222" ,
"status" : "created" ,
"contact" : {
"contact_id" : "22222222-2222-4222-8222-222222222222" ,
"display_name" : "Sam Rivera" ,
"email" : null ,
"phone" : "+15551234567" ,
"original_source" : "Public API" ,
"created_at" : "2026-04-30T12:00:00.000Z" ,
"updated_at" : "2026-04-30T12:00:00.000Z"
}
}
]
}
Tented checks normalized email and phone values before creating a contact. If an item matches an existing contact, that item is rejected with error_code: "conflict".
{
"index" : 0 ,
"client_item_id" : "crm-row-001" ,
"status" : "rejected" ,
"error_code" : "conflict" ,
"message" : "Contact already exists" ,
"existing_contact" : {
"contact_id" : "11111111-1111-4111-8111-111111111111" ,
"display_name" : "Jane Doe" ,
"email" : "jane@example.com" ,
"phone" : null
}
}
Request Body
Field Type Required Notes itemsarrayYes Between 1 and 25 update records
Update Item Fields
Field Type Required Notes contact_iduuidYes Contact to update client_item_idstringNo Your own per-item identifier for reconciliation emailstring | nullNo Set to null to clear, as long as phone remains present phonestring | nullNo Set to null to clear, as long as email remains present display_namestring | nullNo Maximum 255 characters first_namestringNo Maximum 255 characters last_namestringNo Maximum 255 characters email_domainstring | nullNo Usually derived automatically from email companystringNo Maximum 255 characters job_titlestringNo Maximum 255 characters addressstringNo Maximum 500 characters address2stringNo Maximum 255 characters citystringNo Maximum 255 characters statestringNo Maximum 255 characters countrystringNo Maximum 255 characters zip_codestringNo Maximum 50 characters original_sourcestring | nullNo Maximum 255 characters original_source_detailstring | nullNo Maximum 255 characters lead_statusstringNo Maximum 100 characters lifecycle_stagestringNo Maximum 100 characters tented_scorenumber | nullNo Optional contact score unsubscribedbooleanNo Unsubscribe flag marketing_email_subscribedboolean | nullNo Email subscription state marketing_sms_subscribedboolean | nullNo SMS subscription state marketing_email_invalidbooleanNo Email validity flag marketing_sms_invalidbooleanNo SMS validity flag custom_fieldsobjectNo Editable custom fields by API name
A contact must always have at least one valid email or phone. An update that clears both identity fields is rejected for that item.
Update Request Example
curl --request POST \
--url https://api.tented.ai/v1/contacts/update \
--header "Authorization: Bearer $TENTED_API_KEY " \
--header "Content-Type: application/json" \
--data '{
"items": [
{
"client_item_id": "crm-row-001",
"contact_id": "11111111-1111-4111-8111-111111111111",
"company": "Acme Enterprise",
"lead_status": "qualified",
"custom_fields": {
"favorite_color": "Green"
}
}
]
}'
Update Response Example
200 OK
{
"status" : "completed" ,
"updated_count" : 1 ,
"rejected_count" : 0 ,
"items" : [
{
"index" : 0 ,
"client_item_id" : "crm-row-001" ,
"contact_id" : "11111111-1111-4111-8111-111111111111" ,
"status" : "updated" ,
"contact" : {
"contact_id" : "11111111-1111-4111-8111-111111111111" ,
"email" : "jane@example.com" ,
"company" : "Acme Enterprise" ,
"lead_status" : "qualified" ,
"updated_at" : "2026-04-30T12:05:00.000Z"
}
}
]
}
POST /v1/contacts/delete
DELETE /v1/contacts
Use POST /v1/contacts/delete if your HTTP client does not support request bodies on DELETE.
Request Body
Field Type Required Notes itemsarrayYes Between 1 and 25 delete records
Delete Item Fields
Field Type Required Notes contact_iduuidYes Contact to delete client_item_idstringNo Your own per-item identifier for reconciliation
Delete Request Example
curl --request POST \
--url https://api.tented.ai/v1/contacts/delete \
--header "Authorization: Bearer $TENTED_API_KEY " \
--header "Content-Type: application/json" \
--data '{
"items": [
{
"client_item_id": "crm-row-001",
"contact_id": "11111111-1111-4111-8111-111111111111"
}
]
}'
Delete Response Example
200 OK
{
"status" : "completed" ,
"deleted_count" : 1 ,
"rejected_count" : 0 ,
"items" : [
{
"index" : 0 ,
"client_item_id" : "crm-row-001" ,
"contact_id" : "11111111-1111-4111-8111-111111111111" ,
"status" : "deleted"
}
]
}
Every contacts write endpoint returns:
Field Type Notes statusstringAlways completed after the request has been processed created_countnumberPresent on create responses updated_countnumberPresent on update responses deleted_countnumberPresent on delete responses rejected_countnumberNumber of rejected items itemsarrayPer-item results in request order
Rejected items include:
Field Type Notes indexnumberZero-based item index from the request client_item_idstringReturned when supplied contact_iduuidReturned when supplied statusstringrejectederror_codestringbad_request, not_found, conflict, or errormessagestringHuman-readable failure reason existing_contactobjectReturned for duplicate conflicts
Common Item-Level Rejections
Error Code Cause bad_requestNo fields to update bad_requestUpdate would remove both email and phone bad_requestCustom field is missing, inactive, non-editable, or has an invalid value not_foundContact does not exist in the workspace conflictEmail or phone matches another existing contact
Common Request Errors
Status Cause 400 Bad RequestInvalid JSON body 400 Bad RequestRequest body is missing 400 Bad Requestitems is missing, empty, or contains more than 25 records400 Bad RequestA create item has neither email nor phone 400 Bad RequestInvalid email, phone, UUID, or field format 401 UnauthorizedMissing or invalid bearer token
Back to API Overview Review the full Vibe Coding API endpoint map.