Skip to main content

Which endpoint should you use?

For most use cases, use POST /contacts/upsert. It handles both creating and updating contacts in a single call, with automatic deduplication based on ID, email, or name/birthdate/address. For specific scenarios, two synchronous alternatives are available:
  • POST /contacts — creates a single contact and returns it immediately; useful when you need the new contact’s ID right away.
  • PATCH /contacts/{id} — updates a known contact by ID; useful for targeted edits when you already have the whole contact object and ID.

Write payload shapes by endpoint

POST /contacts/upsert accepts high-level contact payloads. For advanced fields, use field-specific arrays such as consents, status, forms, custom_fields, actions, or presence_status. Use POST /contacts or PATCH /contacts/{id} when you need synchronous create or update behavior. For advanced fields, both endpoints use the lower-level formdatas structure to link a contact to a form and a selected value.

Upsert matching strategy

When upserting, the system tries to find an existing contact to update using the following strategy (in order). If no match is found, a new contact is created.
1

Match by ID

If an id is provided and matches an existing contact, that contact is updated. Accepts a Qomon contact ID or a NationBuilder ID.
2

Match by email + name

If no ID is provided (or it didn’t match), the system searches for contacts with the same mail. Among the results, firstname and surname are used as additional filters if provided. An empty value means the field is not used for matching.
3

Match by surname + firstname + birthdate + address

If no email match was found and a surname is provided, the system searches by surname. firstname must also match. If both contacts have a birthdate, it must match exactly. If both have an address, city or postalcode must match — and if no birthdate comparison was made, street must also match.
4

No match — contact is created

If none of the above strategies found a match, a new contact is created.
If the id or label of an advanced field, or the value (for non-free-text fields), does not exist, the contact will not be updated or created. Errors will not be logged.

Advanced fields (form fields)

In POST /contacts/upsert, several fields in the contact object accept arrays of form objects. Each object requires a form id or unique label, and a string value defined in your account settings.
1

Find your form IDs

Each form type has its own endpoint. Call the relevant one to retrieve the IDs and accepted values for your account:
FieldEndpoint
consentsGET https://incoming.qomon.app/forms/consent
custom_fieldsGET https://incoming.qomon.app/forms/custom_fields
statusGET https://incoming.qomon.app/forms/level_of_support
For more information, look at the reference for /forms.
2

Retrieve your form IDs

Each field type has a dedicated endpoint. Call it to get the valid IDs and accepted values for your account:
Field familyPayload keyEndpoint
ConsentsconsentsGET /v1/forms/type/consent
Custom fieldscustom_fieldsGET /v1/forms/type/custom_fields
Level of supportstatusGET /v1/forms/type/level_of_support
Survey answersformsGET /v1/forms/type/survey
TasksactionsGET /v1/forms/type/tasks
Presence statuspresence_statusGET /v1/forms/type/presence_status
See the Forms overview for more details about form types and formdatas.
3

Correct payload structure

Each form field follows the same shape: an array of objects with an id and a string value.If the form has a unique label, you can use the label instead of the id.
{
  "kind": "contact",
  "data": {
    "firstname": "Jane",
    "surname": "Doe",
    "gender": "F",
    "mail": "jane.doe@example.com",
    "address": {
      "postalcode": "12345"
    },
    "consents": [
      { "id": 1234, "value": "consent_email" },
      { "label": "General communication", "value": "consent_sms" }
    ],
    "custom_fields": [
      { "id": 4512, "value": "member" }
    ],
	"status": [
	  { "id": 9826, "value": "donator" }
	]
  }
}
4

Structure your payload

Each form field is an array of objects with an id and a value. If a form has a unique label, you can use label instead of id.
{
  "kind": "contact",
  "data": {
    "firstname": "Jane",
    "surname": "Doe",
    "mail": "jane.doe@example.com",
    "consents": [
      { "id": 1234, "value": "consent_email" },
      { "label": "General communication", "value": "consent_sms" }
    ],
    "custom_fields": [
      { "id": 4512, "value": "member" }
    ],
    "status": [
      { "id": 9826, "value": "donator" }
    ],
    "forms": [
      { "id": 7621, "value": "Interested in volunteering" }
    ],
    "actions": [
      { "id": 2314, "value": "send_information" }
    ]
  }
}
Use the form id returned by the endpoint, not the form_ref_id.
The value field always expects a string — never a boolean or integer.
Every form field must be an array, even when setting a single value.
Last modified on June 10, 2026