An integration app keeps two kinds of credential. Secrets are values you receive from another system, such as API keys, tokens, passwords and webhook signing keys. Client credentials are values xMatix issues so that a partner system can call your app. Both are write-only: you see a value once, when you enter it or when it is issued, and never again.
Overview
Every integration app in Setup → Platform → Integrations has its own Secrets page and Client credentials page. You can find them in the app's side navigation, next to Connections, Flows, Triggers and Members.
- A secret is stored under a Reference name, for example
partner-api-token. Connections, flow steps and webhook triggers never hold the value itself. They hold the token${secret:partner-api-token}, and xMatix looks up the current value each time a run, a webhook call or a connection test needs it. That is why rotating a secret needs no change anywhere else. - A client credential is a client id and client secret pair. A partner exchanges the pair at the token endpoint shown on the page, then calls the app's webhook URLs with
Authorization: Bearer <access_token>. The partner doesn't need to sign each request.
When to use it
- You connect xMatix to an external system and need to store its API key, token, password or OAuth client secret. Use a secret.
- A webhook trigger must check a partner's HMAC signature or API key. Store that shared key as a secret.
- A partner system has to push data into xMatix and cannot sign each request. Issue client credentials.
- A key expires, a staff member with access leaves, your policy calls for periodic rotation, or you suspect a leak. Rotate the secret or the client credential.
How xMatix handles it
- Encrypted and bound. A secret's value is encrypted when it is saved. The encrypted value is bound to your organization, the app and the reference name, so it can't be moved to another app or reference. No screen or API returns the value. The list shows only the reference, the key id and the dates.
- Looked up each time. Nothing caches the value between uses. Each flow step that uses a connection reads the current value of every
${secret:…}reference in the connection's and the step's configuration. So does each webhook request and each Test Connection. - Missing means stop. In a flow run, if a reference can't be found, or a stored value can no longer be decrypted, the step fails before any call goes out. The run's error reads "references secret(s) that could not be resolved … Re-enter the secret in the integration secrets store".
- App first, then organization. A connection or step looks for the reference in its own app first. It then falls back to an organization-wide secret with the same name. The Setup screens manage app secrets only.
- Masked in diagnostics. Before step input and output are saved for troubleshooting, any
${secret:…}token is masked. So is the value of any property whose name suggests a credential, such as password, token, secret, authorization, API key or client secret. These values show as***redacted***. - Not copied into sandboxes. Creating or refreshing a sandbox never copies integration secrets. Enter sandbox credentials in the sandbox yourself.
- OAuth sign-ins are reused. The Salesforce and Zoho connectors exchange the stored client id, client secret and refresh token or password for a short-lived access token, and they reuse that token for up to 50 minutes. After you rotate their secrets, runs can keep using the token obtained with the old values until it lapses. If the provider refuses a sign-in, that refusal is remembered for up to 10 minutes, so runs keep failing with the same message for a short while after you fix the secret.
- Client secrets are stored hashed. xMatix keeps only a one-way hash of a client secret. That is why the secret is shown once and can't be shown again, only replaced.
Prerequisites
- The Manage integrations capability in your security profile. Without it you don't see Integrations in Setup.
- For Secrets: the Admin role on the app. You get it through a security profile on the app's Members page. The Members screen describes Connection Manager as able to manage secrets, but the Secrets page and its actions require Admin.
- For Client credentials: the Manage integrations capability is enough. No app role is checked.
- For a rotation: the new value from the external system, created before you start.
Procedure
Step 1 — Store a secret
- Go to Setup → Platform → Integrations and open the app that owns the connection.
- Select Secrets in the app's navigation, then Add Secret in the page header.
- Enter a Reference. Use letters, digits and
.,_,-or:only, up to 200 characters, for examplepartner-api-token. This is the name you use later in${secret:partner-api-token}. - Paste the Value into the masked field and select Save.
You see "Secret saved". The new row shows the reference, a Key Id and the Created and Updated dates. The value is never shown again.
If you enter a reference that already exists in the app, the old value is replaced. This counts as a rotation, not as a second secret, so check the list before you save.
Step 2 — Reference the secret from a connection, step or trigger
- Connection form. On a connection field meant for a credential, either type
${secret:partner-api-token}or choose the name from the Pick list beside the field. The field then shows a secret tag. The Pick list loads the app's secrets, so it is empty if you are not an Admin on the app. In that case, type the reference. - Raw JSON. If you edit a connection as raw JSON, write the reference as a string value, for example
"apiToken": "${secret:partner-api-token}". Never paste the credential itself. The editor reminds you of this under the text box. - Webhook trigger. In the trigger configuration,
hmacSecretRefnames the secret that the partner signs requests with (HMAC-SHA256 in theX-Signatureheader).apiKeySecretRefnames the secret the partner sends as an API key in theX-Api-Keyheader, or in the header thatapiKeyHeadernames.
Save, reopen the connection and select Test Connection. The test reads the current value of each reference in the connection's own configuration.
Keep a list of every connection, step and trigger that uses each reference. You need that list when you rotate.
Step 3 — Rotate a secret
- Create the replacement credential in the external system first. Keep the old one working for now if the system allows two at once.
- On the app's Secrets page, select Rotate in the row's actions. The dialog is titled Rotate "partner-api-token", and the reference can't be changed.
- Paste the new Value and select Rotate. You see "Secret rotated". Last Rotated and Updated change to now, and Key Id shows the key the value was encrypted with.
- Select Test Connection on every connection on your list.
- Watch the next real run on the Sync Monitor or on the app's Errors page, and confirm that it signs in and does its work. For a Salesforce or Zoho connection, rely on Test Connection as well as the run. The test always signs in afresh with the stored values, but a run in the first 50 minutes may still use an access token obtained with the old values.
You don't need to edit or restart anything else, because every use reads the new value.
Step 4 — Revoke the old credential in the external system
Revoke the old key in the external system only after every connection test and one live run have passed. If the new key turns out to be wrong while the old one still works, rotate again and paste the old value back under the same reference. You don't need to change any connection.
Step 5 — Rotate a webhook signing key or API key
A webhook secret is a hard switch. Each reference holds only one value, and every incoming request is checked against the current one. From the moment you select Rotate, the partner's requests are refused until the partner uses the new key.
- Agree a time with the partner, rotate at that time, and have the partner switch at the same time.
- For partners who need a gradual handover, use client credentials instead. Bearer tokens are accepted on every webhook of the app, alongside HMAC and API keys.
Step 6 — Issue client credentials to a partner
- In the app, select Client credentials, then Create credentials in the page header.
- Enter a Name that says who uses the credentials, up to 120 characters, and select Create.
- The Copy the client secret now dialog shows the Client id (it starts with
xmxapp_), the Client secret and the Token endpoint. Copy all three into the partner system's own secret store, then select I have copied it. The client secret is never shown again.
The partner posts grant_type=client_credentials, client_id and client_secret to the token endpoint. It then sends the returned access_token as Authorization: Bearer … to the app's webhook URLs. An access token lasts one hour by default. A token issued for one app is refused by every other app.
The list shows Name, Client id, Status (Enabled or Disabled), Secret issued, Last used, Created by and Created. Last used shows when a token was last issued, updated at most every five minutes.
Step 7 — Rotate, disable or delete client credentials
- Rotate secret. This issues a new client secret for the same client id. The confirmation reads "The current secret stops working immediately. Tokens already issued stay valid until they expire." The new secret is shown once, in the same copy dialog.
- Disable / enable. A disabled client can't get new tokens. Use this to pause a partner without losing the client id.
- Delete. This removes the client id permanently. Tokens already issued stay valid until they expire.
Rotate secret cuts the old secret off at once. For a handover without downtime, create a second set of credentials, have the partner switch to it, check that Last used moves to the new row, and then delete the old row. An app can hold up to ten sets of client credentials.
Fields
Secrets
| Field | What it means | Notes |
|---|---|---|
| Reference | The name used in ${secret:<reference>} | Required. Up to 200 characters; letters, digits and . _ - :. It can't be changed after creation, so delete and re-create the secret to rename it. |
| Value | The credential itself | Required. Entered in a masked field and never shown again. |
| Key Id | Identifies the key the value was encrypted with | Read-only. Set again on each save. |
| Created | When the reference was first saved | Read-only. |
| Updated | When the value was last saved | Read-only. |
| Last Rotated | When the value was last replaced | Read-only. Empty until the first rotation. Saving over an existing reference from Add Secret also counts. |
Client credentials
| Field | What it means | Notes |
|---|---|---|
| Name | Who uses these credentials | Required, up to 120 characters. |
| Client id | The identifier the partner sends | Generated, starts with xmxapp_. Copy it from the list at any time. |
| Status | Enabled or Disabled | Disabled credentials can't get new tokens. |
| Secret issued | When the current client secret was issued | Changes when you select Rotate secret. |
| Last used | When a token was last issued to this client | Updated at most every five minutes. |
| Created by | Who created the credentials | Read-only. |
| Created | When the credentials were created | Read-only. |
Business rules
- A secret value is never returned after it is saved, whether on screen, through the API or in an export.
- Add Secret with an existing reference replaces that secret's value and stamps Last Rotated.
- A flow step fails before calling the external system if any
${secret:…}reference in its connection or step configuration can't be found or decrypted. - Test Connection checks only the connection's own configuration. A missing secret is passed to the connector as an empty value, so the connector's own error appears, or the test can even pass. References used only in a flow step's configuration are not tested.
- Deleting a secret takes effect at once. The confirmation says: "Any flow or webhook referencing it will fail until a new value is saved."
- Each app can hold up to ten sets of client credentials. Creating an eleventh is refused with "An interface app can have at most 10 client credentials. Delete an unused one first."
- Rotating, disabling or deleting client credentials doesn't revoke access tokens already issued. They stay valid until they expire.
Example
An integration administrator at a distributor connects xMatix to a logistics partner's API. The partner issues API keys that expire every 90 days.
- In the app "Logistics partner", the administrator adds the secret
logistics-api-key. On the connection "Logistics production", they pick it in the API key field, which now shows${secret:logistics-api-key}. Test Connection passes. - The flows "Send dispatches" and "Pull delivery status" both use that connection. The administrator records both in the rotation log.
- Ten days before the key expires, the administrator creates a second key in the partner's portal. They rotate
logistics-api-keyin xMatix, run Test Connection again, and watch the next "Pull delivery status" run succeed on the Sync Monitor. - Next day, they revoke the old key in the partner's portal and close the log entry with both timestamps.
- The partner also pushes proof-of-delivery events into xMatix. For that, the administrator created client credentials named "Logistics partner POD" and sent the client id and secret through the partner's secure channel. When the partner later asks for a fresh secret, the administrator creates "Logistics partner POD 2". After the partner switches over, Last used moves to the new row and the administrator deletes the old one.
Training
Practice exercise
In a sandbox, on a test integration app:
- Add the secret
training-tokenwith any value. - Create or open a connection and reference
${secret:training-token}from a credential field using Pick. - Rotate
training-tokenand confirm that Last Rotated is now filled in. - Create client credentials named "Training partner", copy the client id, then disable and delete them.
Expected result: the Secrets list shows training-token with Created, Updated and Last Rotated dates and no value anywhere. The connection's configuration shows only the reference. The client credentials row moved from Enabled to Disabled and then disappeared.
Quick reference
- Secrets live on an app's Secrets page. You need the Admin role on the app.
- Reference format:
${secret:<reference>}. Letters, digits and. _ - :only. - Rotating means pasting a new value under the same reference. Nothing else changes.
- Create the new key in the external system first, and revoke the old one last.
- Test Connection tests only the connection's own references.
- A rotated webhook key is a hard cutover, so agree the time with the partner.
- Client credentials are shown once. Rotate secret cuts the old secret off at once.
- For a gradual handover, use a second set of client credentials (up to ten per app).
- Sandboxes never receive production secrets.
Permissions
| Task | What you need |
|---|---|
| See Setup → Platform → Integrations | Manage integrations capability |
| View, add, rotate or delete secrets | Manage integrations plus the Admin role on the app |
| Pick a secret on a connection | Same as above. Without Admin, type the reference instead. |
| Create, edit or test a connection | Connection Manager role or higher on the app |
| Create, rotate, disable or delete client credentials | Manage integrations |
| Grant app roles to security profiles | Admin role on the app (Members page, Grant Profile) |
App roles build on each other: Viewer, Operator, Connection Manager, Admin. If a profile has several roles, the highest one counts. See Security profiles and the grant matrix for capabilities.
Configuration
- Members (in the app's navigation): grant a security profile a role with Grant Profile, or change it with Change role. Only Admin opens the Secrets page.
- Trigger configuration:
hmacSecretRef,apiKeySecretRefandapiKeyHeader(defaultX-Api-Key) choose which secrets protect a webhook. Bearer tokens from the app's client credentials are always accepted as well. - Connector pages: each connector page lists the credentials its connection needs. Some ship with fixed reference names, such as the three secrets the Zoho starter templates create connections for. See Salesforce, Zoho and manifest apps.
- Sandboxes: after creating or refreshing a sandbox, add the sandbox's own credentials on each app's Secrets page there.
Common problems
A run fails with "references secret(s) that could not be resolved"
The reference named in the message doesn't exist in the app, is misspelt, or holds a value that can no longer be decrypted. Open the app's Secrets page and compare the reference letter for letter. Add the secret, or rotate it to re-enter the value, then replay the run.
Test Connection passes but the scheduled run fails
The test checks only the connection's own references, and it passes a missing secret as an empty value. Look for ${secret:…} references in the flow step's configuration, and make sure each one exists on the Secrets page.
I deleted a secret that was still in use
Every run and webhook that uses it now fails. Add a secret with the same reference and a valid value. Nothing else needs to change.
The rotation "didn't take"
Check that you rotated the reference the failing connection actually uses. Apps often hold similar names, such as crm-client and crm-client-secret. Then read the run's error text: it carries the external system's own answer, for example an expired or revoked key.
I fixed a Salesforce or Zoho secret but runs still fail with the same sign-in error
The connector remembers a refused sign-in for up to 10 minutes before it asks the provider again. This applies to Test Connection too. Wait 10 minutes, then test again and replay the run.
Partner webhooks started failing right after a rotation
Webhook keys switch over at once. Either have the partner use the new key now, or rotate back to the old value until the agreed switch-over time.
I can't see the Secrets page, or the Pick list is empty
You need the Admin role on the app. Ask an app Admin to grant your security profile Admin on the app's Members page.
"An interface app can have at most 10 client credentials"
Delete credentials that are no longer used. Last used shows which ones are idle.
Common questions
Can I read a secret back if I lose it?
No. Nobody can read a stored value, including platform administrators. A lost credential is handled like a rotation. Create a new credential in the external system and save it under the same reference with Rotate. Treat the external system's console as the record of the credential itself. The same applies to client secrets: if a partner loses one, use Rotate secret or create a new set of client credentials.
Who can manage secrets?
Users whose security profile has the Manage integrations capability and the Admin role on that app. Viewer, Operator and Connection Manager can't open the Secrets page. They can still reference a secret by typing ${secret:name} in a connection, if they know its name. Even Admins only ever see the reference and its dates, never the value.
What is the difference between a secret and client credentials?
A secret is something you receive from another system and store so that xMatix can call it, or so xMatix can check that system's webhook signatures. Client credentials work the other way round. xMatix issues them, and the partner stores them so that it can call your app's webhooks with a short-lived Bearer token. A secret value can be replaced, but you never see it again. A client secret is issued by xMatix and shown once.
How often should keys rotate?
Follow your security policy and the external system's guidance. Rotation needs no configuration change, so quarterly rotation, or immediate rotation when someone with access leaves, is practical. The Last Rotated column on the Secrets page shows when each secret last changed. An empty value means the secret has never been rotated.
Do sandboxes use my production credentials?
No. Integration secrets are never copied when a sandbox is created or refreshed, so a sandbox can't call your live external systems with production keys. Add test credentials on each app's Secrets page in the sandbox.
