Build

Contacts

Manage lender and sponsor contacts in the Lev API.

Updated June 2026
GET/api/external/v2/contacts
GET/api/external/v2/contacts/{contact_id}
GET/api/external/v2/contacts/{contact_id}/notesNotes logged on a contact
POST/api/external/v2/contacts/{contact_id}/notes
PATCH/api/external/v2/contacts/{contact_id}/notes/{note_id}
DELETE/api/external/v2/contacts/{contact_id}/notes/{note_id}

Overview

EndpointDescription
GET /contactsList contacts with pagination
GET /contacts/{id}Get a single contact
POST /contactsCreate a new contact
PATCH /contacts/{id}Update a contact
POST /contacts/{id}/actions/unlockReveal an AI-recommended lender contact (charges credits)
GET /contacts/{id}/notesList notes logged on a contact
POST /contacts/{id}/notesAdd a note to a contact
PATCH /contacts/{id}/notes/{note_id}Edit a contact note
DELETE /contacts/{id}/notes/{note_id}Delete a contact note

Contacts are scoped to your account. Only connected contacts (active relationships) are returned by default.

List Contacts

GET/api/external/v2/contacts

List contacts with pagination

Query parameters
limitinteger
Results per page (1–200, default 50)
cursorstring
Cursor for next page
fieldsstring
Comma-separated fields to include

Response (200):

{
  "request_id": "b8c9d0e1-f2a3-4567-1234-678901234567",
  "timestamp": "2026-03-20T15:30:45Z",
  "data": [
    {
      "id": 78,
      "contact_type": "lender_contact",
      "first_name": "Sarah",
      "last_name": "Chen",
      "email": "schen@meridiancapital.com",
      "title": "Senior Vice President",
      "department": "Originations",
      "address": "1 Battery Park Plaza",
      "address2": "Suite 2400",
      "city": "New York",
      "state": "NY",
      "zip": "10004",
      "linkedin_url": "https://linkedin.com/in/sarah-chen-cre",
      "photo_url": "https://meridiancapital.com/team/sarah-chen.jpg",
      "phones": [
        {
          "id": null,
          "type": "office",
          "raw": "(212) 555-0184",
          "country": "US",
          "e164": "+12125550184",
          "extension": ""
        }
      ],
      "is_primary": true,
      "is_connected": true,
      "owner_account_id": 56,
      "created_at": "2025-09-01T11:00:00Z",
      "updated_at": "2026-02-20T16:45:00Z"
    }
  ],
  "pagination": {
    "total": 128,
    "limit": 50,
    "has_more": true,
    "next_cursor": "eyJpZCI6IDc4fQ=="
  }
}
401unauthorized
Authentication requiredMissing or invalid Authorization header
400bad_request
cursor and sort cannot be combined; use offset pagination when sortingBoth cursor and sort params provided

Get Contact

GET/api/external/v2/contacts/{contact_id}

Get a single contact by ID

Path parameters
contact_idintegerrequired
The contact ID

Response (200):

{
  "request_id": "c9d0e1f2-a3b4-5678-2345-789012345678",
  "timestamp": "2026-03-20T15:30:45Z",
  "data": {
    "id": 78,
    "contact_type": "lender_contact",
    "first_name": "Sarah",
    "last_name": "Chen",
    "email": "schen@meridiancapital.com",
    "title": "Senior Vice President",
    "department": "Originations",
    "address": "1 Battery Park Plaza",
    "address2": "Suite 2400",
    "city": "New York",
    "state": "NY",
    "zip": "10004",
    "linkedin_url": "https://linkedin.com/in/sarah-chen-cre",
    "photo_url": "https://meridiancapital.com/team/sarah-chen.jpg",
    "phones": [
      {
        "id": null,
        "type": "office",
        "raw": "(212) 555-0184",
        "country": "US",
        "e164": "+12125550184",
        "extension": ""
      }
    ],
    "is_primary": true,
    "is_connected": true,
    "owner_account_id": 56,
    "created_at": "2025-09-01T11:00:00Z",
    "updated_at": "2026-02-20T16:45:00Z"
  }
}
401unauthorized
Authentication requiredMissing or invalid Authorization header
404not_found
Contact not foundThe ID doesn't exist or isn't accessible to the authenticated user

Create Contact

POST/api/external/v2/contacts

Create a new contact

