# Using Incode in Tines Stories

## Introduction

[Tines](https://tines.com/) is a security and workflow automation platform that uses a straightforward graphical design process to automate tasks.

[Incode](/content/site-root.html) is an AI-powered identity verification platform that uses government-issued photo IDs and biometric matching to verify a person's identity over the Internet — built for workforce, financial, and enterprise use cases.

Tines' ability to work with APIs combined with the Incode Workforce API is the simplest way to add automated, biometric identity verification to your security workflows, HR pipelines, or customer onboarding processes.

This article assumes you have some familiarity with Tines and no familiarity with Incode. For a nice introduction to Tines, see the content in [Tines University](https://www.tines.com/university).

## Collecting information from Incode

You will need three things from Incode to configure Tines:

- an API key (`*API_KEY*`)
- a Workforce integration ID (`*INTEGRATION_ID*`)
- a Workforce integration secret (`*INTEGRATION_SECRET*`)

Go to the [Incode Dashboard](https://dashboard.incode.com/) and sign in.

**To get your API key**, navigate to **Settings → API Keys** in the left sidebar. Select **Create new API key**, give it a descriptive name such as `tines-integration`, and copy the generated key. This is your `*API_KEY*`.

**To get your integration ID and secret**, navigate to **Integrations** in the left sidebar. Select the integration you want to use (or create a new one). From the integration detail page, copy the **Integration ID** and **Integration Secret**. These are your `*INTEGRATION_ID*` and `*INTEGRATION_SECRET*`.

> **Note:** If you are using Incode's sandbox environment, your API base URL will be `https://demo-api-incode-id.incodesmile.com`. For production, use the base URL provided by your Incode account manager.

## Adding credentials to Tines

Go to Tines and navigate to **Credentials** in the left sidebar.

Add `*API_KEY*` as a **Text Credential** named `incode_x_api_key`. Add `incodesmile.com` in the **Domains** field.

Add `*INTEGRATION_ID*` as a **Text Credential** named `incode_workforce_integrationid`. Leave **Domains** blank.

Add `*INTEGRATION_SECRET*` as a **Text Credential** named `incode_workforce_secret`. Leave **Domains** blank.

All three credentials are entered as **Text** credentials and will look like this in the Tines Credentials panel:

| Name | Type | Domains |
| --- | --- | --- |
| `incode_x_api_key` | Text | `incodesmile.com` |
| `incode_workforce_integrationid` | Text | — |
| `incode_workforce_secret` | Text | — |

## Setting up Tines actions

The high-level steps we'll configure in Tines are:

1. Authenticate with the Incode API to get a session token.
2. Generate a personalized verification link for the end-user.
3. Deliver that link to the end-user.
4. Wait for a webhook from Incode when the user completes verification.
5. Validate the webhook and use the result.

### Authenticate with Incode

Before you can generate a verification link, the Incode API requires a short-lived session token obtained via a server-side authentication call. This token is used as the `x-auth-token` header in subsequent requests.

Drag the **HTTP Request** action into your story from the sidebar and configure it as follows:

- **Name**: `GetIncodeToken`
- **URL**: `https://demo-api-incode-id.incodesmile.com/v1/integration/authorize/server`
- **Content type**: JSON
- **Method**: `POST`
- **Headers**:

```undefined
x-api-key: CREDENTIAL.INCODE_X_API_KEY
```

- **Payload**:

```json
{
    "integrationId": "CREDENTIAL.INCODE_WORKFORCE_INTEGRATIONID",
    "secret": "CREDENTIAL.INCODE_WORKFORCE_SECRET"
}
```

In the **Editor** view on the right side of the Tines workspace, this looks like:

```json
{
  "url": "https://demo-api-incode-id.incodesmile.com/v1/integration/authorize/server",
  "content_type": "application_json",
  "method": "post",
  "headers": {
    "x-api-key": "CREDENTIAL.INCODE_X_API_KEY"
  },
  "payload": {
    "integrationId": "CREDENTIAL.INCODE_WORKFORCE_INTEGRATIONID",
    "secret": "CREDENTIAL.INCODE_WORKFORCE_SECRET"
  }
}
```

Select **Play** on this action. The events window should show a successful response from Incode:

```json
{
  "token": "eyJhbGci....",
  "expiresAt": 1714512000
}
```

The `token` field is the session token. It is short-lived, so this action should run at the beginning of each story run — not stored for reuse across separate executions.

### Generate a verification link

Now that you have a session token, you can generate a personalized, time-limited verification link for the end-user.

Drag another **HTTP Request** action into your story and configure it as follows:

- **Name**: `GenerateVerificationLink`
- **URL**: `https://demo-api-incode-id.incodesmile.com/v1/workforce/verification/candidate/generate-verification-link`
- **Content type**: JSON
- **Method**: `POST`
- **Headers**:

```undefined
x-auth-token: GETINCODETOKEN.BODY.TOKEN
```

- **Payload**:

```json
{
    "integrationID": "CREDENTIAL.INCODE_WORKFORCE_INTEGRATIONID",
    "secret": "CREDENTIAL.INCODE_WORKFORCE_SECRET",
    "loginHint": "USER_EMAIL",
    "loginHintType": "EMAIL",
    "validityMinutes": 4320,
    "redirectUrl": "https://your-company.com",
    "givenNames": "USER_FIRST_NAME",
    "lastName": "USER_LAST_NAME"
}
```

Replace `USER_EMAIL`, `USER_FIRST_NAME`, and `USER_LAST_NAME` with the Tines variables from wherever you collect or receive the user's information earlier in your story — for example from a web form, a webhook payload, or a previous API call.

The `validityMinutes` field controls how long the verification link stays active. `4320` equals 72 hours, which is a sensible default for most workflows. Adjust this to suit your use case.

In the **Editor** view, this looks like:

```json
{
  "url": "https://demo-api-incode-id.incodesmile.com/v1/workforce/verification/candidate/generate-verification-link",
  "content_type": "application_json",
  "method": "post",
  "headers": {
    "x-auth-token": "GETINCODETOKEN.BODY.TOKEN"
  },
  "payload": {
    "integrationID": "CREDENTIAL.INCODE_WORKFORCE_INTEGRATIONID",
    "secret": "CREDENTIAL.INCODE_WORKFORCE_SECRET",
    "loginHint": "USER_EMAIL",
    "loginHintType": "EMAIL",
    "validityMinutes": 4320,
    "redirectUrl": "https://your-company.com",
    "givenNames": "USER_FIRST_NAME",
    "lastName": "USER_LAST_NAME"
  }
}
```

Select **Play** on this action. The response from Incode will look like:

```json
{
  "verificationLink": "https://verify.incode.com/x/acme/abcd1234xyz",
  "verificationTraceId": "f78ee334-79a8-4a5e-be4a-d728e226df64"
}
```

The two key fields are:

- `verificationLink` — the URL you will send to the end-user so they can complete biometric verification.
- `verificationTraceId` — a unique identifier for this verification session. **Store this value** — you will use it later to match the Incode webhook callback back to this specific verification request.

### Deliver the verification link

Tines offers many methods to deliver data to end-users. Any of them will work for delivering this link — email, Slack, SMS, or even a redirect from a Tines page.

To demonstrate the flow, we'll use email delivery. If your story has already collected the user's email address from a form or upstream system, you can skip the form step.

**Optional — collect the user's email via a Tines Page**

If you need to collect the user's details first, select **\+ / Tools** on the left of your Tines workspace and drag a **Page** object onto your workspace. Name the page `Request Identity Verification` and add input fields for the user's email address, first name, and last name.

**Send the email**

Drag the **Send Email** action from the sidebar onto your workspace and configure it as follows:

- **Recipients**: `USER_EMAIL` (or `REQUEST_IDENTITY_VERIFICATION.BODY.EMAIL` if using a Tines form)
- **Reply to**: your team's support email address
- **Sender name**: your company or team name
- **Subject**: `Your identity verification request from *COMPANY*`
- **Body**: Write a message explaining the purpose of the verification. Include the link using the Tines variable `GENERATEVERIFICATIONLINK.BODY.VERIFICATIONLINK`. For example:

```undefined
Hi USER_FIRST_NAME,

Please complete your identity verification by clicking the link below.
The process takes less than 5 minutes and requires a government-issued
photo ID and a quick facial scan.

Verify your identity: GENERATEVERIFICATIONLINK.BODY.VERIFICATIONLINK

This link expires in 72 hours. If you have any questions, reply to
this email and our team will be happy to help.
```

Connect the actions in your story so they run in this order: `GetIncodeToken` → `GenerateVerificationLink` → `Send Email`.

To test the flow, run the story and confirm the email arrives with a working verification link.

### Set up the Incode webhook

Incode can POST a signed message to a pre-defined HTTP endpoint when an end-user completes (or fails) verification. This is how you receive the result back into your Tines story.

**Create the webhook action in Tines**

Go to your Tines story and drag a **Webhook Action** into your workspace. Select it to edit. Set **Allowed verbs** to `POST` only. Select **Copy** next to the **Webhook URL** to copy it. This is the `*DELIVERY_URL*` you will register in Incode.

**Register the webhook in Incode**

Go to the [Incode Dashboard](https://dashboard.incode.com/) and navigate to **Configuration → Webhooks**. Select your integration and open the **Webhooks** tab.

Select **Add Webhook** and configure it as follows:

| Field | Value |
| --- | --- |
| Delivery URL | Paste the `*DELIVERY_URL*` you copied from Tines |
| Events | `verification.succeeded`, `verification.failed` |
| Enabled | Toggle on |

Save the webhook. Incode will now POST an event to your Tines story each time a user completes or fails a verification session on this integration.

**Name the webhook action**

Back in Tines, rename the Webhook Action to `IncodeStatusWebhook` to make it easy to reference in downstream actions.

### Validate the webhook in Tines

When Incode posts a verification result to your Tines story, the webhook body will look like this:

```json
{
  "event_type": "verification.succeeded",
  "data": {
    "verification_trace_id": "f78ee334-79a8-4a5e-be4a-d728e226df64",
    "failure_reason": null,
    "ip": "203.0.113.42",
    "user_name": "Jane Smith",
    "latitude": 37.7749,
    "longitude": -122.4194
  }
}
```

The `verification_trace_id` in the callback matches the `verificationTraceId` you received when you generated the link. This is how you confirm that this callback belongs to the verification session you initiated.

**Create a Trigger Action**

Drag a **Trigger Action** into your story. Configure a rule that checks the incoming `event_type` and only passes events for successfully completed verifications:

```json
{
  "rules": [
    {
      "type": "field==value",
      "value": "verification.succeeded",
      "path": "INCODESTATUSWEBHOOK.BODY.EVENT_TYPE"
    }
  ]
}
```

This ensures that the rest of your story only runs when verification succeeds. If you want to handle failures separately, add a second Trigger Action with `"value": "verification.failed"` and connect it to a different branch of your story.

**Optionally verify the trace ID**

If your story initiated the verification session and stored the `verificationTraceId`, you can add a second Trigger Action to confirm the callback matches the session you expect:

```json
{
  "rules": [
    {
      "type": "field==value",
      "value": "GENERATEVERIFICATIONLINK.BODY.VERIFICATIONTRACEID",
      "path": "INCODESTATUSWEBHOOK.BODY.DATA.VERIFICATION_TRACE_ID"
    }
  ]
}
```

> **Note:** In asynchronous workflows where the verification link is sent and the result arrives in a separate story run, use Tines Records to store the `verificationTraceId` alongside any relevant identifiers (such as a user ID or opportunity ID) when the link is generated, then look up that record using the incoming `verification_trace_id` when the callback arrives. See [Tines Records documentation](https://www.tines.com/docs/records) for details.

### Use the verification result

Now that you have a validated verification result from Incode, you can use the data in your workflow. The `data` object in the webhook payload contains:

| Field | Description |
| --- | --- |
| `verification_trace_id` | Unique ID for this verification session |
| `failure_reason` | Reason for failure if verification did not succeed; `null` on success |
| `ip` | IP address of the device used for verification |
| `user_name` | Name of the person as verified by Incode |
| `latitude` / `longitude` | Approximate geolocation of the device at verification time |

Here are some examples of how you might use this in Tines:

- **ATS integration** — use an HTTP Request action to add a `biometric-verified` tag and post a note to the candidate's profile in your applicant tracking system (e.g., Lever, Greenhouse, Workday).
- **IT provisioning** — trigger an account creation or password reset workflow once identity is confirmed, combining the verified name with a lookup in your corporate directory.
- **Access control** — update a record in your IAM or HRIS system to reflect that this person has completed biometric verification.
- **Helpdesk escalation** — send the verified identity details to a Slack channel or a support ticket so a human agent can take over with confidence.
- **Audit log** — write the `verification_trace_id`, verified name, IP, and timestamp to a Tines Record or external data store for compliance purposes.

To display the result for demonstration purposes, drag a **Page** object onto your workspace, set the **Page behavior** to **Show success message**, and set the success message to:

```undefined
Identity verification complete.

Verified name: INCODESTATUSWEBHOOK.BODY.DATA.USER_NAME
Trace ID: INCODESTATUSWEBHOOK.BODY.DATA.VERIFICATION_TRACE_ID
Processed: <<DATE("now")>>
```

## Summary

At the end of these steps, your Tines story will consist of two connected flows:

**Flow 1 — Send verification**

```undefined
[Collect user details] → [GetIncodeToken] → [GenerateVerificationLink] → [Send Email]
```

**Flow 2 — Receive result**

```undefined
[IncodeStatusWebhook] → [Check event_type] → [Use verified data]
```

This story shows how you can use the Incode Workforce API in Tines to verify the identity of any user — whether a job candidate, a new hire, a customer, or an employee requesting elevated access — and feed the result back into any downstream system Tines can reach.
