Voyado

Datafly Signal syncs identified contacts to Voyado Engage server-to-server using the Engage Contacts API (v3). When a visitor identifies themselves — signs up, logs in, or submits a form — Signal creates or updates their Engage contact with their name, email, phone, locale, and marketing-consent preferences.

Voyado’s Engage API is server-side only — client-side calls are blocked by CORS. Signal delivers from your own infrastructure, so the API key never reaches the browser.

Why route Voyado through Datafly Signal

  • Profiles are updated from the server, not the browser. Events reach Voyado even when a tracker blocker or a failed page unload would have dropped a client-side call, so the profile reflects what actually happened.
  • One consent decision governs every destination. Voyado is gated by the same consent state as the rest of your stack, so a withdrawal applies everywhere at once.

Prerequisites

Before configuring Voyado in Signal, you need a Voyado Engage tenant and an API key.

Step 1: Find Your Tenant Name

Your tenant name is the first part of your Engage URL. If you sign in at https://acme.voyado.com, your tenant name is acme. Use the matching staging tenant (https://acme.staging.voyado.com → acme.staging) when testing against a staging environment.

Step 2: Create an API Key

  1. In Engage, go to Configure > API connections.
  2. Create a new API key. Voyado recommends a unique key per integration, so name it something identifiable (e.g. “Datafly Signal”).
  3. Copy the key — you will paste it into Signal.
⚠️

The API key is sent in the apikey HTTP header. Never put it in a URL or expose it client-side.

Step 3: Confirm Your Contact Type

New contacts are created with a contact type. If you don’t specify one, Engage defaults to Member. If your instance uses a custom contact type for web sign-ups, note its exact name.

Configure in Signal

Configuration Fields

FieldRequiredDescription
tenantYesYour Voyado tenant name (e.g. acme for https://acme.voyado.com).
api_keyYesEngage API key from Configure > API connections. Sent in the apikey header.
contact_typeNoContact type for new contacts, sent as contactType in the body (and the query string). Voyado defaults to Member if blank.

Management UI Setup

Add the integration

Go to Integrations > Add Integration > Voyado.

Enter your credentials

Fill in your tenant name and api_key, and optionally a contact_type.

Choose the consent categories that gate delivery. Cookie consent is not mapped to Voyado’s acceptsEmail, acceptsSms or acceptsPostal: those are communications preferences, which a cookie banner must never set.

Save

Click Save. The integration is now live.

API Endpoint

POST https://{tenant}.voyado.com/api/v3/contacts?contactType={contact_type}&source=datafly-signal

Authentication is the apikey request header. Each request also sends User-Agent: Datafly-Signal/1.0 and Content-Type: application/json, both required by Engage.

⚠️

POST /api/v3/contacts only creates. For a contact that already exists, Voyado answers 409 Conflict (ApprovedContactWithKeyExists); Signal treats it as permanent and does not retry. Updating an existing contact needs Voyado’s lookup-then-PATCH flow, which Signal cannot run yet (#1490).

Identity Signals

Voyado is a first-party CRM and stores raw contact details — it does not accept hashed match keys. Signal sends these fields in plaintext to your own Voyado instance:

Signal traitVoyado fieldNotes
emailemailLowercased and trimmed. Primary unique identifier.
phonemobilePhoneNormalised to E.164. Paired with countryCode.
first_namefirstName
last_namelastName
countrycountryCodeISO country code, upper-cased; Engage auto-populates the country name.
context.localelangFor example en-GB.
user_idexternalIdYour own stable customer ID, stored as Engage externalId.

The preset keys contacts on email: identity events without an email are not delivered.

How to Send Contact Data

Call datafly.identify() when a user signs up, logs in, or submits a form:

datafly.identify("user-123", {
  email: "jane.doe@example.com",
  phone: "+46 70 123 45 67",
  first_name: "Jane",
  last_name: "Doe",
  country: "SE"
});

Event Mapping

The Voyado Contacts API accepts profile data, not behavioural events. Signal therefore delivers only identity-bearing events to Voyado; all other events (page views, product views, purchases) are dropped because they carry no contact identifier.

Default preset

Signal eventVoyado action
sign_upCreate contact
identifyCreate contact

Example: Sign-up

Datafly.js call:

datafly.track("sign_up", { method: "email" });
// ...with traits previously set via datafly.identify():
datafly.identify("user-123", {
  email: "jane.doe@example.com",
  phone: "+46 70 123 45 67",
  first_name: "Jane",
  last_name: "Doe",
  country: "SE"
});

Voyado payload sent by Signal:

{
  "email": "jane.doe@example.com",
  "firstName": "Jane",
  "lastName": "Doe",
  "mobilePhone": "+46701234567",
  "countryCode": "SE",
  "lang": "sv-SE",
  "externalId": "user-123",
  "contactType": "Member"
}

A successful create returns HTTP 201 Created with the full contact record.

Testing

Use your staging tenant

Point the tenant field at your staging tenant (e.g. acme.staging) so test contacts don’t land in production.

Trigger an identify

Sign up or log in on your site, or fire datafly.identify() from the browser console with a test email.

Verify in Engage

In Engage, search Contacts for the test email. The contact should appear with the name and phone you sent. Re-running the same identify returns 409 (the contact exists) and changes nothing.

Troubleshooting

ProblemSolution
401 / 403 responsesThe apikey is wrong, revoked, or lacks contact permissions. Regenerate it under Configure > API connections.
404 responsesThe tenant name is wrong. Check the first part of your Engage URL and whether you should be using a staging tenant.
400 responsesThe contact is missing a unique identifier — ensure email or phone is set via datafly.identify().
Contact not appearingConfirm the event is sign_up or identify and that traits include an email. Other events are dropped by design.
409 responsesThe contact already exists; the endpoint only creates (#1490).
Wrong contact typeSet the contact_type field to a type that exists in your Engage instance.