Request body
contact_typestringrequired
Contact type: lender_contact or sponsor
company_idintegerrequired
Associated company ID
first_namestring
First name
last_namestring
Last name
emailstring
Email address
titlestring
Job title
departmentstring
Department
addressstring
Street address
address2string
Apartment, suite, or unit line
citystring
City
statestring
State
zipstring
ZIP code
linkedin_urlstring
LinkedIn profile URL
photo_urlstring
URL to a profile photo
phonesPhoneIn[]
Phone numbers. Each object: { raw, type?, country?, extension? }. raw accepts any common format and is normalized to E.164 server-side (unparseable numbers return 422). type is mobile, office, or fax (default mobile). country is a 2-letter ISO region used to parse numbers without a + prefix (default US).
is_primaryboolean
Whether this is the primary contact at the company

Response (201):

{
  "request_id": "d0e1f2a3-b4c5-6789-3456-890123456789",
  "timestamp": "2026-03-20T15:30:45Z",
  "data": {
    "id": 142,
    "contact_type": "lender_contact",
    "first_name": "James",
    "last_name": "Rodriguez",
    "email": "jrodriguez@eastdilsecured.com",
    "title": "Managing Director",
    "department": "Debt Capital Markets",
    "address": "40 West 57th Street",
    "address2": "Floor 30",
    "city": "New York",
    "state": "NY",
    "zip": "10019",
    "linkedin_url": "https://linkedin.com/in/james-rodriguez-cre",
    "photo_url": "https://eastdilsecured.com/team/james-rodriguez.jpg",
    "phones": [
      {
        "id": null,
        "type": "mobile",
        "raw": "(917) 555-0142",
        "country": "US",
        "e164": "+19175550142",
        "extension": ""
      }
    ],
    "is_primary": false,
    "is_connected": false,
    "owner_account_id": 56,
    "created_at": "2026-03-20T15:30:45Z",
    "updated_at": "2026-03-20T15:30:45Z"
  }
}
401unauthorized
Authentication requiredMissing or invalid Authorization header
403forbidden
User not authorized to create contactThe user's role doesn't have CREATE permission
422validation_error
contact_type is requiredMissing required contact_type field

Update Contact

PATCH/api/external/v2/contacts/{contact_id}

Update a contact

Path parameters
contact_idintegerrequired
The contact ID
Request body
first_namestring
First name
last_namestring
Last name
emailstring
Email address
titlestring
Job title
departmentstring
Department
addressstring
Street address
address2string
Apartment, suite, or unit line
citystring
City
statestring
State
zipstring
ZIP code
linkedin_urlstring
LinkedIn profile URL
photo_urlstring
URL to a profile photo
phonesPhoneIn[]
Replaces the contact's entire phone list — send [] to clear all numbers. Same object shape as Create Contact.
is_primaryboolean
Set to true to make this the primary contact at the company. Promoting one contact demotes the previous primary.

All request body fields are optional. Only provided fields are updated. contact_type and company_id are not updatable. email can be set once if absent, but changing an existing email is rejected with 409 — it would break the link to the underlying person record.

Response (200):

{
  "request_id": "e1f2a3b4-c5d6-7890-4567-901234567890",
  "timestamp": "2026-03-20T15:30:45Z",
  "data": {
    "id": 78,
    "contact_type": "lender_contact",
    "first_name": "Sarah",
    "last_name": "Chen",
    "email": "schen@meridiancapital.com",
    "title": "Executive Vice President",
    "department": "Originations",
    "address": "1 Battery Park Plaza",
    "address2": "Suite 2400",
    "city": "New York",
    "state": "NY",
    "zip": "10004",
    "linkedin_url": "https://linkedin.com/in/sarah-chen-cre",
    "photo_url": "https://meridiancapital.com/team/sarah-chen.jpg",
    "phones": [
      {
        "id": null,
        "type": "office",
        "raw": "(212) 555-0184",
        "country": "US",
        "e164": "+12125550184",
        "extension": ""
      }
    ],
    "is_primary": true,
    "is_connected": true,
    "owner_account_id": 56,
    "created_at": "2025-09-01T11:00:00Z",
    "updated_at": "2026-03-20T15:30:45Z"
  }
}
401unauthorized
Authentication requiredMissing or invalid Authorization header
404not_found
Contact not foundThe ID doesn't exist or isn't accessible to the authenticated user
409conflict
Changing a contact's email is not supported yetThe contact already has an email and the request supplies a different one

Unlock Contact

POST/api/external/v2/contacts/{contact_id}/actions/unlock

Reveal an AI-recommended lender contact — charges credits; requires the ai:actions scope

