Create a contact

posthttps://api.expiryedge.com/v1/createContact
editor or admin60/minIdempotency-KeyAny method
Request
curl -X POST 'https://api.expiryedge.com/v1/createContact' \
  -H "Authorization: Bearer $EXPIRYEDGE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "firstName": "Priya",
  "lastName": "Shah",
  "email": "priya.shah@northwinddental.example",
  "smsPhone": "+15550123456",
  "jobTitle": "Practice Manager",
  "contactType": "Staff",
  "contactGroup": "Licensing",
  "timezone": "America/New_York",
  "sendNotifications": true,
  "email_opt_in": true,
  "sms_opt_in": true
}'
Response
{
  "message": "Contact added successfully",
  "contact": {
    "id": "c_8Hk2pQ",
    "user_id": "u_71bXq",
    "organization_id": "org_northwind",
    "firstName": "Priya",
    "lastName": "Shah",
    "email": "priya.shah@northwinddental.example",
    "smsPhone": "+15550123456",
    "whatsappPhone": null,
    "contactType": "Staff",
    "jobTitle": "Practice Manager",
    "timezone": "America/New_York",
    "contactGroup": "Licensing",
    "is_default": false,
    "email_opt_in": true,
    "sms_opt_in": true,
    "whatsapp_opt_in": false,
    "sendNotifications": true,
    "createdAt": "2026-09-27T14:05:00.000Z",
    "updatedAt": "2026-09-27T14:05:00.000Z"
  }
}

Emails must be unique in the organization (case-insensitive, 409 EMAIL_EXISTS). Counts toward the plan's contact limit (403 with current/limit/remaining when reached). A new contactGroup name creates the group. Send lastName (use '' if unknown).

Headers

  • Idempotency-Keystring
    Optional client-generated key (1-255 characters of letters, digits, - _ : .).
    pattern: ^[A-Za-z0-9_\-:.]{1,255}$

Body parameters

application/json
  • firstNamestring
  • lastNamestring
    Send '' when unknown (create stores it as given).
  • emailstring | null
    Unique per organization (case-insensitive) on create.
    format: email
  • smsPhonestring | null
    E.164 phone for SMS, e.g. +15550123456.
  • whatsappPhonestring | null
  • contactTypestring | null
    Free-text category, e.g. Client, Staff, Vendor.
  • jobTitlestring | null
  • timezonestring
    IANA timezone. Defaults to Europe/London on create.
  • contactGroupstring | null
    Group name (not id). A new name creates the group.
  • is_defaultboolean
    Default contact added to new expiries. Defaults to false. isDefault is also accepted on create.
  • email_opt_inboolean
    Defaults to true.
  • sms_opt_inboolean
    Defaults to false.
  • whatsapp_opt_inboolean
    Defaults to false.
  • sendNotificationsboolean
    Master switch for reminders to this contact. Defaults to true.

Returns

201
Contact created.
  • messagestringrequired
  • contactobjectrequired
    A contact as returned by the API (camelCase; stored snake_case).

Errors

400
The request is missing required fields or contains invalid values.
401
Missing, expired or invalid bearer token.
403
Role is not editor/admin ({error}), or the plan's contact limit is reached (PlanLimitError).
404
The record does not exist or is not in your organization.
409
A contact with this email already exists in your organization.; or a request with the same Idempotency-Key is still being processed (code IDEMPOTENCY_IN_PROGRESS).
422
The Idempotency-Key was already used with a different request body.
429
Too many requests for this endpoint from your IP. Wait Retry-After seconds.