{"openapi":"3.0.3","info":{"title":"Contacts","description":"Create, Get, update, and delete contacts. Use this API to look up contacts\nby identifier, perform full or partial updates on a single contact, bulk-import\ncollections of contacts asynchronously, and bulk-delete contacts. When listing\ncontacts you can filter by contact status, list subscription status, list\nmembership, segment, or creation and modification date. Each contact can carry\ndata fields, channel properties (email, SMS, WhatsApp), list memberships,\nmarketing preferences, and consent records.","version":"3.5.0"},"externalDocs":{"description":"Learn more about Dotdigital APIs","url":"https://developer.dotdigital.com"},"servers":[{"url":"https://{region}-api.dotdigital.com","variables":{"region":{"description":"The Dotdigital region id your account belongs to","enum":["r1","r2","r3"],"default":"r1"}}}],"security":[{"basicAuth":[]}],"paths":{"/contacts/v3":{"get":{"summary":"Get contacts based on your criteria","description":"Get contacts based on criteria you specify. Contacts are returned with full data, specified data fields, or key information and identifiers only.<br/><br/>\n\n*Note: All data is returned in ascending order*<br/><br/>\n\n**Note:** This call also returns deleted contacts, with the status **deleted**. When a contact or its mobile number is deleted, **email** and **mobileNumber** are returned with the value **deleted**.","operationId":"getContacts","parameters":[{"name":"x-ddg-integration-token","in":"header","description":"If you are a partner of Dotdigital and have a [verified integration](https://developer.dotdigital.com/docs/partner-integration-verification) then include your [integration tracking token](https://developer.dotdigital.com/docs/verified-integration-tracking) here.","required":false,"schema":{"type":"string","format":"uuid","example":"5a96bc79-19a7-4544-973b-e2da0c9136f9"}},{"name":"data-fields","in":"query","description":"Contact data is returned with a minimum of **contactId** and any associated **identifiers**. Use this field to specify any additional data fields you want to return. Enter a pipe delimited string of the contact data fields required or **[[ALL]]** to Get all data fields.","required":false,"style":"pipeDelimited","explode":false,"schema":{"type":"array","example":["FIRSTNAME","LASTNAME","FULLNAME","GENDER","POSTCODE"],"items":{"type":"string"}}},{"name":"include","in":"query","description":"Specify additional data sets associated with the contact to include in the returned data.","required":false,"style":"pipeDelimited","explode":false,"schema":{"type":"array","example":["preferences","lists"],"items":{"type":"string","enum":["channelProperties","lists","preferences","consentRecords"]}}},{"name":"~created","in":"query","description":"Filter by created date.<br/>\n***Note:***\n* The date must be in ([ISO 8601 format](https://en.wikipedia.org/wiki/ISO_8601))\n* Can't be used in conjunction with the **~modified** parameter.","schema":{"pattern":"^gte::\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z$","type":"string"},"examples":{"Greater than or equal to created date":{"value":"gte::2021-12-17T00:00:00Z"}}},{"name":"~modified","in":"query","description":"Filter by last modified date.<br/>\n***Note:***\n* The date must be in ([ISO 8601 format](https://en.wikipedia.org/wiki/ISO_8601))","schema":{"pattern":"^gte::\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z$","type":"string"},"examples":{"Greater than or equal to modified date":{"value":"gte::2021-12-17T00:00:00Z"}}},{"name":"~listId","in":"query","description":"Filter by a specific list.<br/>\n***Note:***\n* Can't be used in conjunction with the **~segmentId** parameter.","schema":{"type":"integer"},"example":54321},{"name":"~segmentId","in":"query","description":"Filter by a specific segment.<br/>\n***Note:***\n* Can't be used in conjunction with the **~listId** parameter.","schema":{"type":"integer"},"example":12345},{"name":"limit","in":"query","description":"Maximum number of records to retrieve per page","schema":{"maximum":5000,"minimum":1,"type":"integer","format":"int32","example":1000}},{"name":"marker","in":"query","description":"Pagination marker to retrieve the data from","schema":{"type":"string","example":"RXhhbXBsZSBhbXJrZXIgdmFsdWU="}}],"responses":{"200":{"description":"Contacts retrieved","content":{"application/json":{"schema":{"required":["_items","_links"],"type":"object","properties":{"_links":{"$ref":"#/components/schemas/paginationLinks"},"_items":{"type":"array","description":"Returned contacts","items":{"$ref":"#/components/schemas/contact"}}}},"examples":{"defaultKeyDetails":{"summary":"Get contacts with key details only","description":"When you do not specify **data-fields** or **include**, each contact has only its key details and identifiers. Every identifier in the account is returned for each contact. An identifier that is not set has an empty value.<br>\n**Request:** `GET /contacts/v3?limit=2`<br><br>\n**Note:** Timestamps are UTC and are returned without a time zone designator, with up to 3 fractional-second digits.","value":{"_links":{"self":{"marker":"","link":"https://r1-api.dotdigital.com/contacts/v3?limit=2"},"first":{"marker":"","link":"https://r1-api.dotdigital.com/contacts/v3?limit=2"}},"_items":[{"contactId":35212311,"status":"subscribed","created":"2025-03-04T09:15:22.483","updated":"2026-10-12T14:03:51.27","identifiers":{"email":"amelia.thornbury@emailsim.io","mobileNumber":"447700900184","loyaltyId":"LOY-000184"}},{"contactId":35212498,"status":"unsubscribed","created":"2025-06-19T17:42:08.9","updated":"2026-09-30T08:27:15.614","identifiers":{"email":"marcus.oldacre@emailsim.io","mobileNumber":"","loyaltyId":""}}]}},"withDataFieldsListsAndPreferences":{"summary":"Get contacts with selected data fields, lists and preferences","description":"Returns the **FIRSTNAME** and **LASTNAME** data fields, the lists the contact belongs to, and the marketing preferences of each contact. A data field that has no value is returned as **null**. When a contact is not in a list or has no preferences, an empty array is returned.<br>\n**Request:** `GET /contacts/v3?data-fields=FIRSTNAME|LASTNAME&include=lists|preferences&limit=2`","value":{"_links":{"self":{"marker":"","link":"https://r1-api.dotdigital.com/contacts/v3?data-fields=FIRSTNAME|LASTNAME&include=lists|preferences&limit=2"},"first":{"marker":"","link":"https://r1-api.dotdigital.com/contacts/v3?data-fields=FIRSTNAME%7cLASTNAME&include=lists%7cpreferences&limit=2"}},"_items":[{"contactId":35212311,"status":"subscribed","created":"2025-03-04T09:15:22.483","updated":"2026-10-12T14:03:51.27","identifiers":{"email":"amelia.thornbury@emailsim.io","mobileNumber":"447700900184","loyaltyId":"LOY-000184"},"dataFields":{"FIRSTNAME":"Amelia","LASTNAME":"Thornbury"},"lists":[{"id":345579,"name":"Monthly newsletter","status":"subscribed"},{"id":345612,"name":"Loyalty members","status":"subscribed"}],"preferences":[{"id":1021,"isOptedIn":true,"publicName":"Special offers","privateName":"specialOffers"},{"id":1022,"isOptedIn":false,"publicName":"Product news","privateName":"productNews"}]},{"contactId":35212498,"status":"unsubscribed","created":"2025-06-19T17:42:08.9","updated":"2026-09-30T08:27:15.614","identifiers":{"email":"marcus.oldacre@emailsim.io","mobileNumber":"","loyaltyId":""},"dataFields":{"FIRSTNAME":"Marcus"},"lists":[],"preferences":[]}]}},"firstPageWithNextPage":{"summary":"Get the first page of contacts when more pages are available","description":"When more contacts are available, the response includes a **next** link. To get the next page, call the **next.link** URL, or send its **marker** value in the **marker** parameter. When there is no **next** link, you have the last page.<br>\n**Request:** `GET /contacts/v3?~modified=gte::2026-10-01T00:00:00Z&limit=2`<br><br>\n**Note:** The **first** and **next** links are URL-encoded. Treat the **marker** value as opaque.","value":{"_links":{"self":{"marker":"","link":"https://r1-api.dotdigital.com/contacts/v3?~modified=gte::2026-10-01T00:00:00Z&limit=2"},"first":{"marker":"","link":"https://r1-api.dotdigital.com/contacts/v3?%7emodified=gte%3a%3a2026-10-01T00%3a00%3a00Z&limit=2"},"next":{"marker":"MzUyMTIzMTE6OjIwMjYtMTAtMTIgMTQ6MDM6NTEuMjcwOjpNb2RpZmllZA==","link":"https://r1-api.dotdigital.com/contacts/v3?%7emodified=gte%3a%3a2026-10-01T00%3a00%3a00Z&limit=2&marker=MzUyMTIzMTE6OjIwMjYtMTAtMTIgMTQ6MDM6NTEuMjcwOjpNb2RpZmllZA%3d%3d"}},"_items":[{"contactId":35212498,"status":"unsubscribed","created":"2025-06-19T17:42:08.9","updated":"2026-10-03T08:27:15.614","identifiers":{"email":"marcus.oldacre@emailsim.io","mobileNumber":"","loyaltyId":""}},{"contactId":35212311,"status":"subscribed","created":"2025-03-04T09:15:22.483","updated":"2026-10-12T14:03:51.27","identifiers":{"email":"amelia.thornbury@emailsim.io","mobileNumber":"447700900184","loyaltyId":"LOY-000184"}}]}},"modifiedSinceLastPoll":{"summary":"Get contacts modified since your last poll","description":"Returns the contacts that were created, updated or deleted at or after the time you specify, with their channel properties. The contacts are in ascending order of **updated**. Use this to keep another system, such as a CRM, up to date. A deleted contact has the status **deleted**, its **email** and **mobileNumber** have the value **deleted**, and its deleted channels are not included.<br>\n**Request:** `GET /contacts/v3?~modified=gte::2026-10-15T08:00:00Z&include=channelProperties&limit=1000`<br><br>\n**Note:** Before each poll, record the current time. On the next poll, use that time in **~modified**, not the **updated** time of the last contact you received. Get all pages until there is no **next** link.","value":{"_links":{"self":{"marker":"","link":"https://r1-api.dotdigital.com/contacts/v3?~modified=gte::2026-10-15T08:00:00Z&include=channelProperties&limit=1000"},"first":{"marker":"","link":"https://r1-api.dotdigital.com/contacts/v3?%7emodified=gte%3a%3a2026-10-15T08%3a00%3a00Z&include=channelProperties&limit=1000"}},"_items":[{"contactId":35211876,"status":"deleted","created":"2024-08-21T10:05:47.32","updated":"2026-10-15T08:41:09.507","identifiers":{"email":"deleted","mobileNumber":"deleted","loyaltyId":""}},{"contactId":35212498,"status":"unsubscribed","created":"2025-06-19T17:42:08.9","updated":"2026-10-15T09:12:44.18","identifiers":{"email":"marcus.oldacre@emailsim.io","mobileNumber":"","loyaltyId":""},"channelProperties":{"email":{"emailType":"html","optInType":"single","status":"unsubscribed","openTracking":"unknown"}}},{"contactId":35213007,"status":"subscribed","created":"2026-10-15T11:48:30.662","updated":"2026-10-15T11:48:30.662","identifiers":{"email":"priya.halvorsen@emailsim.io","mobileNumber":"447700900362","loyaltyId":""},"channelProperties":{"email":{"emailType":"html","optInType":"double","status":"subscribed","openTracking":"subscribed"},"sms":{"countryCode":"GB","status":"subscribed"},"whatsApp":{"status":"noSubscription"}}}]}},"modifiedInList":{"summary":"Get contacts in a list that were modified since your last poll","description":"Returns the contacts in list **345579** that were created or updated at or after the time you specify, with the **FIRSTNAME** and **LASTNAME** data fields.<br>\n**Request:** `GET /contacts/v3?~listId=345579&~modified=gte::2026-10-15T08:00:00Z&data-fields=FIRSTNAME|LASTNAME`<br><br>\n**Note:** You cannot use **~listId** and **~segmentId** in the same request.","value":{"_links":{"self":{"marker":"","link":"https://r1-api.dotdigital.com/contacts/v3?~listId=345579&~modified=gte::2026-10-15T08:00:00Z&data-fields=FIRSTNAME|LASTNAME"},"first":{"marker":"","link":"https://r1-api.dotdigital.com/contacts/v3?%7elistId=345579&%7emodified=gte%3a%3a2026-10-15T08%3a00%3a00Z&data-fields=FIRSTNAME%7cLASTNAME"}},"_items":[{"contactId":35212311,"status":"subscribed","created":"2025-03-04T09:15:22.483","updated":"2026-10-15T10:21:09.4","identifiers":{"email":"amelia.thornbury@emailsim.io","mobileNumber":"447700900184","loyaltyId":"LOY-000184"},"dataFields":{"FIRSTNAME":"Amelia","LASTNAME":"Thornbury"}}]}},"modifiedInSegment":{"summary":"Get contacts in a segment that were modified since your last poll","description":"Returns the contacts in segment **12345** that were created or updated at or after the time you specify, with the **FIRSTNAME**, **LASTNAME** and **LOYALTYTIER** data fields.<br>\n**Request:** `GET /contacts/v3?~segmentId=12345&~modified=gte::2026-10-15T08:00:00Z&data-fields=FIRSTNAME|LASTNAME|LOYALTYTIER`<br><br>\n**Note:** You cannot use **~listId** and **~segmentId** in the same request.","value":{"_links":{"self":{"marker":"","link":"https://r1-api.dotdigital.com/contacts/v3?~segmentId=12345&~modified=gte::2026-10-15T08:00:00Z&data-fields=FIRSTNAME|LASTNAME|LOYALTYTIER"},"first":{"marker":"","link":"https://r1-api.dotdigital.com/contacts/v3?%7esegmentId=12345&%7emodified=gte%3a%3a2026-10-15T08%3a00%3a00Z&data-fields=FIRSTNAME%7cLASTNAME%7cLOYALTYTIER"}},"_items":[{"contactId":35214120,"status":"subscribed","created":"2024-11-02T13:37:55.071","updated":"2026-10-15T16:05:27.85","identifiers":{"email":"hana.velloway@emailsim.io","mobileNumber":"447700900912","loyaltyId":"LOY-000912"},"dataFields":{"FIRSTNAME":"Hana","LASTNAME":"Velloway","LOYALTYTIER":"Gold"}}]}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"example":{"errorCode":"contacts:invalidFilter","description":"The filter value '2022-08-01T00:00:00Z' is invalid"}}}},"401":{"description":"Unauthorized"}}},"post":{"summary":"Create a contact","description":"Creates a contact if the identifiers passed are unique in the account then a new contact will be created, otherwise it will fail the call with a 409.<br><br>\n**Note:** The request must contain **identifiers.email** or **identifiers.mobileNumber**. A contact cannot be created with only a custom identifier. If neither is sent, the call returns **400 Bad request** with the error code **contacts:identifierMissing**.","operationId":"createContact","parameters":[{"name":"x-ddg-integration-token","in":"header","description":"If you are a partner of Dotdigital and have a [verified integration](https://developer.dotdigital.com/docs/partner-integration-verification) then include your [integration tracking token](https://developer.dotdigital.com/docs/verified-integration-tracking) here.","required":false,"schema":{"type":"string","format":"uuid","example":"5a96bc79-19a7-4544-973b-e2da0c9136f9"}}],"requestBody":{"description":"Contact data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/createContactRequest"},"examples":{"emailOnly":{"summary":"Create a contact with an email address only","description":"Creates a contact that has only an email address. The email channel gets the default values: **emailType** is **html**, **optInType** is **unknown**, **status** is **subscribed** and **openTracking** is **unknown**.","value":{"identifiers":{"email":"amelia.thornbury@emailsim.io"}}},"fullProfile":{"summary":"Create a contact with data fields, channels, lists, preferences and consent","description":"Creates a contact with an email address, a mobile number and a custom identifier. The request sets data fields and email channel properties, subscribes the contact to SMS, adds the contact to a list, opts the contact into a marketing preference and adds a consent record.<br><br>\n**Note:** The custom identifier (`loyaltyId` in this example), the list ID and the preference ID must already exist in your account.","value":{"identifiers":{"email":"hana.velloway@emailsim.io","mobileNumber":"447700900912","loyaltyId":"LOY-000912"},"dataFields":{"FIRSTNAME":"Hana","LASTNAME":"Velloway","GENDER":"female","LOYALTYTIER":"Gold"},"channelProperties":{"email":{"emailType":"html","optInType":"double","openTracking":"subscribed"},"sms":{"status":"subscribed"}},"lists":[345579],"preferences":[{"id":1021,"isOptedIn":true}],"consentRecords":[{"text":"Yes, I would like to receive the monthly newsletter and special offers by email","dateTimeConsented":"2026-09-14T10:42:17Z","url":"https://www.example.com/newsletter/signup","ipAddress":"203.0.113.48","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36"}]}},"verifiedDoubleOptIn":{"summary":"Create a contact that must confirm their email subscription","description":"Creates a contact with the opt-in type **verifiedDouble**. The contact is sent an email to confirm their subscription. Until the contact confirms, the email channel status is **pendingOptIn**.","value":{"identifiers":{"email":"tobias.wrenfield@emailsim.io"},"dataFields":{"FIRSTNAME":"Tobias","LASTNAME":"Wrenfield"},"channelProperties":{"email":{"optInType":"verifiedDouble"}},"lists":[345579]}},"smsOnly":{"summary":"Create a contact with a mobile number only","description":"Creates a contact that has only a mobile number and subscribes the contact to SMS. The contact does not have an email channel.<br><br>\n**Note:** Send the mobile number in [E.164 format](https://en.wikipedia.org/wiki/E.164) without the leading **+**.","value":{"identifiers":{"mobileNumber":"447700900527"},"dataFields":{"FIRSTNAME":"Rohan"},"channelProperties":{"sms":{"status":"subscribed"}}}}}}},"required":true},"responses":{"201":{"description":"Contact created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/contact"},"examples":{"fullProfile":{"summary":"Contact created with data fields, channels, lists, preferences and consent","description":"The response to the **fullProfile** request example. The response contains the full contact.<br><br>\n**Note:**\n* Every data field in your account is returned. Data fields that have no value are **null**. This example shows only some of them.\n* Every identifier in your account is returned. Identifiers that have no value are empty.","value":{"contactId":35214120,"status":"subscribed","created":"2026-10-16T13:17:36.4759674Z","updated":"2026-10-16T13:17:36.4759674Z","identifiers":{"email":"hana.velloway@emailsim.io","mobileNumber":"447700900912","loyaltyId":"LOY-000912"},"dataFields":{"FIRSTNAME":"Hana","GENDER":"female","LASTNAME":"Velloway","LOYALTYTIER":"Gold"},"channelProperties":{"email":{"status":"subscribed","emailType":"html","optInType":"double","openTracking":"subscribed"},"sms":{"status":"subscribed","countryCode":"GB"},"whatsApp":{"status":"noSubscription"}},"lists":[{"id":345579,"name":"Monthly newsletter","status":"subscribed"}],"preferences":[{"publicName":"Special offers","privateName":"specialOffers","id":1021,"isOptedIn":true}],"consentRecords":[{"text":"Yes, I would like to receive the monthly newsletter and special offers by email","dateTimeConsented":"2026-09-14T10:42:17Z","url":"https://www.example.com/newsletter/signup","ipAddress":"203.0.113.48","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36","dateTimeCreated":"2026-10-16T13:17:36"}]}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"examples":{"invalidIdentifier":{"summary":"Identifier value is not valid","value":{"errorCode":"contacts:invalidId","description":"The id value '123646' is invalid for the identifier 'email'"}},"identifierMissing":{"summary":"No email address or mobile number","description":"The request does not contain **identifiers.email** or **identifiers.mobileNumber**, so the contact cannot be created.","value":{"errorCode":"contacts:identifierMissing","description":"You must provide at least one identifier for email (email) or mobile number (mobileNumber)."}}}}}},"401":{"description":"Unauthorized"},"409":{"description":"Identifier conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"example":{"errorCode":"contacts:idAlreadyExists","description":"The id value 'jane.doe@emailsim.io' for the identifier 'email' already exists. All identifiers must be unique!"}}}}}}},"/contacts/v3/delete":{"post":{"summary":"Delete multiple contacts","description":"Async deletes multiple contacts using whichever identifier you wish.","operationId":"deleteContacts","parameters":[{"name":"x-ddg-integration-token","in":"header","description":"If you are a partner of Dotdigital and have a [verified integration](https://developer.dotdigital.com/docs/partner-integration-verification) then include your [integration tracking token](https://developer.dotdigital.com/docs/verified-integration-tracking) here.","required":false,"schema":{"type":"string","format":"uuid","example":"5a96bc79-19a7-4544-973b-e2da0c9136f9"}}],"requestBody":{"description":"The contact references you want to delete","content":{"application/json":{"schema":{"maxItems":5000,"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/contactIdentifier"}},"examples":{"mixedIdentifiers":{"summary":"Delete contacts using different identifiers","description":"Deletes four contacts. Each item identifies one contact with one identifier: **contactId**, **email**, **mobileNumber** or a custom identifier.<br><br>\n**Note:**\n* You can send a maximum of 5000 contacts in one request.\n* The custom identifier (`loyaltyId` in this example) must already exist in your account.\n* The contacts are deleted asynchronously. Use the **deleteId** in the response to get the result with **getDeleteStatus**.","value":[{"contactId":35211876},{"email":"marcus.oldacre@emailsim.io"},{"mobileNumber":"447700900527"},{"loyaltyId":"LOY-000433"}]}}}},"required":true},"responses":{"202":{"description":"Delete request accepted","content":{"application/json":{"schema":{"type":"object","properties":{"deleteId":{"type":"string","example":"c4920aee-3add-44e4-b8c0-dcbfacbfee40"}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"example":{"errorCode":"contacts:noContactsSpecified","description":"You must specify 1 or more contacts to be deleted!"}}}},"401":{"description":"Unauthorized"},"429":{"description":"Too many bulk delete jobs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"example":{"errorCode":"contacts:tooManyBulkDeleteJobs","description":"Your bulk delete request cannot be accepted as too many bulk delete jobs are being processed for you account. Please wait for a bulk delete job to complete and then resubmit."}}}}}}},"/contacts/v3/delete/{deleteId}":{"get":{"summary":"Get the status of a delete contacts job","description":"Gets the status of a delete contacts job and the results if complete.","operationId":"getDeleteStatus","parameters":[{"name":"deleteId","in":"path","description":"The delete job id you want the status for","required":true,"schema":{"type":"string","example":"c4920aee-3add-44e4-b8c0-dcbfacbfee40"}}],"responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"required":["deleteId","status"],"type":"object","properties":{"deleteId":{"type":"string","description":"The delete job request id","example":"c4920aee-3add-44e4-b8c0-dcbfacbfee40"},"status":{"type":"string","enum":["NotStarted","NotFinished","Finished","Failed"]},"summary":{"required":["deletedContacts","invalidEntries","requestedContacts","unknownContacts"],"type":"object","properties":{"requestedContacts":{"type":"integer","description":"The number of contacts requested to be deleted","format":"int32","example":100},"deletedContacts":{"type":"integer","description":"The number of contacts deleted","format":"int32","example":95},"unknownContacts":{"type":"integer","description":"The number of contacts that could not be identified","format":"int32","example":4},"invalidEntries":{"type":"integer","description":"The number of contacts that could not be processed","format":"int32","example":1}}},"deleted":{"type":"array","description":"The contacts that were successfully deleted","items":{"$ref":"#/components/schemas/contactIdentifier"}},"failures":{"type":"array","description":"The contacts that failed to be deleted","items":{"required":["failures","identifier"],"type":"object","properties":{"identifier":{"$ref":"#/components/schemas/contactIdentifier"},"failures":{"type":"array","description":"The reasons the contact failed to import","example":[{"failureCode":"invalidEmail","description":"Invalid value for 'email'"},{"failureCode":"contactNotFound","description":"The contact could not be found"}],"items":{"required":["description","failureCode"],"type":"object","properties":{"failureCode":{"type":"string","description":"The unique failure code for this failure reason","example":"invalidEmail"},"description":{"type":"string","description":"The English reason for the failure","example":"Invalid value for 'email'"}},"description":"A failure reason"}}},"description":"Contact delete failure summary"}}}},"examples":{"notFinished":{"summary":"Delete job still in progress","description":"The delete job has started but has not finished. Call **getDeleteStatus** again later.","value":{"deleteId":"c4920aee-3add-44e4-b8c0-dcbfacbfee40","status":"NotFinished"}},"finishedWithUnknownContact":{"summary":"Delete job finished with one contact not found","description":"The result of the **mixedIdentifiers** request example for **deleteContacts**. Three contacts were deleted. The contact with the mobile number **447700900527** could not be found, so it is in **failures**.","value":{"deleteId":"c4920aee-3add-44e4-b8c0-dcbfacbfee40","status":"Finished","summary":{"requestedContacts":4,"deletedContacts":3,"unknownContacts":1,"invalidEntries":0},"deleted":[{"contactId":35211876},{"email":"marcus.oldacre@emailsim.io"},{"loyaltyId":"LOY-000433"}],"failures":[{"identifier":{"mobileNumber":"447700900527"},"failures":[{"failureCode":"contactNotFound","description":"The contact could not be found"}]}]}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"example":{"errorCode":"contacts:invalidDeleteId","description":"The id value '123646' is not a recognized deletion job identifier"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Delete job not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"example":{"errorCode":"contacts:deleteNotFound","description":"The specified Delete job can’t be found."}}}}}}},"/contacts/v3/import":{"put":{"summary":"Import contact collection","description":"Imports a collection of contacts. Creates contacts if they do not exist and updates contacts if they do. This is an async operation and you will need to check when it is complete by calling **getImportStatus** <br><br>**Note:** It isn't possible to specify the value for the **contactId** field when creating a contact, so it is only used to check for a matching contact when specified.<br><br>**Note:** To create a new contact, its **identifiers** must contain **email** or **mobileNumber**. A contact cannot be created with only a custom identifier. If it has only a custom identifier, it is not imported, and **getImportStatus** shows it in **failures** with the failure code **Invalid Contact**.","operationId":"importContacts","parameters":[{"name":"x-ddg-integration-token","in":"header","description":"If you are a partner of Dotdigital and have a [verified integration](https://developer.dotdigital.com/docs/partner-integration-verification) then include your [integration tracking token](https://developer.dotdigital.com/docs/verified-integration-tracking) here.","required":false,"schema":{"type":"string","format":"uuid","example":"5a96bc79-19a7-4544-973b-e2da0c9136f9"}}],"requestBody":{"description":"Contact data collection","content":{"application/json":{"schema":{"required":["contacts"],"type":"object","properties":{"mergeOption":{"type":"string","description":"Specify how the merging of new data with existing data is handled","example":"overwrite","enum":["overwrite","overwriteIfNotEmpty","overwriteIfEmpty"],"default":"overwrite"},"contacts":{"minItems":1,"type":"array","items":{"$ref":"#/components/schemas/contactRequest"}}}},"examples":{"updateDataAndIdentifiers":{"summary":"Update a contact's data fields and identifiers","description":"Finds each contact by **email** and updates the data fields. The request also adds a mobile number and a custom identifier to each contact.<br><br>\n**Note:** The custom identifier (`loyaltyId` in this example) must already exist in your account.","value":{"mergeOption":"overwrite","contacts":[{"matchIdentifier":"email","identifiers":{"email":"amelia.thornbury@emailsim.io","mobileNumber":"447700900184","loyaltyId":"LOY-000184"},"dataFields":{"FIRSTNAME":"Amelia","LASTNAME":"Thornbury","GENDER":"female","POSTCODE":"ZZ1 4AB"}},{"matchIdentifier":"email","identifiers":{"email":"rohan.castellane@emailsim.io","mobileNumber":"447700900527","loyaltyId":"LOY-000527"},"dataFields":{"FIRSTNAME":"Rohan","LASTNAME":"Castellane","GENDER":"male","POSTCODE":"ZZ9 7QD"}}]}},"unsubscribeFromEmail":{"summary":"Unsubscribe a contact from the email channel","description":"Finds the contact by **email** and sets the email channel status to **unsubscribed**. The contact's data fields, identifiers and other channels do not change.","value":{"contacts":[{"matchIdentifier":"email","identifiers":{"email":"marcus.oldacre@emailsim.io"},"channelProperties":{"email":{"status":"unsubscribed"}}}]}},"setEmailOpenTracking":{"summary":"Set email open tracking for a contact","description":"Finds each contact and sets only the **openTracking** property of the email channel. The first contact allows open tracking and the second contact does not. The email subscription status does not change.","value":{"contacts":[{"matchIdentifier":"email","identifiers":{"email":"priya.halvorsen@emailsim.io"},"channelProperties":{"email":{"openTracking":"subscribed"}}},{"matchIdentifier":"mobileNumber","identifiers":{"mobileNumber":"447700900362"},"channelProperties":{"email":{"openTracking":"unsubscribed"}}}]}},"addConsentRecord":{"summary":"Add a consent record to a contact","description":"Finds the contact by **email** and adds a marketing consent record that was captured on a sign-up form.<br><br>\n**Note:** Each consent record must include **text**, **dateTimeConsented**, **url**, **ipAddress** and **userAgent**. You can send a maximum of 5 consent records for each contact.","value":{"contacts":[{"matchIdentifier":"email","identifiers":{"email":"elodie.marchetti@emailsim.io"},"consentRecords":[{"text":"Yes, I would like to receive the monthly newsletter and special offers by email","dateTimeConsented":"2026-09-14T10:42:17Z","url":"https://www.example.com/newsletter/signup","ipAddress":"203.0.113.48","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36"}]},{"matchIdentifier":"email","identifiers":{"email":"tobias.wrenfield@emailsim.io"},"consentRecords":[{"text":"Yes, I would like to receive the monthly newsletter and special offers by email","dateTimeConsented":"2026-09-15T18:05:52Z","url":"https://www.example.com/newsletter/signup","ipAddress":"2001:db8:85a3::8a2e:370:7334","userAgent":"Mozilla/5.0 (iPhone; CPU iPhone OS 17_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.6 Mobile/15E148 Safari/604.1"}]}]}},"updateDataIdentifiersAndLists":{"summary":"Update a contact's data fields, identifiers and list membership","description":"Finds each contact by the custom identifier **loyaltyId**, updates the data fields and identifiers, and adds the contact to one or more lists. If the contact does not exist, it is created.<br><br>\n**Note:** The custom identifier and the list IDs must already exist in your account. The contact is added to the lists you specify; it is not removed from other lists.","value":{"mergeOption":"overwriteIfNotEmpty","contacts":[{"matchIdentifier":"loyaltyId","identifiers":{"loyaltyId":"LOY-000912","email":"hana.velloway@emailsim.io","mobileNumber":"447700900912"},"dataFields":{"FIRSTNAME":"Hana","LASTNAME":"Velloway","GENDER":"female","LOYALTYTIER":"Gold"},"lists":[345579,345612]},{"matchIdentifier":"loyaltyId","identifiers":{"loyaltyId":"LOY-000433","email":"declan.ashworth@emailsim.io"},"dataFields":{"FIRSTNAME":"Declan","LASTNAME":"Ashworth","GENDER":"male","LOYALTYTIER":"Silver"},"lists":[345579]}]}},"mixedMatchIdentifiers":{"summary":"Import contacts that use different match identifiers","description":"Finds the first contact by **email**, the second contact by **mobileNumber** and the third contact by **contactId**. The third contact gets a new email address.","value":{"mergeOption":"overwrite","contacts":[{"matchIdentifier":"email","identifiers":{"email":"jane.doe@emailsim.io"},"dataFields":{"FIRSTNAME":"Jane","LASTNAME":"Doe","GENDER":"female"}},{"matchIdentifier":"mobileNumber","identifiers":{"email":"john.doe@emailsim.io","mobileNumber":"447123123123"},"dataFields":{"FIRSTNAME":"John","LASTNAME":"Doe","GENDER":"male"},"channelProperties":{"email":{"emailType":"html"}}},{"matchIdentifier":"contactId","identifiers":{"contactId":123456,"email":"my-new-email@emailsim.io"}}]}}}}},"required":true},"responses":{"202":{"description":"Import processing","content":{"application/json":{"schema":{"type":"object","properties":{"importId":{"type":"string","example":"d7de900d-d337-43f6-b1e1-c8ec73e1a434"}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"example":{"errorCode":"contacts:badJson","description":"The request JSON is badly formed"}}}},"401":{"description":"Unauthorized"},"429":{"description":"Too many import requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"example":{"errorCode":"contacts:tooManyActiveImports","description":"Your import request cannot be accepted as too many imports are being processed for you account. Please wait for an import to complete and then resubmit."}}}}}}},"/contacts/v3/import/{importId}":{"get":{"summary":"Get the status of a contacts import request","description":"Gets the status of a contacts import request and the results if available.<br><br>**Note:** When importing, contacts are created or updated but if any associated data sets fail to import then details of these are included in the **failures** results","operationId":"getImportStatus","parameters":[{"name":"importId","in":"path","description":"The import id you want the status for","required":true,"schema":{"type":"string","example":"d7de900d-d337-43f6-b1e1-c8ec73e1a434"}}],"responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"required":["importId","status"],"type":"object","properties":{"importId":{"type":"string","description":"The import id you want the status for","example":"d7de900d-d337-43f6-b1e1-c8ec73e1a434"},"status":{"type":"string","enum":["Finished","NotFinished","RejectedByWatchdog","Failed","ExceedsAllowedContactLimit"]},"summary":{"type":"object","properties":{"newContacts":{"type":"integer","description":"Number of new contacts added","format":"int32","example":10},"updatedContacts":{"type":"integer","description":"Number of contacts updated","format":"int32","example":14},"globallySuppressed":{"type":"integer","description":"Number of contacts that are suppressed at the account level, so can't be updated","format":"int32","example":0},"invalidEntries":{"type":"integer","description":"Number of contacts with invalid data, so can't be updated or created","format":"int32","example":2},"duplicateIdentifiers":{"type":"integer","description":"Number of contacts with a duplicate identifier, so can't be updated or created","format":"int32","example":2}}},"created":{"type":"array","description":"Contacts that were successfully created","items":{"$ref":"#/components/schemas/contactReference"}},"updated":{"type":"array","description":"Contacts that were successfully updated","items":{"$ref":"#/components/schemas/contactReference"}},"failures":{"type":"array","description":"Contacts that were not imported. **contactId** is included if the contact matched an existing contact, or if you sent it in the request.","example":[{"contactId":35213007,"identifiers":{"email":"priya.halvorsen@emailsim.io","mobileNumber":"447700900362"},"failures":[{"failureCode":"Invalid Contact","description":"Cannot update: channel data belongs to another contact."}]},{"identifiers":{"email":"","mobileNumber":"","loyaltyId":"LOY-000777"},"failures":[{"failureCode":"Invalid Contact","description":"Cannot update: A contact cannot be created with only custom identifiers."}]}],"items":{"required":["failures","identifiers"],"type":"object","properties":{"contactId":{"$ref":"#/components/schemas/contactId"},"matchIdentifier":{"maxLength":50,"minLength":1,"pattern":"(^[-A-Za-z0-9_]{1,50}$)","type":"string","description":"Which identifier in the provided `identifiers` was used to match the contact to an existing record. This can also include the name of a custom identifier.","example":"mobileNumber"},"identifiers":{"$ref":"#/components/schemas/identifiers"},"failures":{"type":"array","description":"Reasons the contact failed to import","items":{"required":["description","failureCode"],"type":"object","properties":{"failureCode":{"type":"string","description":"Unique failure code for this failure reason","example":"invalidEmail"},"description":{"type":"string","description":"Description of the reason for the failure","example":"Invalid value for 'email'"}},"description":"A failure reason"}}},"description":"Contact import failure summary"}}}},"examples":{"notFinished":{"summary":"Import still in progress","description":"The import has not finished. Call **getImportStatus** again later. The response does not include **summary** until the import has finished.","value":{"importId":"d7de900d-d337-43f6-b1e1-c8ec73e1a434","status":"NotFinished"}},"finishedWithFailures":{"summary":"Import finished with some contacts not imported","description":"An import of four contacts. One contact was created, one contact was updated and two contacts were not imported.<br><br>\n**Note:**\n* In **created** and **updated**, **identifiers** always contains **email** and **mobileNumber**, with an empty value if the contact does not have one. Custom identifiers are only included if you sent them.\n* In **failures**, **contactId** is included if the contact matched an existing contact, or if you sent it in the request.","value":{"importId":"d7de900d-d337-43f6-b1e1-c8ec73e1a434","status":"Finished","summary":{"newContacts":1,"updatedContacts":1,"globallySuppressed":0,"invalidEntries":2,"duplicateIdentifiers":0},"created":[{"contactId":35214388,"identifiers":{"email":"tobias.wrenfield@emailsim.io","mobileNumber":""}}],"updated":[{"contactId":35212498,"identifiers":{"email":"marcus.oldacre@emailsim.io","mobileNumber":""}}],"failures":[{"contactId":35213007,"identifiers":{"email":"priya.halvorsen@emailsim.io","mobileNumber":"447700900362","loyaltyId":"LOY-000362"},"failures":[{"failureCode":"Invalid Contact","description":"Cannot update: channel data belongs to another contact."}]},{"contactId":35212311,"identifiers":{"email":"amelia.thornbury@emailsim.io","mobileNumber":"447700900185"},"failures":[{"failureCode":"Invalid Contact","description":"Cannot update a suppressed channel with a new identifier."}]}]}},"onlyCustomIdentifier":{"summary":"Import finished with a contact that has only a custom identifier","description":"The import had one new contact with only the custom identifier **loyaltyId**. A contact cannot be created without an email address or mobile number, so the contact is in **failures**. When no contacts were created or updated, **created** and **updated** are empty arrays.","value":{"importId":"188eb627-df77-4130-a3cf-06440365d065","status":"Finished","summary":{"newContacts":0,"updatedContacts":0,"globallySuppressed":0,"invalidEntries":1,"duplicateIdentifiers":0},"created":[],"updated":[],"failures":[{"identifiers":{"email":"","mobileNumber":"","loyaltyId":"LOY-000777"},"failures":[{"failureCode":"Invalid Contact","description":"Cannot update: A contact cannot be created with only custom identifiers."}]}]}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"example":{"errorCode":"contacts:invalidId","description":"The id value '123646' is invalid for the identifier 'email'"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Import request not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"example":{"errorCode":"contacts:importNotFound","description":"The import request 'd7de900d-d337-43f6-b1e1-c8ec73e1a434' could not be found!"}}}}}}},"/contacts/v3/{identifier}/{value}":{"get":{"summary":"Get a contact by an identifier","description":"Get a contact's details using a specific identifier.<br><br>\n**Note:**\n* For a deleted contact, this call returns **404 Not Found**. To get deleted contacts, use **getContacts**.\n* If the contact's mobile number was deleted, **mobileNumber** has the value **deleted**.","operationId":"getContact","parameters":[{"name":"identifier","in":"path","description":"The field to use to uniquely identify the contact. This can be a custom identifier or a contact identifer of **contactId**, **email** or **mobileNumber**","required":true,"schema":{"maxLength":50,"minLength":1,"pattern":"(^[-A-Za-z0-9_]{1,50}$)","type":"string"},"examples":{"email":{"summary":"Email address","value":"email"},"mobileNumber":{"summary":"Mobile number","value":"mobileNumber"},"contactId":{"summary":"Contact ID","value":"contactId"},"customIdentifier":{"summary":"Custom identifier","value":"loyaltyId"}}},{"name":"value","in":"path","description":"The unique value to identify the contact.<br>***Note:** Must be the same type as the **identifier***","required":true,"schema":{"maxLength":256,"minLength":1,"type":"string"},"examples":{"email":{"summary":"Email address (use with the email identifier)","value":"amelia.thornbury@emailsim.io"},"mobileNumber":{"summary":"Mobile number (use with the mobileNumber identifier)","value":"447700900184"},"contactId":{"summary":"Contact ID (use with the contactId identifier)","value":"35212311"},"customIdentifier":{"summary":"Custom identifier value (use with the loyaltyId identifier)","value":"LOY-000184"}}},{"name":"x-ddg-integration-token","in":"header","description":"If you are a partner of Dotdigital and have a [verified integration](https://developer.dotdigital.com/docs/partner-integration-verification) then include your [integration tracking token](https://developer.dotdigital.com/docs/verified-integration-tracking) here.","required":false,"schema":{"type":"string","format":"uuid","example":"5a96bc79-19a7-4544-973b-e2da0c9136f9"}}],"responses":{"200":{"description":"Successful operation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/contact"},"examples":{"fullContact":{"summary":"A contact with all data sets","description":"The response contains the full contact.<br><br>\n**Note:**\n* Every data field in your account is returned. Data fields that have no value are **null**. This example shows only some of them.\n* Every identifier in your account is returned. Identifiers that have no value are empty.","value":{"contactId":35212311,"status":"subscribed","created":"2025-03-04T09:15:22.483","updated":"2026-10-12T14:03:51.27","identifiers":{"email":"amelia.thornbury@emailsim.io","mobileNumber":"447700900184","loyaltyId":"LOY-000184"},"dataFields":{"FIRSTNAME":"Amelia","FULLNAME":"Amelia Thornbury","GENDER":"female","LASTNAME":"Thornbury","LOYALTYTIER":"Gold","POSTCODE":"ZZ1 4AB","TOTAL_SPEND":245.5},"channelProperties":{"email":{"status":"subscribed","emailType":"html","optInType":"double","openTracking":"subscribed"},"sms":{"status":"subscribed","countryCode":"GB"},"whatsApp":{"status":"noSubscription"}},"lists":[{"id":345579,"name":"Monthly newsletter","status":"subscribed"},{"id":345612,"name":"Loyalty members","status":"subscribed"}],"preferences":[{"publicName":"Special offers","privateName":"specialOffers","id":1021,"isOptedIn":true}],"consentRecords":[{"text":"Yes, I would like to receive the monthly newsletter and special offers by email","dateTimeConsented":"2026-09-14T10:42:17Z","url":"https://www.example.com/newsletter/signup","ipAddress":"203.0.113.48","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36","dateTimeCreated":"2026-09-14T10:42:19.4815562Z"}]}},"mobileNumberDeleted":{"summary":"A contact whose mobile number was deleted","description":"The mobile number of this contact was deleted, so **mobileNumber** has the value **deleted**. Its SMS and WhatsApp channels were deleted with it, so they are not included. The contact is not in a list and has no preferences or consent records, so **lists**, **preferences** and **consentRecords** are not included.","value":{"contactId":35212498,"status":"subscribed","created":"2025-06-19T17:42:08.9","updated":"2026-10-14T16:20:31.05","identifiers":{"email":"marcus.oldacre@emailsim.io","mobileNumber":"deleted","loyaltyId":""},"dataFields":{"FIRSTNAME":"Marcus","GENDER":"male","LASTNAME":"Oldacre"},"channelProperties":{"email":{"status":"subscribed","emailType":"html","optInType":"single","openTracking":"unknown"}}}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"example":{"errorCode":"contacts:invalidId","description":"The id value '123646' is invalid for the identifier 'email'"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Contact not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"example":{"errorCode":"contacts:contactNotFound","description":"The following contacts could not be found.","details":[{"item":"unknown@emailsim.io","description":"Not found using the identifier 'Email'."}]}}}}}},"put":{"summary":"Replace a contact","description":"Replaces a contact with the data passed in the request.<br><br>\n  **Note:**\n  * This call **replaces** the contact's **identifiers**, **dataFields**, **lists** and **preferences**. Identifiers and data fields you do not specify are removed, and the contact is removed from lists and preferences you do not specify. If you do not specify **mobileNumber**, the contact's mobile number is deleted, and **mobileNumber** then has the value **deleted**.\n  * This call does **not** replace the email channel properties. If the contact already has an email channel, the **emailType**, **optInType**, **status** and **openTracking** properties you do not specify remain unaltered. Defaults are only applied when the contact does not have an email channel yet.\n  * This call does **not** change consent records. The contact's existing consent records are kept. To add consent records, use **importContact** (PATCH) or **importContacts**.\n  * To change only some fields, use the PATCH call.","operationId":"replaceContact","parameters":[{"name":"identifier","in":"path","description":"The field to use to uniquely identify the contact. This can be a custom identifier or a contact identifer of **contactId**, **email** or **mobileNumber**","required":true,"schema":{"maxLength":50,"minLength":1,"pattern":"(^[-A-Za-z0-9_]{1,50}$)","type":"string"},"examples":{"email":{"summary":"Email address","value":"email"},"mobileNumber":{"summary":"Mobile number","value":"mobileNumber"},"contactId":{"summary":"Contact ID","value":"contactId"},"customIdentifier":{"summary":"Custom identifier","value":"loyaltyId"}}},{"name":"value","in":"path","description":"The unique value to identify the contact.<br>***Note:** Must be the same type as the **identifier***","required":true,"schema":{"maxLength":256,"minLength":1,"type":"string"},"examples":{"email":{"summary":"Email address (use with the email identifier)","value":"amelia.thornbury@emailsim.io"},"mobileNumber":{"summary":"Mobile number (use with the mobileNumber identifier)","value":"447700900184"},"contactId":{"summary":"Contact ID (use with the contactId identifier)","value":"35212311"},"customIdentifier":{"summary":"Custom identifier value (use with the loyaltyId identifier)","value":"LOY-000184"}}},{"name":"x-ddg-integration-token","in":"header","description":"If you are a partner of Dotdigital and have a [verified integration](https://developer.dotdigital.com/docs/partner-integration-verification) then include your [integration tracking token](https://developer.dotdigital.com/docs/verified-integration-tracking) here.","required":false,"schema":{"type":"string","format":"uuid","example":"5a96bc79-19a7-4544-973b-e2da0c9136f9"}}],"requestBody":{"description":"The contact data. **Note:** It is not possible to modify the **contactId** field","content":{"application/json":{"schema":{"$ref":"#/components/schemas/replaceContactRequest"},"examples":{"replaceDataAndLists":{"summary":"Replace a contact's identifiers, data fields, lists and preferences","description":"Replaces the contact found by the path parameters. After the call, the contact has only the identifiers, data fields, lists and preferences in the request.<br>\n**Request:** `PUT /contacts/v3/email/amelia.thornbury@emailsim.io`<br><br>\n**Note:** Because this call replaces the contact, send every identifier, data field, list and preference that you want to keep. Consent records are always kept.","value":{"identifiers":{"email":"amelia.thornbury@emailsim.io","mobileNumber":"447700900184","loyaltyId":"LOY-000184"},"dataFields":{"FIRSTNAME":"Amelia","LASTNAME":"Thornbury","GENDER":"female","LOYALTYTIER":"Platinum"},"lists":[345579,345612],"preferences":[{"id":1021,"isOptedIn":true}]}},"removeMobileNumber":{"summary":"Replace a contact and remove its mobile number","description":"The request does not include **mobileNumber**, so the contact's mobile number is deleted. After the call, **mobileNumber** has the value **deleted**, and the contact's SMS and WhatsApp channels are not included in the response.<br>\n**Request:** `PUT /contacts/v3/email/marcus.oldacre@emailsim.io`<br><br>\n**Note:** Because this call replaces the contact, send every identifier, data field, list and preference that you want to keep. Consent records are always kept.","value":{"identifiers":{"email":"marcus.oldacre@emailsim.io"},"dataFields":{"FIRSTNAME":"Marcus","LASTNAME":"Oldacre","GENDER":"male"},"lists":[345579]}}}}},"required":true},"responses":{"200":{"description":"Contact replaced","content":{"application/json":{"schema":{"$ref":"#/components/schemas/contact"},"examples":{"replaceDataAndLists":{"summary":"Contact after the identifiers, data fields, lists and preferences were replaced","description":"The response to the **replaceDataAndLists** request example. The response contains the full contact.<br><br>\n**Note:**\n* Every data field in your account is returned. Data fields that have no value are **null**. This example shows only some of them.\n* Every identifier in your account is returned. Identifiers that have no value are empty.\n* Lists, preferences and consent records are only included if the contact has them.","value":{"contactId":35212311,"status":"subscribed","created":"2025-03-04T09:15:22.483","updated":"2026-10-16T14:07:04.217","identifiers":{"email":"amelia.thornbury@emailsim.io","mobileNumber":"447700900184","loyaltyId":"LOY-000184"},"dataFields":{"FIRSTNAME":"Amelia","GENDER":"female","LASTNAME":"Thornbury","LOYALTYTIER":"Platinum"},"channelProperties":{"email":{"status":"subscribed","emailType":"html","optInType":"double","openTracking":"subscribed"},"sms":{"status":"subscribed","countryCode":"GB"},"whatsApp":{"status":"noSubscription"}},"lists":[{"id":345579,"name":"Monthly newsletter","status":"subscribed"},{"id":345612,"name":"Loyalty members","status":"subscribed"}],"preferences":[{"publicName":"Special offers","privateName":"specialOffers","id":1021,"isOptedIn":true}]}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"example":{"errorCode":"contacts:invalidId","description":"The id value '123646' is invalid for the identifier 'email'"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Contact not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"example":{"errorCode":"contacts:contactNotFound","description":"The following contacts could not be found.","details":[{"item":"35219999","description":"Not found using the identifier 'ContactId'."}]}}}}}},"delete":{"summary":"Deletes a contact using a specific identifier","description":"Delete a contact using a specific identifier","operationId":"deleteContact","parameters":[{"name":"identifier","in":"path","description":"The field to use to uniquely identify the contact. This can be a custom identifier or a contact identifer of **contactId**, **email** or **mobileNumber**","required":true,"schema":{"maxLength":50,"minLength":1,"pattern":"(^[-A-Za-z0-9_]{1,50}$)","type":"string"},"examples":{"email":{"summary":"Email address","value":"email"},"mobileNumber":{"summary":"Mobile number","value":"mobileNumber"},"contactId":{"summary":"Contact ID","value":"contactId"},"customIdentifier":{"summary":"Custom identifier","value":"loyaltyId"}}},{"name":"value","in":"path","description":"The unique value to identify the contact.<br>***Note:** Must be the same type as the **identifier***","required":true,"schema":{"maxLength":256,"minLength":1,"type":"string"},"examples":{"email":{"summary":"Email address (use with the email identifier)","value":"amelia.thornbury@emailsim.io"},"mobileNumber":{"summary":"Mobile number (use with the mobileNumber identifier)","value":"447700900184"},"contactId":{"summary":"Contact ID (use with the contactId identifier)","value":"35212311"},"customIdentifier":{"summary":"Custom identifier value (use with the loyaltyId identifier)","value":"LOY-000184"}}},{"name":"x-ddg-integration-token","in":"header","description":"If you are a partner of Dotdigital and have a [verified integration](https://developer.dotdigital.com/docs/partner-integration-verification) then include your [integration tracking token](https://developer.dotdigital.com/docs/verified-integration-tracking) here.","required":false,"schema":{"type":"string","format":"uuid","example":"5a96bc79-19a7-4544-973b-e2da0c9136f9"}}],"responses":{"200":{"description":"Contact deleted","content":{"application/json":{"schema":{"required":["contactId"],"type":"object","properties":{"contactId":{"$ref":"#/components/schemas/contactId"}},"description":"The contact id of the deleted contact"},"examples":{"contactDeleted":{"summary":"Contact deleted","description":"Returns the **contactId** of the deleted contact.<br>\n**Request:** `DELETE /contacts/v3/email/marcus.oldacre@emailsim.io`<br><br>\n**Note:** After the call, **getContact** and **deleteContact** return **404 Not Found** for this contact, and **getContacts** returns it with the status **deleted**.","value":{"contactId":35212498}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"example":{"errorCode":"contacts:invalidId","description":"The id value '123646' is invalid for the identifier 'email'"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Contact not found, or the contact is already deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"example":{"errorCode":"contacts:contactNotFound","description":"The following contacts could not be found.","details":[{"item":"35219999","description":"Not found using the identifier 'ContactId'."}]}}}}}},"patch":{"summary":"Import a single contact","description":"Imports a single contact; if it is an existing contact it updates the contact with just the fields passed in the request with a choice of how to handle the merging of data, otherwise it creates a new contact.<br><br>\n**Note:** To create a new contact, the request body must contain **identifiers.email** or **identifiers.mobileNumber**, even if you use the same identifier in the path. If it does not, the call returns **400 Bad request** with the error code **contacts:identifierMissing**.","operationId":"importContact","parameters":[{"name":"identifier","in":"path","description":"The field to use to uniquely identify the contact. This can be a custom identifier or a contact identifer of **contactId**, **email** or **mobileNumber**","required":true,"schema":{"maxLength":50,"minLength":1,"pattern":"(^[-A-Za-z0-9_]{1,50}$)","type":"string"},"examples":{"email":{"summary":"Email address","value":"email"},"mobileNumber":{"summary":"Mobile number","value":"mobileNumber"},"contactId":{"summary":"Contact ID","value":"contactId"},"customIdentifier":{"summary":"Custom identifier","value":"loyaltyId"}}},{"name":"value","in":"path","description":"The unique value to identify the contact.<br>***Note:** Must be the same type as the **identifier***","required":true,"schema":{"maxLength":256,"minLength":1,"type":"string"},"examples":{"email":{"summary":"Email address (use with the email identifier)","value":"amelia.thornbury@emailsim.io"},"mobileNumber":{"summary":"Mobile number (use with the mobileNumber identifier)","value":"447700900184"},"contactId":{"summary":"Contact ID (use with the contactId identifier)","value":"35212311"},"customIdentifier":{"summary":"Custom identifier value (use with the loyaltyId identifier)","value":"LOY-000184"}}},{"name":"x-ddg-integration-token","in":"header","description":"If you are a partner of Dotdigital and have a [verified integration](https://developer.dotdigital.com/docs/partner-integration-verification) then include your [integration tracking token](https://developer.dotdigital.com/docs/verified-integration-tracking) here.","required":false,"schema":{"type":"string","format":"uuid","example":"5a96bc79-19a7-4544-973b-e2da0c9136f9"}},{"name":"merge-option","in":"query","description":"Set the behavior of how the new data should be merged into existing contacts.","required":false,"schema":{"type":"string","example":"overwrite","enum":["overwrite","overwrite-if-not-empty","overwrite-if-empty"],"default":"overwrite"}}],"requestBody":{"description":"The contact fields to update. **Note:** It is not possible to modify the **contactId** field","content":{"application/json":{"schema":{"$ref":"#/components/schemas/updateContactRequest"},"examples":{"updateDataAndIdentifiers":{"summary":"Update a contact's data fields and identifiers","description":"Updates the data fields of the contact and adds a mobile number and a custom identifier.<br>\n**Request:** `PATCH /contacts/v3/email/amelia.thornbury@emailsim.io`<br><br>\n**Note:** The custom identifier (`loyaltyId` in this example) must already exist in your account.","value":{"identifiers":{"mobileNumber":"447700900184","loyaltyId":"LOY-000184"},"dataFields":{"FIRSTNAME":"Amelia","LASTNAME":"Thornbury","GENDER":"female","POSTCODE":"ZZ1 4AB"}}},"unsubscribeFromEmail":{"summary":"Unsubscribe a contact from the email channel","description":"Sets the email channel status of the contact to **unsubscribed**. The data fields, identifiers and other channels of the contact do not change.<br>\n**Request:** `PATCH /contacts/v3/email/marcus.oldacre@emailsim.io`","value":{"channelProperties":{"email":{"status":"unsubscribed"}}}},"setEmailOpenTracking":{"summary":"Set email open tracking for a contact","description":"Sets only the **openTracking** property of the email channel, so that you are allowed to track email opens for the contact. The email subscription status does not change.<br>\n**Request:** `PATCH /contacts/v3/mobileNumber/447700900362`","value":{"channelProperties":{"email":{"openTracking":"subscribed"}}}},"addConsentRecord":{"summary":"Add a consent record to a contact","description":"Adds a marketing consent record that was captured on a sign-up form.<br>\n**Request:** `PATCH /contacts/v3/email/elodie.marchetti@emailsim.io`<br><br>\n**Note:** Each consent record must include **text**, **dateTimeConsented**, **url**, **ipAddress** and **userAgent**. You can send a maximum of 5 consent records.","value":{"consentRecords":[{"text":"Yes, I would like to receive the monthly newsletter and special offers by email","dateTimeConsented":"2026-09-14T10:42:17Z","url":"https://www.example.com/newsletter/signup","ipAddress":"203.0.113.48","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36"}]}},"updateDataIdentifiersAndLists":{"summary":"Update a contact's data fields, identifiers and list membership","description":"Finds the contact by the custom identifier **loyaltyId**, updates the data fields and identifiers, and adds the contact to two lists. If the contact does not exist, it is created.<br>\n**Request:** `PATCH /contacts/v3/loyaltyId/LOY-000912?merge-option=overwrite`<br><br>\n**Note:** The custom identifier and the list IDs must already exist in your account. The contact is added to the lists you specify; it is not removed from other lists.","value":{"identifiers":{"email":"hana.velloway@emailsim.io","mobileNumber":"447700900912"},"dataFields":{"FIRSTNAME":"Hana","LASTNAME":"Velloway","GENDER":"female","LOYALTYTIER":"Gold"},"lists":[345579,345612]}},"resubscribeEmail":{"summary":"Resubscribe a contact to email with a confirmation email","description":"Sets the email channel status to **subscribed** and sends the contact a resubscription confirmation email in English. After the contact confirms, they are sent to the URL in **redirectUrlAfterChallenge**. The data fields, identifiers, lists and preferences of the contact do not change.<br>\n**Request:** `PATCH /contacts/v3/email/priya.halvorsen@emailsim.io`<br><br>\n**Note:** To resubscribe the contact without a confirmation email, set **resubscribeWithNoChallenge** to **true**.","value":{"channelProperties":{"email":{"status":"subscribed","resubscribeOptions":{"resubscribeWithNoChallenge":false,"preferredLocale":"en-EN","redirectUrlAfterChallenge":"https://www.example.com/newsletter/resubscribed"}}}}},"createNewContact":{"summary":"Create a contact if it does not exist","description":"No contact has this email address, so a new contact is created and the call returns **201 Created**.<br>\n**Request:** `PATCH /contacts/v3/email/tobias.wrenfield@emailsim.io`<br><br>\n**Note:** To create a contact, the request body must contain **identifiers.email** or **identifiers.mobileNumber**, even if you use the same identifier in the path.","value":{"identifiers":{"email":"tobias.wrenfield@emailsim.io"},"dataFields":{"FIRSTNAME":"Tobias","LASTNAME":"Wrenfield"},"channelProperties":{"email":{"optInType":"single"}}}},"updateExistingContact":{"summary":"Update a contact that exists","description":"The contact created by the **createNewContact** example exists, so it is updated and the call returns **200 OK**. Only the **LASTNAME** data field and the **openTracking** email property change.<br>\n**Request:** `PATCH /contacts/v3/email/tobias.wrenfield@emailsim.io?merge-option=overwrite`","value":{"dataFields":{"LASTNAME":"Wrenfield-Hale"},"channelProperties":{"email":{"openTracking":"subscribed"}}}}}}},"required":true},"responses":{"200":{"description":"Contact updated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/contact"},"examples":{"updateExistingContact":{"summary":"Contact updated","description":"The response to the **updateExistingContact** request example. The response contains the full contact. Lists, preferences and consent records are only included if the contact has them.<br><br>\n**Note:**\n* Every data field in your account is returned. Data fields that have no value are **null**. This example shows only some of them.\n* Every identifier in your account is returned. Identifiers that have no value are empty.","value":{"contactId":35214388,"status":"subscribed","created":"2026-10-16T14:30:07.377","updated":"2026-10-16T14:30:41.267","identifiers":{"email":"tobias.wrenfield@emailsim.io","mobileNumber":"","loyaltyId":""},"dataFields":{"FIRSTNAME":"Tobias","LASTNAME":"Wrenfield-Hale"},"channelProperties":{"email":{"status":"subscribed","emailType":"html","optInType":"single","openTracking":"subscribed"}}}}}}}},"201":{"description":"Contact created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/contact"},"examples":{"createNewContact":{"summary":"Contact created","description":"The response to the **createNewContact** request example. The response contains the full contact. The email channel gets the default values for the properties that were not sent.<br><br>\n**Note:**\n* Every data field in your account is returned. Data fields that have no value are **null**. This example shows only some of them.\n* Every identifier in your account is returned. Identifiers that have no value are empty.","value":{"contactId":35214388,"status":"subscribed","created":"2026-10-16T14:30:07.3760173Z","updated":"2026-10-16T14:30:07.3760173Z","identifiers":{"email":"tobias.wrenfield@emailsim.io","mobileNumber":"","loyaltyId":""},"dataFields":{"FIRSTNAME":"Tobias","LASTNAME":"Wrenfield"},"channelProperties":{"email":{"status":"subscribed","emailType":"html","optInType":"single","openTracking":"unknown"}},"consentRecords":[]}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"examples":{"invalidIdentifier":{"summary":"Identifier value is not valid","value":{"errorCode":"contacts:invalidId","description":"The id value '123646' is invalid for the identifier 'email'"}},"identifierMissing":{"summary":"New contact without an email address or mobile number","description":"The contact does not exist, and the request body does not contain **identifiers.email** or **identifiers.mobileNumber**, so the contact cannot be created.","value":{"errorCode":"contacts:identifierMissing","description":"You must provide at least one identifier for email (email) or mobile number (mobileNumber)."}}}}}},"401":{"description":"Unauthorized"},"409":{"description":"Identifier conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/errorResponse"},"example":{"errorCode":"contacts:idAlreadyExists","description":"The id value 'jane.doe@emailsim.io' for the identifier 'email' already exists. All identifiers must be unique!"}}}}}}}},"components":{"schemas":{"optInType":{"type":"string","description":"Channel opt-in type for the contact","example":"double","enum":["unknown","single","double","verifiedDouble"]},"status":{"type":"string","description":"The opt in status for the contact. Only **getContacts** returns contacts with the status **deleted**.","example":"subscribed","enum":["subscribed","unsubscribed","pendingOptIn","deleted","suppressed","binned","noSubscription"]},"preference":{"required":["id","isOptedIn"],"type":"object","properties":{"id":{"type":"integer","description":"ID of the preference","format":"int32","example":1},"isOptedIn":{"type":"boolean","description":"Specify whether the contact is opted into this preference"}}},"preferenceFull":{"required":["id","isOptedIn","privateName","publicName"],"type":"object","properties":{"id":{"type":"integer","description":"ID of the preference","format":"int32","example":1},"isOptedIn":{"type":"boolean","description":"Indicates whether the contact is opted into this preference"},"publicName":{"type":"string","description":"Public name of the marketing preference","example":"Mens fashion"},"privateName":{"type":"string","description":"Private name of the marketing preference","example":"mensFashion01"}}},"consentRecord":{"required":["dateTimeConsented","ipAddress","text","url","userAgent"],"type":"object","properties":{"text":{"minLength":1,"type":"string","description":"Consent text displayed to the contact","example":"Yes, I would like to receive a monthly newsletter"},"dateTimeConsented":{"type":"string","description":"ISO 8601 UTC timestamp for when the consent was obtained","format":"date-time","example":"2023-01-26T21:29:00Z"},"url":{"type":"string","description":"URL the consent was obtained with","format":"uri","example":"http://www.example.com/signup"},"ipAddress":{"oneOf":[{"type":"string","description":"IPv4 address of the contact the consent was obtained for","format":"ipv4","example":"129.168.0.2"},{"type":"string","description":"IPv6 address of the contact the consent was obtained for","format":"ipv6","example":"2b01:1234:136:0:116f:3244:a476:d6b7"}]},"userAgent":{"minLength":1,"type":"string","description":"User agent header of the browser used by the contact the consent was obtained for","example":"Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36"}},"description":"Marketing consent records to be associated with the contact"},"consentRecordsToBeInserted":{"maxItems":5,"minItems":1,"type":"array","description":"The marketing consent records to be associated with the contact","items":{"$ref":"#/components/schemas/consentRecord"}},"consentRecords":{"type":"array","description":"Marketing consent records associated with the contact. If the contact has no consent records, this property is an empty array or is not included, depending on the call.","items":{"example":{"text":"Yes, I would like to receive a monthly newsletter","dateTimeConsented":"2023-01-26T21:29:00","url":"http://www.example.com/signup","ipAddress":"129.168.0.2","userAgent":"Mozilla/5.0 (X11; OpenBSD i386) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36","dateTimeCreated":"2023-01-26T22:55:00"},"allOf":[{"$ref":"#/components/schemas/consentRecord"},{"required":["dateTimeCreated"],"type":"object","properties":{"dateTimeCreated":{"type":"string","description":"UTC timestamp for when the consent record was created, in ISO 8601 format. Depending on the call, it is returned with or without the **Z** time zone designator and fractional seconds. For example, **getContact** returns **2023-07-11T11:19:06.2514793Z** and **createContact** returns **2026-10-16T13:17:36**.","format":"date-time","example":"2023-01-26T22:55:00Z"}}}]}},"contactBasicDetails":{"required":["contactId","created","identifiers","status","updated"],"type":"object","properties":{"contactId":{"$ref":"#/components/schemas/contactId"},"status":{"$ref":"#/components/schemas/status"},"created":{"type":"string","description":"UTC timestamp for when the contact was created, in ISO 8601 format. Depending on the call, it is returned with or without the **Z** time zone designator, and with up to 7 fractional-second digits. For example, **getContacts** returns **2025-03-04T09:15:22.483** and **createContact** returns **2026-10-16T13:17:36.4759674Z**.","format":"date-time"},"updated":{"type":"string","description":"UTC timestamp for when the contact was last updated, in ISO 8601 format. Depending on the call, it is returned with or without the **Z** time zone designator, and with up to 7 fractional-second digits. For example, **getContacts** returns **2026-10-12T14:03:51.27** and **createContact** returns **2026-10-16T13:17:36.4759674Z**.","format":"date-time"},"identifiers":{"$ref":"#/components/schemas/identifiers"}}},"contact":{"allOf":[{"$ref":"#/components/schemas/contactBasicDetails"},{"type":"object","properties":{"dataFields":{"type":"object","additionalProperties":true,"description":"Addtional data fields for the contact specified for the contact","example":{"FIRSTNAME":"John","LASTNAME":"Doe","GENDER":"male"}},"channelProperties":{"type":"object","properties":{"email":{"required":["emailType","openTracking","optInType","status"],"type":"object","properties":{"emailType":{"type":"string","description":"The format the contact expects emails in.","example":"html","enum":["plainText","html"]},"optInType":{"$ref":"#/components/schemas/optInType"},"status":{"$ref":"#/components/schemas/emailChannelStatus"},"openTracking":{"type":"string","description":"Specifies if you are allowed to track email opens for the contact. **unknown** means that no explicit opt-in or opt-out record exists.","example":"subscribed","enum":["unknown","subscribed","unsubscribed"]}},"additionalProperties":false},"sms":{"required":["countryCode","status"],"type":"object","properties":{"countryCode":{"type":"string","description":"[ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) country code the contacts **mobileNumber**","example":"GB"},"status":{"$ref":"#/components/schemas/smsChannelStatus"}},"additionalProperties":false},"whatsApp":{"required":["status"],"type":"object","properties":{"status":{"$ref":"#/components/schemas/whatsAppChannelStatus"}},"additionalProperties":false}},"additionalProperties":false,"description":"Properties associated with each channel for a contact, for example message format or subscription status. A channel the contact does not have, or a channel that was deleted, is not included."},"lists":{"type":"array","description":"Lists the contact belongs to","items":{"required":["id","name","status"],"type":"object","properties":{"id":{"type":"integer","description":"Immutable unique list ID","format":"int32","example":12345},"name":{"maxLength":128,"type":"string","description":"Name of the list","example":"Top customers"},"status":{"type":"string","description":"The list status for the contact","example":"subscribed","enum":["subscribed","suppressed","pending"]}}}},"preferences":{"type":"array","description":"Marketing preferences of the contact. If the contact has no preferences, this property is an empty array or is not included, depending on the call.","items":{"$ref":"#/components/schemas/preferenceFull"}},"consentRecords":{"$ref":"#/components/schemas/consentRecords"}},"description":"A contact"}]},"baseContact":{"allOf":[{"type":"object","properties":{"dataFields":{"type":"object","additionalProperties":true,"description":"Addtional data fields for the contact","example":{"FIRSTNAME":"John","LASTNAME":"Doe","GENDER":"male"}}}},{"$ref":"#/components/schemas/channelProperties"},{"type":"object","properties":{"lists":{"maxItems":100,"minItems":1,"type":"array","description":"List IDs for the lists the contact should be added to","items":{"type":"integer","description":"Unique list id","format":"int32","example":345579}},"preferences":{"minItems":1,"type":"array","description":"Preferences you want to opt the contact into. ***Note:** Only required for preferences and not preference categories*","items":{"$ref":"#/components/schemas/preference"}}}}]},"baseContactRequest":{"allOf":[{"$ref":"#/components/schemas/baseContact"},{"type":"object","properties":{"consentRecords":{"$ref":"#/components/schemas/consentRecordsToBeInserted"}}}]},"createContactRequest":{"allOf":[{"required":["identifiers"],"type":"object","properties":{"identifiers":{"allOf":[{"description":"Identifiers this contact can be referenced by"},{"$ref":"#/components/schemas/identifiers"}]}}},{"$ref":"#/components/schemas/baseContactRequest"}]},"updateContactRequest":{"allOf":[{"type":"object","properties":{"identifiers":{"allOf":[{"description":"Identifiers this contact can be referenced by"},{"$ref":"#/components/schemas/identifiers"}]}}},{"$ref":"#/components/schemas/baseContactRequest"},{"$ref":"#/components/schemas/channelPropertiesWithResubscribe"}]},"replaceContactRequest":{"allOf":[{"required":["identifiers"],"type":"object","properties":{"identifiers":{"allOf":[{"description":"Identifiers this contact can be referenced by"},{"$ref":"#/components/schemas/identifiers"}]}}},{"$ref":"#/components/schemas/baseContact"},{"$ref":"#/components/schemas/channelPropertiesWithResubscribe"}]},"contactRequest":{"allOf":[{"required":["identifiers","matchIdentifier"],"type":"object","properties":{"matchIdentifier":{"type":"string","description":"Specify which identifier in the provided `identifiers` should be used to match the contact to an existing record. This can be a custom identifier or a contact identifier of contactId, email or mobileNumber.","example":"mobileNumber"},"identifiers":{"$ref":"#/components/schemas/contactRequestIdentifiers"}},"description":"The contact data"},{"$ref":"#/components/schemas/baseContactRequest"},{"$ref":"#/components/schemas/channelPropertiesWithResubscribe"}]},"contactRequestIdentifiers":{"type":"object","properties":{"contactId":{"$ref":"#/components/schemas/contactId"},"email":{"$ref":"#/components/schemas/email"},"mobileNumber":{"$ref":"#/components/schemas/mobileNumber"}},"additionalProperties":{"$ref":"#/components/schemas/additionalProperties"},"description":"Identifiers this contact can be referenced by. Use **contactId** only to match an existing contact; you cannot set or change it.","example":{"contactId":35212311,"email":"someone@emailsim.io","mobileNumber":"447123123123","myCustomId":"MYID_12345"}},"contactIdentifier":{"oneOf":[{"maxProperties":1,"required":["contactId"],"type":"object","properties":{"contactId":{"type":"integer","format":"int64","example":12345}},"description":"Contact Id identifier to identify the contact"},{"maxProperties":1,"required":["email"],"type":"object","properties":{"email":{"type":"string","example":"john.doe@emailsim.io"}},"description":"Email identifier to identify the contact"},{"maxProperties":1,"required":["mobileNumber"],"type":"object","properties":{"mobileNumber":{"type":"string","example":"447123123123"}},"description":"Phone number identifier to identify the contact"},{"maxProperties":1,"minProperties":1,"type":"object","not":{"anyOf":[{"required":["contactId"]},{"required":["email"]},{"required":["mobileNumber"]}]},"additionalProperties":{"type":"string","example":"C00000000001"},"description":"Custom identifier to identify the contact. This custom identifier must exist in the account."}]},"channelStatusUpdate":{"type":"string","description":"The subscription status for the channel; if not specified it remains unaltered for existing contacts, and for new contacts this defaults to values defined in _Settings > Contacts > Mobile subscription_","example":"subscribed","enum":["noSubscription","subscribed","unsubscribed","suppressed"]},"emailChannelStatus":{"type":"string","description":"Current status of the email channel for the contact","example":"subscribed","enum":["subscribed","unsubscribed","suppressed","binned","pendingOptIn","softBounced","hardBounced","ispComplained","mailBlocked","directComplaint","spamTrap","blockedLocalPart","sharedSuppression","sharedDomainSuppression","purchased","knownComplainer","knownLitigator","domainSuppression","noMXRecord"]},"whatsAppChannelStatus":{"type":"string","description":"The current status for the WhatsApp channel for this contact","example":"subscribed","enum":["noSubscription","subscribed","unsubscribed","suppressed","binned"]},"smsChannelStatus":{"type":"string","description":"The current status for the SMS channel for this contact","example":"subscribed","enum":["noSubscription","subscribed","unsubscribed","suppressed","binned","bounced"]},"channelProperties":{"type":"object","properties":{"channelProperties":{"type":"object","properties":{"email":{"type":"object","properties":{"emailType":{"type":"string","description":"Format the contact receives emails in.<br>\n* **New contacts, or contacts that do not have an email channel yet:** If not specified, this is set to **html**.\n* **Contacts that already have an email channel:** If not specified, the existing value remains unaltered.<br>\n***Note:** When you import a collection of contacts and one or more contacts in the collection specify **emailType**, then the contacts in the same collection that do not specify it are set to **html**. To keep the existing value, specify **emailType** for each contact, or do not specify it for any contact in the collection.*","example":"html","enum":["plainText","html"]},"optInType":{"type":"string","description":"Email opt-in type for the contact.<br>\n* **New contacts, or contacts that do not have an email channel yet:** If not specified, this is set to **unknown**.\n* **Contacts that already have an email channel:** If not specified, the existing value remains unaltered.<br>\n***Note:** If you set this to **verifiedDouble**, or the account setting *Enforce double opt-in for all signups, including bulk uploads* is on, the contact is sent an email to confirm their subscription. Until the contact confirms, the email channel status is **pendingOptIn** and **optInType** remains **unknown**.*","example":"double","enum":["unknown","single","double","verifiedDouble"]},"status":{"type":"string","description":"The subscription status for the email channel.<br>\n* **New contacts, or contacts that do not have an email channel yet:** If not specified, this is set to **subscribed**.\n* **Contacts that already have an email channel:** If not specified, the existing value remains unaltered.<br>\n***Note:** If you change the email address of an existing contact and the current email channel status is **subscribed**, **binned** or **deleted**, the status is set to **subscribed**. If the current status is **subscribed** and the account setting *Enforce double opt-in for all signups, including bulk uploads* is on, the status is set to **pendingOptIn** until the contact confirms.*","enum":["subscribed","unsubscribed","suppressed"]},"openTracking":{"type":"string","description":"Specifies if you are allowed to track email opens for the contact.<br>\n* **New contacts, or contacts that do not have an email channel yet:** If not specified, this is set to **unknown** and no explicit opt-in or opt-out record is written.\n* **Contacts that already have an email channel:** If not specified, the existing value remains unaltered.","enum":["unknown","subscribed","unsubscribed"],"default":"unknown"}},"description":"The channel properties for email. All properties are optional. Specify only the properties you want to set. For contacts that already have an email channel, properties you do not specify remain unaltered."},"sms":{"type":"object","properties":{"status":{"$ref":"#/components/schemas/channelStatusUpdate"}},"additionalProperties":false,"description":"The channel properties for SMS/MMS"},"whatsApp":{"type":"object","properties":{"status":{"$ref":"#/components/schemas/channelStatusUpdate"}},"additionalProperties":false,"description":"The channel properties for WhatsApp"}},"additionalProperties":false,"description":"Properties associated with each channel for a contact. For example, message format or subscription status"}}},"channelPropertiesWithResubscribe":{"type":"object","properties":{"channelProperties":{"type":"object","properties":{"email":{"type":"object","properties":{"resubscribeOptions":{"type":"object","properties":{"resubscribeWithNoChallenge":{"type":"boolean","description":"Set to **true** to resubscribe the contact without sending a resubscription confirmation email. If not specified, this is set to **false**, so the contact is sent a resubscription confirmation email.","default":false},"preferredLocale":{"type":"string","description":"The language code for the language of the resubscription confirmation email. If not specified, the default locale of the account is used.<br><br>\n**Note:** Use the values exactly as listed. Some of them are not standard locale codes, for example **en-EN** for English and **se-SE** for Swedish.\n\n| Value | Language |\n|---|---|\n| `cs-CS` | Czech |\n| `da-DA` | Danish |\n| `de-DE` | German |\n| `el-EL` | Greek |\n| `en-EN` | English |\n| `es-ES` | Spanish (Spain) |\n| `es` | Spanish |\n| `fi-FI` | Finnish |\n| `fr-FR` | French |\n| `hu-HU` | Hungarian |\n| `it-IT` | Italian |\n| `nl-NL` | Dutch |\n| `nb-NO` | Norwegian Bokmål |\n| `pl-PL` | Polish |\n| `pt-PT` | Portuguese |\n| `ru-RU` | Russian |\n| `se-SE` | Swedish |\n| `sk-SK` | Slovak |\n| `tr-TR` | Turkish |\n| `zh-CN` | Chinese (Simplified) |","enum":["cs-CS","da-DA","de-DE","el-EL","en-EN","es-ES","es","fi-FI","fr-FR","hu-HU","it-IT","nl-NL","nb-NO","pl-PL","pt-PT","ru-RU","se-SE","sk-SK","tr-TR","zh-CN"]},"redirectUrlAfterChallenge":{"type":"string","description":"The URL to send the contact to after they confirm their resubscription. If not specified, the standard default redirect page is used.","format":"uri","example":"https://somedomain.io/some/page"}},"description":"Options for resubscribing the email channel of a contact. A resubscription is only triggered when you specify **resubscribeOptions**; if you do not specify it, no resubscription occurs."}}}}}}},"paginationLinks":{"required":["first","self"],"type":"object","properties":{"self":{"required":["link","marker"],"type":"object","properties":{"marker":{"type":"string","description":"Pagination marker to be passed to API calls to retrieve this data page"},"link":{"type":"string","description":"Link to retrieve this data page. It contains the query string as you sent it, so it is not URL-encoded."}},"description":"Details for accessing this data page via pagination"},"first":{"required":["link","marker"],"type":"object","properties":{"marker":{"type":"string","description":"Pagination marker to be passed to API calls to retrieve this data page"},"link":{"type":"string","description":"Link to retrieve the data page. The query string is URL-encoded."}},"description":"Details for accessing the first page worth of data"},"prev":{"required":["link","marker"],"type":"object","properties":{"marker":{"type":"string","description":"Pagination marker to be passed to API calls to retrieve this data page"},"link":{"type":"string","description":"Link to retrieve the data page. The query string is URL-encoded."}},"description":"Details for accessing the previous pagea worth of data"},"next":{"required":["link","marker"],"type":"object","properties":{"marker":{"type":"string","description":"Pagination marker to be passed to API calls to retrieve this data page"},"link":{"type":"string","description":"Link to retrieve the data page. The query string is URL-encoded."}},"description":"Details for accessing the next pages worth of data"},"last":{"required":["link","marker"],"type":"object","properties":{"marker":{"type":"string","description":"Pagination marker to be passed to API calls to retrieve this data page"},"link":{"type":"string","description":"Link to retrieve the data page. The query string is URL-encoded."}},"description":"Details for accessing the last pages worth of data"}},"description":"Pagination links"},"errorResponse":{"required":["description","errorCode"],"type":"object","properties":{"errorCode":{"type":"string","description":"Unique error code"},"description":{"type":"string","description":"Description of the issue"},"details":{"type":"array","items":{"required":["description","item"],"type":"object","properties":{"item":{"type":"string","description":"Item the error is associated with, for example, field name, unique identifier for an entity or item in batch"},"description":{"type":"string","description":"Description of the error"}}}}}},"contactReference":{"required":["contactId","identifiers"],"type":"object","properties":{"contactId":{"$ref":"#/components/schemas/contactId"},"identifiers":{"$ref":"#/components/schemas/identifiers"}},"description":"Contact reference"},"contactId":{"minimum":0,"type":"integer","description":"Immutable unique identifier for the contact","example":35212311},"identifiers":{"type":"object","properties":{"email":{"type":"string","description":"Contact email address","nullable":true,"example":"someone@emailsim.io"},"mobileNumber":{"type":"string","description":"Contact phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)","nullable":true,"example":"447123123123"}},"additionalProperties":{"type":"string","description":"Any additional custom identifiers. Property names must match one of the custom identifiers that exists in the account.","nullable":true},"description":"Identifiers this contact can be referenced by","example":{"email":"someone@emailsim.io","mobileNumber":"447123123123","myCustomId":"MYID_12345"}},"email":{"type":"string","description":"Contact email address","nullable":true,"example":"someone@emailsim.io"},"mobileNumber":{"type":"string","description":"Contact phone number in [E.164 format](https://en.wikipedia.org/wiki/E.164)","nullable":true,"example":"447123123123"},"additionalProperties":{"type":"string","description":"Any additional custom identifiers. Property names must match one of the custom identifiers that exists in the account.","nullable":true}},"parameters":{"integrationTrackingToken":{"name":"x-ddg-integration-token","in":"header","description":"If you are a partner of Dotdigital and have a [verified integration](https://developer.dotdigital.com/docs/partner-integration-verification) then include your [integration tracking token](https://developer.dotdigital.com/docs/verified-integration-tracking) here.","required":false,"schema":{"type":"string","format":"uuid","example":"5a96bc79-19a7-4544-973b-e2da0c9136f9"}},"createdFilter":{"name":"~created","in":"query","description":"Filter by created date.<br/>\n***Note:***\n* The date must be in ([ISO 8601 format](https://en.wikipedia.org/wiki/ISO_8601))\n* Can't be used in conjunction with the **~modified** parameter.","schema":{"pattern":"^gte::\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z$","type":"string"},"examples":{"Greater than or equal to created date":{"value":"gte::2021-12-17T00:00:00Z"}}},"modifiedFilter":{"name":"~modified","in":"query","description":"Filter by last modified date.<br/>\n***Note:***\n* The date must be in ([ISO 8601 format](https://en.wikipedia.org/wiki/ISO_8601))","schema":{"pattern":"^gte::\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z$","type":"string"},"examples":{"Greater than or equal to modified date":{"value":"gte::2021-12-17T00:00:00Z"}}},"listFilter":{"name":"~listId","in":"query","description":"Filter by a specific list.<br/>\n***Note:***\n* Can't be used in conjunction with the **~segmentId** parameter.","schema":{"type":"integer"},"example":54321},"segmentFilter":{"name":"~segmentId","in":"query","description":"Filter by a specific segment.<br/>\n***Note:***\n* Can't be used in conjunction with the **~listId** parameter.","schema":{"type":"integer"},"example":12345},"limit":{"name":"limit","in":"query","description":"Maximum number of records to retrieve per page","schema":{"maximum":5000,"minimum":1,"type":"integer","format":"int32","example":1000}},"marker":{"name":"marker","in":"query","description":"Pagination marker to retrieve the data from","schema":{"type":"string","example":"RXhhbXBsZSBhbXJrZXIgdmFsdWU="}},"identifier":{"name":"identifier","in":"path","description":"The field to use to uniquely identify the contact. This can be a custom identifier or a contact identifer of **contactId**, **email** or **mobileNumber**","required":true,"schema":{"maxLength":50,"minLength":1,"pattern":"(^[-A-Za-z0-9_]{1,50}$)","type":"string"},"examples":{"email":{"summary":"Email address","value":"email"},"mobileNumber":{"summary":"Mobile number","value":"mobileNumber"},"contactId":{"summary":"Contact ID","value":"contactId"},"customIdentifier":{"summary":"Custom identifier","value":"loyaltyId"}}},"value":{"name":"value","in":"path","description":"The unique value to identify the contact.<br>***Note:** Must be the same type as the **identifier***","required":true,"schema":{"maxLength":256,"minLength":1,"type":"string"},"examples":{"email":{"summary":"Email address (use with the email identifier)","value":"amelia.thornbury@emailsim.io"},"mobileNumber":{"summary":"Mobile number (use with the mobileNumber identifier)","value":"447700900184"},"contactId":{"summary":"Contact ID (use with the contactId identifier)","value":"35212311"},"customIdentifier":{"summary":"Custom identifier value (use with the loyaltyId identifier)","value":"LOY-000184"}}}},"securitySchemes":{"basicAuth":{"type":"http","scheme":"basic"}}},"x-ddg-notes":"This version corrects the schema and documentation for importing contacts and for email channel properties. The changes are additive; the API behaviour does not change.\n* **importContacts:** Added request examples for these use cases: update data fields and identifiers, unsubscribe from email, set email open tracking, add a consent record, and update data fields, identifiers and list membership.\n* **getContacts:** Added response examples: key details only, selected data fields with lists and preferences, a page with a next link, contacts modified since the last poll, and modified contacts in a list or a segment.\n* **importContact:** Added request examples for the same use cases, and an example to resubscribe a contact to email. Added request examples that create and then update a contact, with their 201 and 200 response examples. The description now states that a new contact needs **identifiers.email** or **identifiers.mobileNumber** in the request body, and a 400 example shows the error.\n* **deleteContacts:** Each item must now contain exactly one identifier. Items that use **email** or **mobileNumber** are now valid against the schema. Added a request example and corrected the 400 error example.\n* **getImportStatus:** Added response examples, including a contact that has only a custom identifier. **matchIdentifier** is no longer required in **failures**, because the API does not return it. Replaced the failures example.\n* **Contact responses:** The email, SMS and WhatsApp channel status values now match the values the API returns. A deleted channel is not included in **channelProperties**.\n* **getContact:** Added examples for each identifier type in the path, and response examples for a full contact and for a contact whose mobile number was deleted.\n* **replaceContact:** Added examples for each identifier type in the path, request examples to replace data and lists and to remove a mobile number, and a response example.\n* **deleteContact:** Added examples for each identifier type in the path, and a response example.\n* **getContact, replaceContact and deleteContact:** Corrected the 404 error examples to match the API.\n* **getDeleteStatus:** Added response examples. Corrected the 404 response, which described an import request in place of a delete job.\n* **createContact:** Added request examples: email address only, a full profile with channels, lists, preferences and consent, verified double opt-in, and mobile number only. Added a 201 response example. Corrected the 409 error example. The description now states that the request must contain **email** or **mobileNumber**, and a 400 example shows the error.\n* **importContacts:** The description now states that a new contact needs **email** or **mobileNumber** in its identifiers, and the failure the import reports if it does not.\n* **importContacts:** Contacts that match on **contactId** are now valid against the schema. The request uses the new **contactRequestIdentifiers** schema, where **contactId** is an integer.\n* **Email channel properties:** **emailType**, **optInType**, **status** and **openTracking** are no longer required. The descriptions now give the default for contacts that do not have an email channel yet, and the behaviour for contacts that already have one.\n* **Email channel properties:** **resubscribeOptions** can now be sent together with the other email channel properties.\n* **resubscribeWithNoChallenge:** The default is now **false**, which agrees with the API behaviour.\n* **Contact responses:** Email channel properties now pass validation. **emailType** and **optInType** values are now camelCase (for example **html** and **single**), which agrees with the API. **openTracking** is now included and is always returned. The request channel properties schema is no longer applied to responses, so all email and SMS statuses and the SMS **countryCode** are now valid.\n* **Contact responses:** Consent records and preferences now pass validation. Preferences require **publicName** and **privateName**, which the API returns, in place of the undefined **name** property.\n* **x-ddg-integration-token:** The header now uses **format: uuid** in place of a pattern that rejected every value. Send the token as a UUID without braces.\n* **Contact responses:** The **created**, **updated** and consent record **dateTimeCreated** descriptions now state the formats the API returns. The **preferences** and **consentRecords** arrays can now be empty or not included.\n* **Deleted contacts:** The descriptions now explain when **email** and **mobileNumber** have the value **deleted**.\n* **replaceContact:** The description now states that email channel properties you do not specify remain unaltered.","x-samples-languages":["curl","csharp","java","javascript","node","python","php","ruby"]}