Reveals an AI-recommended lender contact and charges credits to your account. When you create a placement without a contact_id, Lev matches a recommended contact at that lender (see Create Placement). The placement carries the recommended contact_id, but the contact's identity stays masked — contact_name is null on the placement, and the contact is not yet retrievable through Get Contact. Unlock reveals it.

Requires the ai:actions scope. Unlocking spends credits, so it is grouped under ai:actions rather than contacts:write — a credential scoped to CRM writes alone cannot spend credits.

Pass the contact_id from the placement. The request takes no body. On success the contact's identity — name, email, phone — is revealed in the response, on Get Contact, and on the placement that holds it.

Supports the Idempotency-Key header. Unlocking is charged once per contact: unlocking an already-unlocked contact returns it without a second charge.

Path parameters
contact_idintegerrequired
The contact to reveal — the `contact_id` returned on the placement
curl -X POST "https://api.lev.com/api/external/v2/contacts/142/actions/unlock" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000"

Response (200): the revealed Contact Object, now carrying the contact's name and other identity fields.

{
  "request_id": "f2a3b4c5-d6e7-8901-5678-012345678901",
  "timestamp": "2026-06-24T15:30:45Z",
  "data": {
    "id": 142,
    "contact_type": "lender_contact",
    "first_name": "James",
    "last_name": "Rodriguez",
    "email": "jrodriguez@eastdilsecured.com",
    "title": "Managing Director",
    "department": "Debt Capital Markets",
    "address": "40 West 57th Street",
    "address2": "Floor 30",
    "city": "New York",
    "state": "NY",
    "zip": "10019",
    "linkedin_url": "https://linkedin.com/in/james-rodriguez-cre",
    "photo_url": "https://eastdilsecured.com/team/james-rodriguez.jpg",
    "phones": [
      {
        "id": null,
        "type": "mobile",
        "raw": "(917) 555-0142",
        "country": "US",
        "e164": "+19175550142",
        "extension": ""
      }
    ],
    "is_primary": false,
    "is_connected": false,
    "owner_account_id": 56,
    "created_at": "2026-03-20T15:30:45Z",
    "updated_at": "2026-06-24T15:30:45Z"
  }
}
401unauthorized
Authentication requiredMissing or invalid Authorization header
402insufficient_credits
Insufficient credits to unlock this contactThe account's credit balance can't cover the unlock; the error details carry action_code, cost, and balance
403forbidden
Missing required scope: ai:actionsThe credential does not include the ai:actions scope
404not_found
Contact not foundThe contact_id doesn't exist or isn't accessible to the authenticated user

List Contact Notes

GET/api/external/v2/contacts/{contact_id}/notes

List notes logged on a contact

Lists the free-text notes logged on a contact — call summaries, relationship context, and other human-written commentary. Notes are returned oldest first; walk the next_cursor in the response to reach the most recent. Internal or private notes are never returned.

For underwriting facts and where a value came from, use the deal index (Search Index) — notes are commentary, not indexed facts.

Path parameters
contact_idintegerrequired
The contact ID
Query parameters
limitinteger
Results per page (1–200, default 50)
cursorstring
Cursor for next page
curl "https://api.lev.com/api/external/v2/contacts/142/notes" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response (200):

{
  "request_id": "43f2c567-57e4-4fac-8044-b22e01ec562c",
  "timestamp": "2026-06-08T17:25:28Z",
  "data": [
    {
      "id": 5012,
      "text": "Met at the conference — covers multifamily in the Southeast.",
      "created_by": {
        "id": 88,
        "name": "Dana Lender"
      },
      "created_at": "2026-06-08T10:00:00Z",
      "updated_at": "2026-06-08T10:00:00Z"
    }
  ],
  "pagination": {
    "total": 1,
    "limit": 50,
    "has_more": false,
    "next_cursor": null
  }
}
401unauthorized
Authentication requiredMissing or invalid Authorization header
404not_found
Contact not foundThe contact_id doesn't exist or isn't accessible to the authenticated user

Create Contact Note

POST/api/external/v2/contacts/{contact_id}/notes

Add a note to a contact

Logs a free-text note on a contact. The note is attributed to the API key's user and appears alongside notes written in the Lev web app. Simple HTML formatting is preserved; scripts and other unsafe markup are stripped.

Supports the Idempotency-Key header to prevent duplicate creation. Requires the contacts:write scope.

Path parameters
contact_idintegerrequired
The contact ID
Request body
textstringrequired
Note text. Must be non-empty.
curl -X POST "https://api.lev.com/api/external/v2/contacts/142/notes" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -d '{"text": "Met at the conference — covers multifamily in the Southeast."}'

Response (201):

