Base URL
https://app.dmu.email/api/v1
Authentication
Bearer dmk_… API key
Rate limit
120 requests a minute per key

List contacts

GET/contacts

Lists your organisation’s contacts, oldest change first, so a sync can pick up where it stopped.

Needs the permissioncontacts:read

This address changed in October 2026

Until then GET /contacts looked up addresses from mail. That lookup is now List correspondents, unchanged. This list needs contacts:read, which keys made before then don’t have.

A key sees the shared contacts. One made with “Include my personal contacts” also sees its own person’s, with visibility: "personal"; only that person can turn the option on, and no key ever sees anyone else’s.

To follow changes, pass the updatedAt of the last contact you saw as updatedSince, then follow nextCursor until it’s null. updatedSince includes its own moment, so you see that contact again: skip what you already have. Start each poll a few minutes before your last updatedAt, since a change saved at the same moment can show up a little late.

Deleted contacts aren’t in the list. Subscribe to the contact.deleted webhook event, or list everything from time to time to find what’s gone.

Query parameters

qstringoptional
Searches names, companies and addresses, as the app does.
updatedSincestringoptional
Only contacts changed at or after this ISO 8601 time. End it in Z, or URL-encode the + of an offset as %2B.
cursorstringoptional
The nextCursor of the page before.
limitnumberoptional
1 to 200, or 100 if you leave it out.

Returns

A list of contacts, and nextCursor beside it, null on the last page. Each contact has:

idstring
The contact.
visibilitystring
shared with the organisation, or personal to the key’s person.
sourcestring
Where it came from: manual, import, api or crm.
firstNamestring or null
With lastName, company and jobTitle: who they are.
emailstring
The first of emails, and the contact’s key: one contact per address.
emailslist of strings
Every address, up to 10.
phoneslist of strings
Up to 10 phone numbers.
fieldsobject
Your organisation’s own fields by key, as List contact fields names them. A Person field holds a colleague’s address, a Date field is YYYY-MM-DD.
lockedlist of strings
The fields the app can’t change because the API or the CRM set them, by key, such as first_name or vat_number.
createdAtstring
With updatedAt: when it was added and last changed.

Errors

400bad_limit
limit isn’t a whole number from 1 to 200.
400bad_updated_since
updatedSince isn’t an ISO 8601 date and time.
401invalid_key
The key is wrong, expired or revoked. With no Authorization header at all, the code is missing_credentials.
403missing_scope
The key doesn’t have contacts:read. The X-Required-Scope header names what’s missing.
429rate_limited
More than 120 requests a minute from this key. Wait for Retry-After seconds.
curl "https://app.dmu.email/api/v1/contacts?updatedSince=2026-10-25T06%3A00%3A00Z&limit=100" \
  -H "Authorization: Bearer dmk_7f3a9c2e1b4d_Xq8v…"

Response

200 OK

{
  "data": [
    {
      "id": "3d7a51c2",
      "visibility": "shared",
      "source": "api",
      "firstName": "Άννα",
      "lastName": "Παπαδάκη",
      "company": "Λογιστήριο Παπαδάκη",
      "jobTitle": "Accountant",
      "email": "anna@papadakis-acc.gr",
      "emails": ["anna@papadakis-acc.gr"],
      "phones": ["210 412 3380"],
      "fields": {
        "vat_number": "094536781",
        "customer_number": "ΠΕΛ-0412"
      },
      "locked": [
        "first_name",
        "last_name",
        "company",
        "job_title",
        "email",
        "phone",
        "vat_number",
        "customer_number"
      ],
      "createdAt": "2026-10-25T06:12:40.000Z",
      "updatedAt": "2026-10-25T06:31:05.000Z"
    }
  ],
  "nextCursor": null
}

Every response wraps its result in data. A page of threads adds nextCursor, which is null on the last page.