Skip to content

Authentication

MendriX has two API surfaces, and they authenticate in fundamentally different ways — don’t assume one from the other. Both, however, start from the same token, created once in the TMS.

REST APISOAP (Custom Link)
Layout you pickSingle tokenSingle token or Username + password
What travels on each callA short-lived Bearer JWTThe credential itself, on every call
Where it travelsAuthorization HTTP headerTAuthenticationHeader, inside the XML envelope
Exchange stepYes — log in once, get an access + refresh pairNone — the credential is sent as-is each time
ExpiryAccess token expires quickly; refresh or re-loginDoesn’t expire; same credential every call

Integrating with the REST API? Read REST API authentication below. Calling Custom Link instead? Skip straight to SOAP (Custom Link) authentication — the REST steps don’t apply there.

An administrator (or any user with the Manage API tokens permission) creates tokens in the TMS desktop client:

  1. Open Administration → Settings → Miscellaneous settings.
  2. Open the Custom Link dialog.
  3. Go to the Api Tokens tab.
  4. Start the create-token wizard and choose:
    • Token type
      • Single client — the token is scoped to one client’s data only.
      • All clients — a master token (ClientId 0) that can act across all clients and carries permissions.
    • Layout
      • Single token — one secret string. Works as the Bearer token for REST, and can equally be used as SOAP credentials (placed in the UserName field of the TAuthenticationHeader, with Password left empty).
      • Username + password — a credential pair. This layout is SOAP only — it exists for the UserName/Password fields of the TAuthenticationHeader; the REST API has no field for a separate username, so this layout can’t be used as a Bearer token.
  5. Enter a label. Labels must be unique; use something descriptive such as crm-sync-prod.
  6. The system generates the secret, copies it to the clipboard, and shows it only once.
  • Master token (all clients, ClientId 0) — carries permissions and can access data across every client. Use it for back-office integrations that span the whole tenant. Guard it carefully.
  • Client-scoped token (single client) — limited to exactly one client’s data. Prefer these when an integration only needs one client, to limit blast radius.
  • Tokens do not expire.
  • There is no rotation endpoint. To rotate, create a new token, switch your integration over, then delete the old one.
  • Revocation = deleting the token in the same Api Tokens tab.

MendriX’s REST API uses the single-token layout created above in a two-step flow:

  1. Take the API token you created in the TMS.
  2. Exchange it for a JWT at the account service’s login endpoint. You receive a short-lived access token and a longer-lived refresh token.

Every REST request then carries the access token as a Bearer JWT:

Authorization: Bearer ACCESS_TOKEN

The username + password layout doesn’t apply here — REST only ever sees the single secret string.

Log in at the account service with your API token to obtain a token pair:

POST https://<your-client-name>.api.mendrix.cloud/api/account/login-api-token
{ "token": "YOUR_API_TOKEN" }

The response contains a short-lived access token and a refresh token (valid for 7 days):

{
"data": {
"items": [
{
"access": "eyJhbGciOi…",
"refresh": "eyJhbGciOi…"
}
]
}
}

Use the access token as the Bearer token on every API call. The endpoints in the reference accept token types planner, apitoken and service (shown as x-token-types in the OpenAPI document); tokens obtained with this login are apitoken.

Terminal window
# 1. Log in with the API token (kept in an env var; never hard-code secrets)
ACCESS_TOKEN=$(curl -s -X POST \
"https://<your-client-name>.api.mendrix.cloud/api/account/login-api-token" \
-H "Content-Type: application/json" \
-d "{\"token\": \"$MENDRIX_API_TOKEN\"}" \
| jq -r '.data.items[0].access')
# 2. Call the API with the access token
curl https://<your-client-name>.api.mendrix.cloud/api/client/clients/ \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Accept: application/json"
const BASE = 'https://<your-client-name>.api.mendrix.cloud/api';
const API_TOKEN = process.env.MENDRIX_API_TOKEN; // never hard-code secrets
// 1. Exchange the API token for a token pair
const login = await fetch(`${BASE}/account/login-api-token`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token: API_TOKEN }),
});
if (!login.ok) throw new Error(`Login failed: ${login.status}`);
const { access, refresh } = (await login.json()).data.items[0];
// 2. Call the API with the short-lived access token
const res = await fetch(`${BASE}/client/clients/`, {
headers: {
Authorization: `Bearer ${access}`,
Accept: 'application/json',
},
});
if (!res.ok) {
throw new Error(`MendriX API error ${res.status}: ${await res.text()}`);
}
const clients = await res.json();
console.log(clients);

The access token is deliberately short-lived. When it expires (the JWT’s exp claim, or a 401 response), either log in again with your API token, or refresh the pair:

POST https://<your-client-name>.api.mendrix.cloud/api/account/refresh
{ "access": "EXPIRED_ACCESS_TOKEN", "refresh": "CURRENT_REFRESH_TOKEN" }

The response has the same shape as the login response and contains a new access + refresh pair.

For long-running integrations the simplest robust strategy is: log in, use the access token until a 401, then log in again. Refresh is an optimisation, not a requirement.

Custom Link does not use JWTs or a login exchange. Every SOAP call carries your credentials directly, in a TAuthenticationHeader SOAP header inside the XML envelope itself — either layout from Creating a token in the TMS works here:

<h:TAuthenticationHeader xmlns:h="urn:UCoSoapDispatcherBase">
<UserName>YOUR_SOAP_NAME</UserName>
<Password>YOUR_SOAP_PASSWORD</Password>
</h:TAuthenticationHeader>
  • Single-token layout: put the secret in UserName and leave Password empty.
  • Username + password layout: put each half of the pair in its matching field.

Other than which layout to use, the same rules apply either way:

  • No exchange step. There’s no equivalent of login-api-token — the credential is sent as-is, on every single call, for the life of the integration.
  • No expiry. Unlike a REST access token, this credential doesn’t go stale; there’s nothing to refresh.
  • Not an HTTP-level credential. The pair travels inside the SOAP body, not as a Bearer token or Basic Auth header — HTTP-level authentication is not accepted. Without this header, the service answers SOAP header for authentication required.
  • Scoping still applies. A client-scoped credential can only call a fixed allowlist of commands; anything else returns Security: no permission for request <RequestClassName>.

For the full envelope mechanics, error shapes, and the client-scoped command allowlist, see SOAP overview & connection and Custom Link: rules of engagement.

REST

  • Never commit tokens. Keep them in environment variables or a secret manager. All examples in this portal use obvious placeholders such as YOUR_API_TOKEN and ACCESS_TOKEN.
  • Access and refresh tokens are secrets too. Keep them in memory (or a secret store), never in logs or exported workflow files.
  • Scope down. Prefer a client-scoped token when you only need one client.
  • One token per integration. Separate tokens make revocation and auditing painless — delete one without disturbing the others.
  • Transport security. Always call over HTTPS; the token is a bearer credential and grants access to anyone who holds it.

SOAP

  • Never commit SOAP credentials. Since they don’t expire, a leaked UserName/Password pair stays valid until someone notices and asks MendriX to rotate it — keep it out of source control and exported n8n workflow JSON.
  • Scope down. Prefer client-scoped credentials when an integration only needs one client.
  • Transport security. Always call over HTTPS/TLS; the raw TCP/IP Custom Link protocol has no authentication and must never be exposed externally.