{
  "request_id": "d0e1f2a3-b4c5-6789-3456-890123456789",
  "timestamp": "2026-06-08T15:30:45Z",
  "data": {
    "id": 5012,
    "text": "Met at the conference — covers multifamily in the Southeast.",
    "created_by": {
      "id": 88,
      "name": "Dana Lender"
    },
    "created_at": "2026-06-08T15:30:45Z",
    "updated_at": "2026-06-08T15:30:45Z"
  }
}
401unauthorized
Authentication requiredMissing or invalid Authorization header
404not_found
Contact not foundThe contact_id doesn't exist or isn't accessible to the authenticated user
422validation_error
text must not be blankThe request omits text or sends an empty string

Update Contact Note

PATCH/api/external/v2/contacts/{contact_id}/notes/{note_id}

Edit a contact note

Replaces the text of a note logged on a contact. Requires the contacts:write scope. Use the id returned by List Contact Notes or Create Contact Note as note_id.

Only notes the authenticated user created and can still write are editable. Notes on another contact, hidden or private notes, and notes the user does not own return 404 Not Found.

Supports the Idempotency-Key header to make retries safe.

Path parameters
contact_idintegerrequired
The contact ID
note_idintegerrequired
The note ID
Request body
textstringrequired
Replacement note text. Must be non-empty.
curl -X PATCH "https://api.lev.com/api/external/v2/contacts/142/notes/5012" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -d '{"text": "Met at the conference — covers multifamily bridge loans in the Southeast."}'

Response (200):

{
  "request_id": "90d7bfc2-ff5e-4b4e-9c77-7987957fd6a7",
  "timestamp": "2026-06-19T15:30:45Z",
  "data": {
    "id": 5012,
    "text": "Met at the conference — covers multifamily bridge loans in the Southeast.",
    "created_by": {
      "id": 88,
      "name": "Dana Lender"
    },
    "created_at": "2026-06-08T15:30:45Z",
    "updated_at": "2026-06-19T15:30:45Z"
  }
}
401unauthorized
Authentication requiredMissing or invalid Authorization header
404not_found
Contact or note not foundThe contact_id or note_id doesn't exist, doesn't match, isn't externally visible, or isn't writable by the authenticated user
400bad_request
text cannot be emptyThe supplied text becomes empty after sanitization
422validation_error
text must not be blankThe request omits text or sends an empty string

Delete Contact Note

DELETE/api/external/v2/contacts/{contact_id}/notes/{note_id}

Permanently delete a contact note

Permanently deletes a note logged on a contact. Requires the contacts:write scope. Use the id returned by List Contact Notes or Create Contact Note as note_id.

Only notes the authenticated user created and can still write are deletable. Notes on another contact, hidden or private notes, and notes the user does not own return 404 Not Found.

Path parameters
contact_idintegerrequired
The contact ID
note_idintegerrequired
The note ID
curl -X DELETE "https://api.lev.com/api/external/v2/contacts/142/notes/5012" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response (200):

{
  "request_id": "2c23bb16-8a8c-4a20-8ec0-9af5f555c84c",
  "timestamp": "2026-06-19T15:30:45Z",
  "data": {
    "deleted": true
  }
}
401unauthorized
Authentication requiredMissing or invalid Authorization header
404not_found
Contact or note not foundThe contact_id or note_id doesn't exist, doesn't match, isn't externally visible, or isn't writable by the authenticated user

Contact Object

FieldTypeDescription
idintegerContact identifier
contact_typestring|nullFirst entry from contact_types, kept as a string for backwards compatibility. lender_contact or sponsor.
contact_typesstring[]All contact types assigned to the contact (a contact can be both a lender and a sponsor contact). Values: lender_contact, sponsor.
first_namestring|nullFirst name
last_namestring|nullLast name
emailstring|nullEmail address
titlestring|nullJob title
departmentstring|nullDepartment
addressstring|nullStreet address
address2string|nullApartment, suite, or unit line
citystring|nullCity
statestring|nullState
zipstring|nullZIP code
linkedin_urlstring|nullLinkedIn profile URL
photo_urlstring|nullURL to a profile photo
phonesPhone[]Phone numbers ([] when none). Each: {id, type, raw, country, e164, extension}e164 is the normalized canonical number (always server-computed from raw); type is mobile, office, or fax; fields may be null on records created before phone support.
is_primarybooleanWhether this is the primary contact
owner_account_idinteger|nullOwning account ID
is_connectedbooleanWhether this is a connected contact
created_atstring|nullCreation timestamp
updated_atstring|nullLast update timestamp
More in this section