Contacts

The people a campaign sends to, and the lists that group them.

Create a contact

POST /contacts is an upsert, matched by email or phone: send the same address twice and the second call updates the first record instead of creating a duplicate. That matters most on re-import: nobody gets the same campaign twice because they were added twice.

cURL
curl -X POST https://api.mailer.quathos.com/api/v1/contacts \
  -H "Authorization: Bearer $QUATHOS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email":      "ada@example.com",
    "first_name": "Ada",
    "consents": [
      {
        "channel":       "email",
        "basis":         "CONSENT",
        "purpose":       "newsletter",
        "source":        "Signup form at example.com/newsletter",
        "consent_text":  "I want to receive news and offers by email."
      }
    ]
  }'
"consents" is optional. Leaving it out is not an oversight the API warns you about: it just means this contact has no marketing consent on file, and a campaign audience will skip them for exactly that reason.

"The customer said they opted in" does not hold up in a dispute. source and consent_text are the proof: where the checkbox lived, and the exact wording the person agreed to.

basisAuthorizes
CONSENTMarketing: the only basis a campaign audience accepts.
CONTRACTTransactional email tied to a purchase or an account.
LEGITIMATE_INTERESTTransactional email your relationship with them already justifies.
LEGAL_OBLIGATIONNotices you are required to send.
A campaign audience only ever counts CONSENT. CONTRACT and LEGITIMATE_INTEREST authorize a receipt or a password reset (never a newsletter), so validating a campaign removes contacts on any other basis the same way it removes contacts with no consent record at all.

Lists and members

A list is what a campaign points at. Create one, then add contacts to it by id.

cURL
curl -X POST https://api.mailer.quathos.com/api/v1/contacts/lists \
  -H "Authorization: Bearer $QUATHOS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "March newsletter",
    "slug": "march-newsletter"
  }'

{
  "id":           "0195f0b2-...",
  "name":         "March newsletter",
  "slug":         "march-newsletter",
  "member_count": 0
}

Adding a contact that is already a member is a no-op, not an error: added and skipped tell you which is which, so re-running the same import is always safe.

cURL
curl -X POST https://api.mailer.quathos.com/api/v1/contacts/lists/$LIST_ID/members \
  -H "Authorization: Bearer $QUATHOS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "contact_ids": ["0195f0c4-...", "0195f0c5-..."]
  }'

{ "added": 2, "skipped": 0, "total": 2 }