Skip to main content
POST
/
contacts
Create contact
curl --request POST \
  --url https://api.routera.io/contacts \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "fields": {
    "external_id": "ext-001",
    "first_name": "Ada",
    "last_name": "Lovelace",
    "email": "ada@example.com"
  }
}
'
{
  "id": "<string>",
  "external_id": "<string>",
  "first_name": "<string>",
  "last_name": "<string>",
  "email": "<string>",
  "contact_owner": "jane@example.com",
  "created_at": "2023-11-07T05:31:56Z",
  "updated_at": "2023-11-07T05:31:56Z",
  "archived": true,
  "archived_by": "<string>"
}

Endpoint

POST https://api.routera.io/contacts
Route: /contacts
Authentication: Bearer JWT

Request body

The body is a JSON object with a single fields property. Each key inside fields is a field internal_name (the same names returned in GET responses, not nested under fields in the response). Include every field you want to set on the new record.
{
  "fields": {
    "external_id": "ext-001",
    "first_name": "Ada",
    "last_name": "Lovelace",
    "email": "ada@example.com"
  }
}
KeyDescription
fieldsRequired. Map of internal_name → value for this object type.
fields.external_idOptional. External identifier for sync with outside systems.
Custom fields configured in your account use the same key names inside fields.
Required on create: At least one of email, first_name, or last_name. See API introduction for field types and validation rules.

Default response fields

201 returns a flat object with these properties:
PropertyDescription
idInternal object ID
first_nameCustom or system field (flat on the object)
last_nameCustom or system field (flat on the object)
emailCustom or system field (flat on the object)
contact_ownerAssigned owner email
external_idExternal identifier (nullable)
archivedfalse when active; ISO timestamp when archived
created_at and updated_at are always included in every response (ISO 8601 UTC), even when not listed above. When an object is archived, archived_by is also included automatically.

Response example

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "external_id": "ext-001",
  "created_at": "2026-05-01T10:00:00.000Z",
  "updated_at": "2026-05-28T12:00:00.000Z",
  "archived": false,
  "first_name": "Ada",
  "last_name": "Lovelace",
  "email": "ada@example.com",
  "contact_owner": "jane@example.com"
}

Errors

StatusWhen
400Invalid JSON body, unknown field name, validation failure, or forbidden system field
401Missing account context
409Duplicate active record (email, website_url, or external_id)
500Internal server error

Authorizations

Authorization
string
header
required

Bearer JWT with valid account context.

Body

application/json

Write payload for POST create and PATCH update. Keys inside fields match field internal names returned in GET responses.

fields
object
required

Field values keyed by internal_name. Custom account fields use the same key names.

Response

Created

Flat JSON object; custom fields at top level alongside id and external_id. created_at and updated_at are always present.

id
string
external_id
string | null
first_name
string | null
last_name
string | null
email
string | null
contact_owner
string | null

Assigned owner email

Example:

"jane@example.com"

created_at
string<date-time>
updated_at
string<date-time>
archived

false when active, or ISO timestamp when archived

archived_by
string

Present when archived