Create a person
Changed onUse this endpoint to add a new person to your Atlas account.
This is the main endpoint for pushing contact data into Atlas from an external system - for example, from your website's application form, a spreadsheet import, or another tool in your tech stack.
Strict create — never updates an existing person.
If any of the contact details (identities) you provide already point at a person in your agency, the request fails with 409 Conflict and the response body includes the existing personId. To update an existing record, use PATCH /api/v1/people/{id} (fields, identities, custom attributes) and the dedicated experience / education endpoints — this endpoint will not merge data into an existing record under any circumstances. The typical integration flow is: POST, and on a 409 take the returned personId and PATCH it.
Conflict detection order:
- source.externalId paired with source.system (high-confidence external-id match).
- Email address (normalized).
- LinkedIn URL (linkedin, linkedin_salesnav, linkedin_recruiter).
- Phone number (matched against all variations Atlas stores).
The first match wins; the returned personId is the conflicting person's id, and conflictType tells you which rule matched — "externalId" for rule 1, "identity" for rules 2–4 (each with a matching distinct error message).
Important fields:
- identities - you must provide at least one non-website contact detail (email, phone, or LinkedIn). This is how Atlas identifies the person and how the conflict check runs.
- addedByEmail - the email address of an existing Atlas user in your agency. This is the team member the action will be attributed to. If no user exists with this email, the request fails with a 404.
- source - optional. Tag where this data came from (e.g. "website", "zapier", "hubspot").
source.externalId uniqueness. A (source.system, source.externalId) pair is unique within your agency — it identifies at most one person and is the highest-priority conflict rule (rule 1 above). Re-pushing a record whose externalId is already stored on a person returns 409 with that person's personId, so it doubles as an idempotency key: on 409, switch to PATCH /api/v1/people/{id}.
Synchronous vs. asynchronous creation.
The person record, its identities, headline, and any custom attribute values are created synchronously — once you receive the 201, the person exists and the conflict check above will match it.
Work experience, education and compensation are created asynchronously: each is queued as an independent background job. They are validated synchronously (an invalid payload still returns 422 before anything is created), so anything accepted will be created — but it may take a short moment to appear, so they are not guaranteed to be present on an immediate GET /api/v1/people/{id}. The company-contact link (when isContact: true) is created synchronously and is present on that immediate read. A failure creating one of these extras (e.g. a transient database error) is retried automatically and never affects the person, the other extras, or the 201 you already received.
What you get back:
On success (201), the response includes:
- The Atlas person ID
- created: true
- identitiesCreated / customAttributesCreated — counts created synchronously
- queued — counts of experience, education, compensation, and company-contact records accepted and enqueued for asynchronous creation
Request
- Base URLhttps://api.recruitwithatlas.com
- AuthHTTP bearer
- TypeScriptA function with typed inputs. Its response is checked against the schema.
Request body
Example request
{
"firstName": "Michael",
"lastName": "Scott",
"gender": "male",
"addedByEmail": "jordan@recruitwithatlas.com",
"source": {
"system": "api",
"externalId": "124456"
},
"identities": [
{
"type": "email",
"value": "mscott@gmail.com",
"isPersonal": true,
"isPrimary": true
}
],
"headline": {
"role": "Regional Manager",
"company": "Dunder Mifflin",
"companyId": "550e8400-e29b-41d4-a716-446655440000",
"roleStartedAt": "2023-04-01"
},
"location": {
"name": "London, UK",
"locality": "London",
"region": "England",
"metro": "new york, new york",
"country": "United Kingdom",
"streetAddress": "123 Baker Street",
"addressLine2": "Suite 200",
"postalCode": "NW1 6XE",
"raw": "123 Baker Street, London NW1 6XE, United Kingdom",
"latitude": 51.523767,
"longitude": -0.158519
},
"compensation": [
{
"type": "actual",
"basicSalary": 120000,
"totalSalary": 150000,
"currency": "USD",
"basis": "gross",
"date": "2024-06-01"
}
],
"customAttributes": [
{
"customAttributeId": "550e8400-e29b-41d4-a716-446655440000",
"value": "Some text value"
},
{
"customAttributeId": "6f9619ff-8b86-d011-b42d-00cf4fc964ff",
"value": 42
},
{
"customAttributeId": "c9bf9e57-1685-4c89-bafb-ff5af830be8a",
"value": "2025-06-01"
},
{
"customAttributeId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"optionId": "9b2e4d6a-1c3f-4a8b-9e7d-2f1a6c5b4d3e"
}
],
"experience": [
{
"companyName": "Dunder Mifflin",
"companyId": "550e8400-e29b-41d4-a716-446655440000",
"companyLinkedinId": "12345678",
"companyDomain": "dundermifflin.com",
"role": "Regional Manager",
"description": "Responsible for managing Scranton branch.",
"startDate": "2021-04-01"
}
],
"education": [
{
"institutionName": "University of Scranton",
"degree": "Bachelor of Science",
"fieldOfStudy": "Business Administration",
"grade": "3.4 GPA",
"description": "Focus on management and sales.",
"startDate": "2012-09-01",
"endDate": "2016-06-30"
}
]
}Response
New person created. Identities, custom attributes and the company-contact link (when isContact is set) are created synchronously; experience, education and compensation are enqueued for asynchronous creation (see the queued counts).
Changes
- info
added the optional property
to the response with the status
- info