# Developer Documentation

This documentation will show you how to integrate Trust Swiftly into your Web Application and communicate with our private API.

### Quickstart Overview

| Integration Options (Web)                                                                          | Details                                                                                                                                                                                                                                                                                                          |
| -------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p><a href="/pages/NLBi8pzAblCbCFOPcfOP">Rest API</a></p><p> (Average 3-7 day effort to setup)</p> | Use the API to programmatically add users and modify required verifications. The API can be used by using the magic link to create a simple verification button. You are not able to directly send us images to analyze for documents. All verifications must be completed through the hosted link for security. |
| [No Code Managed](/hosted/share-hosted-link)                                                       | Use the no code integration to share a simple link through email, chat, or SMS which will redirect the user to a hosted page to complete verifications. This method requires an admin to add the user to verify manually and then review them once complete.                                                     |
| [iOS and Android Apps](/web/webview-ios-and-android)                                               | Use iOS and Android webview implementations to integrate your native app with Trust Swiftly.                                                                                                                                                                                                                     |
| <p><a href="/pages/-MVO4WnREeb4TDAIsnA-">No Code Self-Signup</a> </p><p>(3-minute setup)</p>       | Direct users to our signup page to register details themselves for onboarding and then allow them to complete the template verification request. This method requires no upfront work and can be used as customer identity management platform.                                                                  |

Each method to integrate above has pros and cons depending on your use case. For the simplest and fastest to manage process the no code self-signup works well. For more custom options we recommend our API.

***

#### Quickstart Guide

Welcome to Trust Swiftly! This guide will walk you through the essential end-to-end workflow in under 5 minutes. By the end, you will have created a user, retrieved their unique verification link, and received a webhook confirming their completion.

Let's get started.

**Prerequisites**

Before you begin, you'll need two things from your Trust Swiftly Dashboard:

1. **Your API Key:** Found under **Settings > API**.
2. **Your Webhook Signing Secret:** Found under **Settings > Webhooks**.

Keep these handy for the next steps.

***

#### Step 1: Create a User via the API

First, we'll register a new user in the Trust Swiftly system. The `reference_id` is crucial; this is your internal ID for the user (e.g., their ID from your database).

Open your terminal and run the following `curl` command. Make sure to replace `YOUR_API_KEY` with your actual key.

```bash
curl -X POST https://company.trustswiftly.com/api/users \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "reference_id": "user_12345",
    "email": "test@example.com",
    "first_name": "John",
    "last_name": "Doe"
  }'
```

You will receive a successful response containing the new user's details, including their unique Trust Swiftly `id` and a `magic_link`.

**✅ Successful Response:**

```json
{
	"status": "success",
	"id": 93,
	"magic_link": "https://company.trustswiftly.dev/security-verify?email=0&expires=1745613424&key=1ACSv57lwn7Z8Y0hF9V3&signature=cd6423294e2328a4fc85e7bc0410d3a&code=FC721Np"
}
```

**Tip:** The `magic_link` is the unique URL you will provide to your user to start their verification process.

***

#### Step 2: Set Up a Webhook Endpoint

To get notified when a user completes their verification, you need to set up a webhook endpoint. For this guide, we'll use the free service [webhook.site](https://webhook.site/) to create a temporary URL to inspect the payloads.

1. Open [webhook.site](https://webhook.site/) in a new tab. It will automatically generate a unique URL for you. Copy it.
2. In your Trust Swiftly Dashboard, navigate to **Settings > Webhooks**.
3. Paste the webhook.site URL into the **Endpoint URL** field and save your changes.

This will now send all events from your account to your temporary `webhook.site` page.

***

#### Step 3: Trigger a Verification Event

Now, let's trigger a test event.

1. Take the `magic_link` you received in the Step 1 response.
2. Open it in your web browser. (Use incognito or separate browser to maintain your Admin portal)
3. You will see the Trust Swiftly verification flow. Complete the steps.

***

#### Step 4: Confirm the Webhook

Once you complete the verification, Trust Swiftly will send a `verification.completed` event to the URL you configured.

Go back to your `webhook.site` page. You will see a new POST request appear on the left. Click on it to inspect the payload. It will be a JSON object that looks like this:

**✅ Webhook Payload Received:**

```json
{
  "id": "evt_fedcba98765",
  "event": "verification.completed",
  "created_at": "2024-10-26T12:05:00Z",
  "reference_id": "user_12345",
  "verifications": [
    {
      "name": "Email",
      "status": { "friendly": "done", "code": 100 }
    }
  ]
}
```

Notice that the `reference_id` matches the one you sent in Step 1. This is how you associate the verification event back to a user in your system.

***

#### What's Next?

Congratulations! You've successfully completed the core Trust Swiftly integration workflow.

Here's where to go from here:

* **Secure Your Endpoint:** Learn how to use your Signing Secret to verify that webhooks are genuinely from Trust Swiftly.
  * [**Verifying Webhook Signatures**](/webhooks/code-examples)
* **Build a Robust Handler:** See our best practices for processing webhooks reliably.
  * [**Handling Webhooks**](/webhooks/code-examples)
* **Explore the API:** Dive into the full API Reference to see what else you can do.
  * [**API Reference**](/api/users)


# Integration

This integration guide is for setting up our embedded verification option. Complete the prerequisites before integrating the flow.

## [**Alternate Integration Methods**](/)

## **Prerequisites**

### Step 1

Following the account creation, create your branded verification site for verifying your users. Your users will be verified on this URL for hosted integrations.

**Parameter to Note: `baseUrl`**

![](/files/-MdTVYUu6pW1ZvNsvw2_)

### Step 2

Create a template(s) for required verification(s) to assign to your users. You can create multiple templates and then use those templates as conditions to invoke multiple verification combinations to your users when they are created or trigger a risk action.

**Parameter to Note: `template_id`**

![Click Add Template](/files/-MdTW31lvwwJLVyJOH7d)

![Input the name and enable each verification assigned to the template](/files/-MdTWGhOw4TaQHCLUAJL)

### Step **3** <a href="#step-2" id="step-2"></a>

Generate your API keys by going to the Settings -> Developer, click on the create key to generate your key.

![Click Create API Key](/files/-MdTX3G0Y0uwRYZLtTwF)

The keys are only visible once so please copy and save the keys.

**KEY (`api_key`) :** This key will be used for API calls which are done through the server of your applications. For example: [Create User API](/api/users#create-user)

![Created keys to save](/files/-MdTY40XA9qjC2-o2Q-d)

***

#### Displaying the User Verification Flow

Once you have created a user via the API, the next step is to present them with the verification flow. Trust Swiftly uses a secure, unique **Magic Link** for this process. This link directs the user to a dedicated page to complete their verification steps.

There are two primary ways to present this flow to your users, both of which use the same core Magic Link technology.

***

#### Core Technology: The Magic Link

When you create a user, the API response contains a `magic_link`:

```json
{
  "id": "usr_abcde12345",
  "reference_id": "user_12345",
  // ... other fields
  "magic_link": "https://verify.trustswiftly.com/v/abcdef123456"
}
```

This URL is the entry point for the user's verification journey. You can guide what happens after completion by providing a `redirect_url` when you create the user. This is the **most critical step** for creating a seamless user experience.

**Example API call with redirect:**

```bash
curl -X POST https://company.trustswiftly.com/api/users \
  -H "Authorization: Bearer YOUR_API_KEY" \
  # ... other headers
  -d '{
    "reference_id": "user_12345",
    "email": "test@example.com",
    "redirect_url": "https://yourapp.com/verification-complete"
  }'
```

When the user finishes, they will be sent to:`https://yourapp.com/verification-complete?reference_id=user_12345&status=completed`

Now, let's look at how to use this link.

***

#### Method 1: Standard Web Redirect

This is the simplest method and is ideal for any web application. The user is redirected from your site to the verification page and then redirected back upon completion.

**How it works:**

1. Your user clicks a "Start Verification" button on your website.
2. This button links to the `magic_link` you received from the API.
3. The user completes the steps on the secure verification page.
4. After completion, they are automatically redirected back to the `redirect_url` you specified.

**Example HTML:**

```html
<!-- Get the magic_link from your backend and render it in the link's href -->
<a href="THE_MAGIC_LINK_FROM_THE_API_RESPONSE" class="button">
  Start Identity Verification
</a>
```

***

#### Method 2: Embedding in a Mobile App (Full Webview)

This method is ideal for providing a seamless experience within your native iOS or Android application. The verification flow is opened in an in-app browser (a "webview").

The process is nearly identical to the web redirect, but your native app must listen for the final redirect to know when the process is complete.

**How it works:**

1. Your mobile app gets a `magic_link` from your backend (which includes the `redirect_url`).
2. A user taps a "Start Verification" button in the app.
3. The app opens the `magic_link` in a full-screen webview.
4. The user completes the verification steps within the webview.
5. When finished, the webview will be redirected to your `redirect_url`.
6. Your native app code should **intercept this specific navigation event**. When it detects the webview navigating to your `redirect_url`, it knows the user is done and can programmatically close the webview and refresh the native UI.

This prevents the user from being "stuck" in the webview and provides a smooth transition back to your app's native experience.

***

#### Customization: Whitelabeling & Custom Domains

To create a truly integrated experience, you can remove all Trust Swiftly branding and host the verification flow on your own custom domain.

* **Remove Branding:** Replace the Trust Swiftly logo with your own.
* **Custom Domain:** Instead of `verify.trustswiftly.com`, the user will see a URL like `verify.yourdomain.com`.

This powerful feature gives your users confidence that they are still within your trusted ecosystem.

To configure this, navigate to **Settings > Branding** in your Trust Swiftly dashboard.


# Button Link

The button integration with a link is another simple integration that allows for faster page loading and minimal setup.

## Implementing the Verification Button

To start the verification flow, you will present the user with a button or link on your website. This element will use the unique magic\_link generated for that user.

This guide covers the full process: retrieving the link from your backend and displaying it on your frontend as a clickable button.

## Overview Steps

1. [Create a user](https://docs.trustswiftly.com/users#create-user) with our API with the information to verify.
2. Save the `magic_link` parameter to use for your button `href` value.
3. *(Optional)* [Regenerate the magic link](https://docs.trustswiftly.com/api/users#get-magic-link) for page refreshes or logins where the link is expired.
4. Display a button with the magic link. Recommended to use `target="_blank"` ([Example Bootstrap Button](https://www.tutorialrepublic.com/twitter-bootstrap-button-generator.php))
5. *(Optional)* Setup redirect URL and messages. You can direct users back to your website upon verification completion to inform them of next onboarding steps.
   1. `https://{sub-domain}.trustswiftly.com`**`/settings`**

Example code

```markup
<a class="btn btn-primary" href="https://demo1.trustswiftly.com/security-verify?expires=1622216986&key=17fwnw4Nux6JbVS3RePdDK6n41s2RGQTFXPP2Nj1AZ3ZKnPDD60RQ&signature=ea4da5121e023df8a9c7dfbfa715a56dc1ee3e55e5ef0d7e4986f22a72fb7cc2" target="_blank" role="button">Verify me</a>
```

![Example Verification Button](/files/-MadL9QvXeP4-WySWsdv)

## Button Assets

{% file src="/files/uoQwcJKhzh91fZMAk5Hs" %}
PNG Button Images
{% endfile %}

{% file src="/files/HhJRcpaSuSuw0QF4BnmN" %}
SVG Button Images
{% endfile %}

![Branded Trust Swiftly Buttons](/files/-MaoCjL-YyY6N7qsJFZz)

## Detailed Button Example

#### Step 1: Get the Magic Link from Your Backend

First, your server-side code needs to make an API call to Trust Swiftly to get the user's `magic_link`. You should trigger this when you need to display the button—for example, when rendering the user's profile page.

Here is a PHP example demonstrating how to get the link for a user with the `reference_id` of 'user\_12345'.

```php
<?php
// Your Trust Swiftly API Key and User's Reference ID
$apiKey = 'YOUR_API_KEY';
$referenceId = 'user_12345'; // The ID of the user in your system

// Make the API call to get user details
$url = 'https://app.trustswiftly.com/api/users/ref/' . $referenceId;
$options = [
    'http' => [
        'header' => "Authorization: Bearer " . $apiKey . "\r\n" .
                    "Accept: application/json\r\n",
        'method' => 'GET',
    ],
];
$context = stream_context_create($options);
$responseJson = file_get_contents($url, false, $context);

// Decode the JSON response and extract the magic_link
$responseData = json_decode($responseJson, true);
$magicLink = $responseData['magic_link'] ?? '#'; // Default to '#' if not found

// Now the $magicLink variable is ready to be used in your HTML.
?>
```

***

#### Step 2: Display the Button on Your Frontend

With the `$magicLink` variable available, you can now render the button. We provide a default CSS class, `.trust-swiftly-button`, to make a standard link look like a clean, modern button.

**Method A: For PHP / Server-Rendered Pages**

If your frontend is rendered with PHP, you can inject the variable directly into the `href` attribute of an `<a>` tag.

**HTML & PHP:**

```html
<!-- Use the PHP variable for the href attribute. -->
<!-- Using htmlspecialchars is a good security practice. -->
<a href="<?php echo htmlspecialchars($magicLink); ?>" class="trust-swiftly-button">
  Start Identity Verification
</a>
```

**Method B: For JavaScript / Single-Page Applications (SPAs)**

If you have a separate frontend (like React or Vue), you'll fetch the link from your own backend API and then dynamically update the button.

**HTML:**

```html
<!-- Give the button an ID so you can easily select it with JavaScript -->
<a id="verify-button" href="#" class="trust-swiftly-button">
  Start Identity Verification
</a>
```

**JavaScript:**

```javascript
// This function fetches user data from your own backend API
async function populateVerificationLink() {
  try {
    // This endpoint on YOUR server should return the magic_link
    const response = await fetch('/api/get-verification-link?userId=user_12345');
    const data = await response.json();

    if (data.magic_link) {
      const button = document.getElementById('verify-button');
      button.href = data.magic_link;
    }
  } catch (error) {
    console.error('Failed to get verification link:', error);
  }
}

// Call the function when the page loads
document.addEventListener('DOMContentLoaded', populateVerificationLink);
```

***

#### Step 3: Style the Link as a Button

To use our default button styling, add the following CSS class to your stylesheet. You can, of course, customize the colors to match your brand.

**Where to put this CSS?** You can add this to your main `.css` file or place it inside a `<style>` tag in the `<head>` of your HTML document.

```css
.trust-swiftly-button {
    background-color: #007bff; /* Primary Blue */
    color: #ffffff;            /* White Text */
    padding: 12px 24px;
    border-radius: 6px;
    text-decoration: none;      /* Removes the underline from the link */
    font-family: sans-serif;
    font-size: 16px;
    font-weight: bold;
    display: inline-block;      /* Allows padding and other box model properties */
    border: none;
    cursor: pointer;
    transition: background-color 0.2s ease-in-out;
}

.trust-swiftly-button:hover {
    background-color: #0056b3; /* A darker blue for hover */
}
```

#### Alternative: Using a `<button>` Element

If you prefer to use a semantic `<button>` tag instead of an `<a>` tag, you can use a small amount of JavaScript to trigger the navigation.

**HTML:**

```html
<button id="verify-js-button" class="trust-swiftly-button">
  Start Identity Verification
</button>
```

**JavaScript:**

```javascript
const magicLink = "THE_MAGIC_LINK_FROM_YOUR_API_CALL"; // Get this from your backend

document.getElementById('verify-js-button').addEventListener('click', () => {
  window.location.href = magicLink;
});
```


# Integrating with WordPress

To integrate Trust Swiftly with Wordpress it can be done in a similar manner as the HTML integration and link.

We provide two primary methods for integrating Trust Swiftly into your WordPress site. The best method depends on whether you are running a WooCommerce store or a different type of site.

* **For WooCommerce Stores:** Our official plugin is the fastest and easiest way to verify customer identities before or after checkout.
* **For Other WordPress Sites:** A custom code snippet can be used to add a verification button for your logged-in users.

***

## Method 1: WooCommerce Plugin (Recommended)

Our official plugin for WooCommerce allows you to seamlessly integrate identity verification into your checkout process. You can require users to verify their identity before they can complete a purchase, or trigger a verification check after an order is placed.

This is the recommended method for all WooCommerce stores.

**Key Features:**

* Gate checkout until a user's identity is verified.
* Automatically trigger verification checks after an order is submitted.
* Display a user's verification status in their "My Account" page.
* Simple setup with no custom coding required.

**Installation & Setup**

1. **Install the Plugin:** From your WordPress dashboard, navigate to **Plugins > Add New**. Search for "**Trust Swiftly Verification**" and click "Install Now," then "Activate."
2. **Enter Your API Credentials:** Go to **WooCommerce > Settings > Trust Swiftly**. Enter your **API Key** and **Webhook Signing Secret**. You can find these in your Trust Swiftly dashboard under **Settings**.
3. **Configure:** Set your preferences for when to require verification (e.g., before or after checkout).

For a full guide and to download the plugin, visit the official WordPress.org repository.

[View Official WooCommerce Plugin](https://wordpress.org/plugins/trust-swiftly-verification/)

***

## Method 2: Custom Integration for Non-WooCommerce Sites

If you are not using WooCommerce or need a more custom implementation (e.g., for a membership site, online course, or custom user profiles), you can add a dynamic verification button using a custom **shortcode**.

This method will automatically generate a verification button for any user who is logged into your WordPress site. It uses WordPress's built-in caching system to ensure it doesn't slow down your site.

**Step 1: Add the Code to `functions.php`**

Copy the entire PHP code block below and add it to the `functions.php` file of your active WordPress theme. You can do this by navigating to **Appearance > Theme File Editor** from your dashboard.

```php
<?php
/**
 * Trust Swiftly: Creates a shortcode [trust_swiftly_button] to display a verification button
 * for the currently logged-in user. Caches the link for 12 hours.
 */
function trust_swiftly_verification_button_shortcode() {
    if ( ! is_user_logged_in() ) {
        return ''; // Don't show anything if the user is not logged in.
    }

    $current_user = wp_get_current_user();
    $user_id = $current_user->ID; // Using WordPress User ID as the reference_id

    $transient_key = 'trust_swiftly_magic_link_' . $user_id;
    $cached_link = get_transient( $transient_key );

    if ( false !== $cached_link ) {
        $magicLink = $cached_link;
    } else {
        $apiKey = 'YOUR_API_KEY'; // <-- PASTE YOUR API KEY HERE

        $url = 'https://app.trustswiftly.com/api/users/ref/' . $user_id;
        $args = [ 'headers' => [ 'Authorization' => 'Bearer ' . $apiKey, 'Accept' => 'application/json' ] ];
        $response = wp_remote_get( $url, $args );

        if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
            return '<!-- Trust Swiftly: Error retrieving link. -->';
        }

        $body = wp_remote_retrieve_body( $response );
        $data = json_decode( $body, true );
        $magicLink = $data['magic_link'] ?? '';
        
        if ( ! empty( $magicLink ) ) {
            set_transient( $transient_key, $magicLink, 12 * HOUR_IN_SECONDS );
        }
    }

    if ( ! empty( $magicLink ) ) {
        return '<a href="' . esc_url( $magicLink ) . '" class="trust-swiftly-button">Start Identity Verification</a>';
    }

    return '';
}

// Register the shortcode so WordPress recognizes it.
add_shortcode( 'trust_swiftly_button', 'trust_swiftly_verification_button_shortcode' );
?>
```

**Warning:** Always be careful when editing `functions.php`. A syntax error can cause issues with your site.

**Step 2: Add the Shortcode to Your Page**

Edit any page where you want the button to appear (e.g., a "My Profile" or "Account Details" page). Add a **Shortcode** block and type in:

`[trust_swiftly_button]`

When a logged-in user views this page, they will see their personal verification button. Logged-out users will see nothing.

**Step 3: Style the Button**

Use the CSS on our Button & Link page to style the button to match your site's branding.


# WebView iOS and Android

The WebView option allows individuals to verify their identity in a mobile app with the Android WebView or iOS WKWebView.

## Mobile WebView Integration (iOS & Android)

For a seamless, in-app user experience, you can embed the Trust Swiftly verification flow within your native mobile app using a WebView component. This guide will walk you through the implementation for both Android and iOS.

The core technology is the same **Magic Link** used in web integrations, but with a specific pattern to control the user flow.

***

#### The Core Concept: The "Redirect-to-Close" Pattern

This is the most important concept for a successful WebView integration.

1. **Get the Link:** Your app gets a unique `magic_link` for a user from your backend.
2. **Provide a Redirect URL:** When your backend creates or requests the user link from the Trust Swiftly API, it **must** include a `redirect_url`. This URL should be a custom, non-existent URL that your app can uniquely identify (e.g., `https://yourapp.com/verification-complete`).
3. **Open the WebView:** Your app opens the `magic_link` in a full-screen WebView.
4. **User Completes Flow:** The user completes the verification steps inside the WebView.
5. **Trust Swiftly Redirects:** Upon completion, our server redirects the WebView to the `redirect_url` you provided.
6. **Your App Intercepts the Redirect:** Your app's native code must listen for navigation events within the WebView. When it detects the WebView attempting to navigate to your specific `redirect_url`, it knows the process is complete.
7. **Your App Closes the WebView:** Upon detecting the redirect, your app programmatically closes the WebView and returns the user to your native UI.

This pattern ensures a smooth transition back to your application without the user getting "stuck" on a "verification complete" page inside the WebView.

***

## Android `WebView` Guide

**Step 1: Configure Permissions & Manifest**

First, ensure your `AndroidManifest.xml` includes the necessary permissions for camera access and is configured to handle the WebView activity.

```xml
<!-- AndroidManifest.xml -->
<manifest ...>
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />

    <application ...>
        <activity android:name=".TrustSwiftlyWebViewActivity" />
        <!-- ... other activities -->
    </application>
</manifest>
```

**Step 2: Implement the WebView Activity**

Create a dedicated `Activity` to host the `WebView`. This code provides a complete, robust implementation that handles permissions, file uploads, and the critical redirect-to-close pattern.

```java
// TrustSwiftlyWebViewActivity.java
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.webkit.PermissionRequest;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import androidx.appcompat.app.AppCompatActivity;

public class TrustSwiftlyWebViewActivity extends AppCompatActivity {

    public static final String EXTRA_MAGIC_LINK = "extra_magic_link";
    private static final String REDIRECT_URL = "https://yourapp.com/verification-complete"; // Your unique redirect URL

    private WebView webView;
    private ValueCallback<Uri[]> filePathCallback;
    // ... (Add other variables for file chooser logic from your original docs if needed)

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webview); // Assume a simple layout with a WebView

        webView = findViewById(R.id.webView);
        String magicLink = getIntent().getStringExtra(EXTRA_MAGIC_LINK);

        // --- Basic WebView Settings ---
        WebSettings settings = webView.getSettings();
        settings.setJavaScriptEnabled(true);
        settings.setDomStorageEnabled(true);
        settings.setMediaPlaybackRequiresUserGesture(false);

        // --- The two most important clients ---
        webView.setWebViewClient(new TrustSwiftlyWebViewClient());
        webView.setWebChromeClient(new TrustSwiftlyWebChromeClient());

        if (magicLink != null) {
            webView.loadUrl(magicLink);
        }
    }

    // This client handles page navigation and the redirect-to-close pattern.
    private class TrustSwiftlyWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            // === THIS IS THE MOST IMPORTANT PART ===
            // Check if the WebView is being redirected to our special URL.
            if (url.startsWith(REDIRECT_URL)) {
                // The flow is complete. Set a result and finish this activity.
                setResult(Activity.RESULT_OK);
                finish();
                return true; // Stop the redirect from actually loading.
            }
            return super.shouldOverrideUrlLoading(view, url);
        }
    }

    // This client handles UI-related events like permissions and file choosers.
    private class TrustSwiftlyWebChromeClient extends WebChromeClient {
        // This is for requesting camera permission when needed by the webpage.
        @Override
        public void onPermissionRequest(PermissionRequest request) {
            // NOTE: This is a simplified example. A production app should handle
            // permission requests more gracefully.
            request.grant(request.getResources());
        }

        // This is for handling file uploads (e.g., uploading an ID document).
        @Override
        public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
            TrustSwiftlyWebViewActivity.this.filePathCallback = filePathCallback;
            // (Your existing robust file chooser logic goes here)
            // ...
            return true;
        }
    }
    
    // (Your existing onActivityResult and onRequestPermissionsResult logic goes here)
    // ...
}
```

**Step 3: Launch the Activity**

From another part of your app, launch the `TrustSwiftlyWebViewActivity` and pass the `magic_link`.

```java
// In your main activity or fragment
Intent intent = new Intent(this, TrustSwiftlyWebViewActivity.class);
intent.putExtra(TrustSwiftlyWebViewActivity.EXTRA_MAGIC_LINK, "YOUR_MAGIC_LINK_FROM_API");
startActivityForResult(intent, YOUR_REQUEST_CODE);
```

***

## iOS `WKWebView` Guide

**Step 1: Configure Permissions (`Info.plist`)**

Your app must include an entry for `NSCameraUsageDescription` in its `Info.plist` file to explain why it needs camera access.

```xml
<!-- Info.plist -->
<key>NSCameraUsageDescription</key>
<string>We need access to your camera to verify your identity.</string>
```

**Step 2: Implement the WebView Controller**

Create a dedicated `UIViewController` to manage the `WKWebView`. This controller will handle loading the URL, delegating permissions, and intercepting the final redirect.

```swift
// TrustSwiftlyWebViewController.swift
import UIKit
import WebKit

class TrustSwiftlyWebViewController: UIViewController, WKNavigationDelegate, WKUIDelegate {

    var magicLink: URL!
    var webView: WKWebView!
    let redirectUrl = "https://yourapp.com/verification-complete" // Your unique redirect URL

    override func loadView() {
        let webConfiguration = WKWebViewConfiguration()
        webConfiguration.allowsInlineMediaPlayback = true // Prevents fullscreen video takeover
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.navigationDelegate = self
        webView.uiDelegate = self
        view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        webView.load(URLRequest(url: magicLink))
    }

    // === THIS IS THE MOST IMPORTANT PART ===
    // This delegate method is called whenever the WebView decides to navigate.
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        if let urlString = navigationAction.request.url?.absoluteString, urlString.starts(with: redirectUrl) {
            // The flow is complete. Dismiss this view controller.
            self.dismiss(animated: true, completion: nil)
            decisionHandler(.cancel) // Stop the redirect from actually happening.
            return
        }
        decisionHandler(.allow) // Allow all other navigation.
    }
    
    // This delegate handles JavaScript UI, like permission requests.
    func webView(_ webView: WKWebView, requestMediaCapturePermissionFor origin: WKSecurityOrigin, initiatedByFrame frame: WKFrameInfo, type: WKMediaCaptureType, decisionHandler: @escaping (WKPermissionDecision) -> Void) {
        // Automatically grant camera permission to provide a smoother experience.
        decisionHandler(.grant)
    }
}
```

**Step 3: Present the Controller (SwiftUI Example)**

From your main application view, present the `TrustSwiftlyWebViewController` as a sheet.

```swift
// Your main SwiftUI View
import SwiftUI

struct ContentView: View {
    @State private var showVerification = false
    // In a real app, this would be fetched from your backend.
    let magicLink = "YOUR_MAGIC_LINK_FROM_API"

    var body: some View {
        Button("Start Verification") {
            self.showVerification.toggle()
        }
        .sheet(isPresented: $showVerification) {
            // Bridge to the UIKit ViewController
            VerificationView(magicLink: URL(string: magicLink)!)
        }
    }
}

// A helper to wrap our UIViewController for use in SwiftUI
struct VerificationView: UIViewControllerRepresentable {
    let magicLink: URL

    func makeUIViewController(context: Context) -> some UIViewController {
        return TrustSwiftlyWebViewController(magicLink: magicLink)
    }

    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {}
}
```

***

### **Common Issues**

> ❗️Multiple signups
>
> If testing your app and creating multiple verify sessions you should clear the cookies and cache of WKWebView inbetween new user sessions. (Refer to [this guide](https://stackoverflow.com/questions/27105094/how-to-remove-cache-in-wkwebview))
>
> ```swift
> WKWebsiteDataStore.default().removeData(ofTypes: [WKWebsiteDataTypeDiskCache, WKWebsiteDataTypeMemoryCache], modifiedSince: Date(timeIntervalSince1970: 0), completionHandler:{ })
> ```
>
> ❗️Webkit Inline Media Playback
>
> Please ensure `allowsInlineMediaPlayback` is enabled when creating a webview on a webkit browser (mobile Safari). This defaults to false and the camera preview will incorrectly open as a fullscreen live broadcast.

> ❗Camera Configuration
>
> The WebView Flow requires access to the device camera. Please include the `NSCameraUsageDescription` key your app's `Info.plist` file as described in the [Apple Developer documentation](https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_ios).

> ❗️Allow External Network Requests
>
> Trust Swiftly makes external network calls within the Inquiry Flow that need to be allowlisted for the flow to properly function. Certain frameworks such as [Cordova](https://cordova.apache.org/docs/en/11.x/guide/appdev/allowlist/index.html#network-request-allow-list) require such requests to be allow listed. Please include `*.trustswiftly.com/*` in such an allow list if needed

Make sure permissions are correctly set for your app bundle.

* Camera and Microphone Permission

<figure><img src="/files/7dKVMoOKjfPV7SbpjUAS" alt=""><figcaption></figcaption></figure>


# Bubble ID Verify Integration

Learn to integrate Bubble.io with Trust Swiftly for the ultimate identity verification experience. Add ID, Selfie, phone and more checks to your Bubble app using no-code.

### Overview <a href="#oqkjd09v5117" id="oqkjd09v5117"></a>

Trust Swiftly provides powerful identity verification tools to help fast-moving businesses ensure secure and seamless customer onboarding. This guide demonstrates how to integrate Trust Swiftly's verification services into a [Bubble.io](https://bubble.io/) app. The example app allows users to register, complete ID verification, and view their verification status—all within the Bubble platform. Following this guide will teach you how to create a user for verification, implement the verification process, and handle the verification status using Trust Swiftly's API and webhooks.

{% hint style="info" %}
The below guide is an example of a basic Bubble integration. For more advanced scenarios it is advised to customize the flow according to your app and business case.&#x20;
{% endhint %}

### Prerequisites <a href="#ib80hoa63njf" id="ib80hoa63njf"></a>

* A Bubble account with a basic understanding of creating and managing Bubble apps.
* API access to Trust Swiftly. Ensure you have your API key ready.
* Familiarity with webhooks and Bubble's API workflows.

### Steps to Implement <a href="#vpk8v7qplj7v" id="vpk8v7qplj7v"></a>

#### Set Up API Key in Bubble <a href="#e977opyntum1" id="e977opyntum1"></a>

Before making API calls to Trust Swiftly, you must configure your API key in Bubble.

* In your Bubble app, navigate to the "Plugins" tab and add the API Connector plugin if you haven't already.
* Open the API Connector plugin and create a new "Create User" API.
* Click the "Add another call" button.

<figure><img src="/files/lSHKySIKSMJMSiZGKKTU" alt=""><figcaption></figcaption></figure>

#### Create a User for Verification <a href="#na5hpzqhvkrf" id="na5hpzqhvkrf"></a>

To verify a user through Trust Swiftly, you'll first need to create the user via their API. This user will undergo the ID verification process.

1. Name the API Call:

○      In the API Connector plugin, name your API call, and in the "Use as" dropdown, select "Action."

2. Set the API Details:

○      Data Type: Set this to "JSON."

○      API Method: Choose POST.

○      API URL: Enter the Trust Swiftly API endpoint URL where the user will be created.

3. Add Headers:

○      In the "Headers" section, click "Add header" and include the following:

■      Authorization:

■      Key: *Authorization*

■      Value: *Bearer YOUR\_API\_KEY* (replace YOUR\_API\_KEY with the actual API key provided by Trust Swiftly)

■      Content-Type:

■      Key: *Content-Type*

■      Value: *application/json*

4. Set the Request Body:

○      Body Type: Select "JSON."

○      JSON Body: Enter the JSON body structure, using <> brackets for dynamic values that will be filled in from your app’s data.

5. Initialize the API Call:

○      Uncheck the "Private" checkbox under the body parameters to ensure the fields are editable in workflows.

○      Click the "Initialize Call" button to test the API call. If successful, Bubble will display the API response. Save the call configuration once it's successfully initialized.

<figure><img src="/files/SCQGLftEODtA0Sz1KtR3" alt=""><figcaption></figcaption></figure>

#### &#x20;**Use Dynamic Data:**

To send dynamic user data from your Bubble app during registration, you'll need to link your form inputs to the API parameters.

○      In your registration workflow, after the user clicks the "Register" button, add an action to trigger the API call.

○      After that add another action. Click on “plugins” and select the API call you just configured.

<figure><img src="/files/F01Zs2m4A75xjnxVwBqU" alt=""><figcaption></figcaption></figure>

&#x20;

○      Once Clicked another panel will appear and there, add all the parameters you want in your JSON body and in the Value field add the form values.

<figure><img src="/files/uU4NxzX7C5LDJnVm19Ea" alt=""><figcaption></figcaption></figure>

&#x20;

Now, when you enter all the details in the form and hit the “Register button,” it will send a request to the API and create the user with the information provided.

**Handle API Response: Storing the Magic Link**

When the API request is successful, Trust Swiftly will return a response containing the magic link, which the user can use to verify their identity. This magic link should be stored in your Bubble database for further use.

**Steps to Handle the Response:**

1. In the workflow, after the API call action, add a new action to store the response data.
2. In Bubble, create a new field in your User data type called "Magic Link."

○      Data Type: Text

3. Set up an action to store the magic link in the "Magic Link" field of the user who just registered.

○      In the workflow, select the action "Make Changes to a Thing."

○      Thing to Change: Current User

○      Field to Change: Magic Link

○      Value: Result of Step X (API call) → Magic Link (replace "X" with the step number where the API call is made).

By storing the magic link in the Bubble database, you can later use it to redirect users to the verification page

#### Handle Verification Button and Email Magic Link <a href="#v1eoscjdl4hb" id="v1eoscjdl4hb"></a>

After successfully creating the user, the next step is to enable the user to initiate the ID verification process. When the user clicks the "Verify" button, they should receive a magic link via email, which they will use to complete the verification.

1. Handle Email Sending:

○      When the user clicks the "Verify" button, you'll need to trigger an action that sends the magic link to the user’s email.

○      Note: Ensure that the magic link is correctly stored in your Bubble database (as set up in the previous section).

2. Set Up an Email Workflow:

○      Go to the “Workflows” section in Bubble and create a new workflow for when the "Verify ID" button is clicked.

○      Action: Send an email with the magic link.

■      Use Bubble’s email functionality (e.g., the “Send email” action) to send an email to the Current User.

■      In the email body, include the magic link retrieved from the database. You can format it as follows:

&#x20;       <img src="/files/QF5QwRf7vnkjoEu7fkxL" alt="" data-size="original">

3. **Verify Email Sending:**

○      Ensure that the email action is correctly configured and that the email is sent to the user's registered email address with the correct magic link.

By implementing these steps, users can receive their magic link via email and complete the ID verification process. Ensure you test the entire workflow to verify that emails are sent correctly and that the link directs users to the appropriate verification page.

&#x20;

#### Setting Up Email Notifications and Handling the Verification Process <a href="#rqiru757dz1s" id="rqiru757dz1s"></a>

Before managing the verification process, you need to ensure that email notifications are enabled for your user in Trust Swiftly. Follow these steps to set up email notifications and handle the verification process:

**Set Up Email Notifications for Verification**

1. **Access Trust Swiftly Users Page:**

○      Log in to your Trust Swiftly account and navigate to the “Users” page.

2. **Find the User:**

○      Locate the user you want to verify by searching for their details (e.g., email or user ID).

3. **Click Verification Button:**

○      Select the user and click on the “Verification” button to access the verification settings.

<figure><img src="/files/y8yB7lNwLFyaPQdKmzXX" alt=""><figcaption></figcaption></figure>

4. Enable Email Notifications:

○      In the verification settings, ensure that email notifications are enabled.

○      This setting allows Trust Swiftly to send the necessary verification emails to the user, including the magic link and any follow-up emails if additional verification is needed.

<figure><img src="/files/3jDdyShccqQ1n4S6Ay5P" alt=""><figcaption></figcaption></figure>

&#x20;

**Receive and Access the Magic Link**

1. Initial Email with Magic Link:

○      The user receives an email with a magic link from Trust Swiftly.

○      Clicking this link directs the user to a verification page with a "Verify" button.

**Click the Magic Link and Verify Identity**

1. Verification Page:

○      On the verification page, the user clicks the "Verify" button to start the verification process.

<figure><img src="/files/VrZ31eeYlV5E94NHJbq3" alt=""><figcaption></figcaption></figure>

2. Initial Verification Attempt:

○      Trust Swiftly processes the verification request. If additional verification is required, the user will receive a follow-up email.

**Follow-Up Email**

1. Receive Follow-Up Email:

○      If further verification is necessary, Trust Swiftly sends a follow-up email.

○      Example Content:

■      “Due to an additional review we require another method of verification. Please complete the new request to verify yourself.”

■      Verify Identity Button: Includes a button or URL for completing the additional verification.

<figure><img src="/files/o1tIWrjQc77fdlI4reMT" alt=""><figcaption></figcaption></figure>

○      Click on Confirm Email button and it will redirect you another page

○      Enter your email in the field and click the “Send verification Email” button

<figure><img src="/files/tpA3HMZdrllSy5fRXI5D" alt=""><figcaption></figcaption></figure>

#### Set Up Webhook for Verification Status <a href="#tw1o0sw15r4f" id="tw1o0sw15r4f"></a>

To keep track of the verification status, you need to set up a webhook with Trust Swiftly and configure Bubble to handle the incoming webhook data. This will allow you to update the user’s verification status based on Trust Swiftly's notifications.

1\. Create a Webhook in Trust Swiftly

1. Log in to your Trust Swiftly account and navigate to the Webhooks section in the dashboard under “Developers” tab.
2. Create a New Webhook:

○      Click on “Create Webhook” to start the setup process.

<figure><img src="/files/0twH8dJy1EpFhD64LOd9" alt=""><figcaption></figcaption></figure>

○      Webhook URL: Enter the URL where Trust Swiftly will send the webhook notifications. This should be the endpoint of your Bubble app that will handle incoming webhooks. (See section “Configure Backend Workflow Bubble” below)

○      Verifications: Select “Email”

○      Webhook Events: Verification.completed

○      Save: Complete the setup by saving the webhook configuration.

<figure><img src="/files/dAmqZ7kOolS09bjcH41X" alt=""><figcaption></figcaption></figure>

2\. Configure Backend Workflow in Bubble

1. Set Up the Webhook Endpoint:

○      In your Bubble app, go to the "API Workflows" section.

○      Create a new API workflow. This will serve as the endpoint for handling webhook requests.

○      Endpoint Name: Choose a meaningful name (e.g., *handle\_verification\_webhook*).

○      Endpoint URL: Bubble will generate a URL for this workflow. Copy this URL and use it as the Webhook URL in Trust Swiftly.

2. Define the API Workflow:

○      Add Actions to handle the incoming data from Trust Swiftly.

○      Verifyuser api workflow settings:

■      Change “Trigger workflow with” method to POST

■      Click on Detect Data to get the URL of the API that’ll be later on used in the webhook.

<figure><img src="/files/BqcfBkiHk5hzlhIlH6M5" alt=""><figcaption></figcaption></figure>

○      Parse the Webhook Data: Use Bubble’s built-in actions to extract relevant information from the webhook payload (verification status).

○      Update the User Record:

■      Use the "Make Changes to a Thing" action to update the user’s record in your Bubble database based on the information received.

■      For example, if the webhook indicates that the verification status is complete, update the corresponding field in the user’s profile.

&#x20;<img src="/files/EqaHUPgDwn5nVABTy0dK" alt="" data-size="original">

By following these steps, you’ll be able to set up and handle webhooks from Trust Swiftly, ensuring your Bubble app stays in sync with the latest verification status updates.

#### Redirect Users to Success Page Upon Verification <a href="#id-31b6j9ytejw8" id="id-31b6j9ytejw8"></a>

Once the user completes the verification process, you need to ensure they are redirected to a success page to confirm their verification status.

1\. Handle Verification Completion in Bubble

1. **Update API Workflow:**

○      In the API workflow that handles the Trust Swiftly webhook (as described in the previous section), include an additional action to redirect the user.

○     **After Updating User Record:**

■      Add an action to send a response or trigger a redirect based on the verification status.

2. **Set Up Redirection Logic:**

○      Trigger Redirection:

■      Use Bubble’s “Go to page” action to redirect the user to the success page that is triggered when the user's verification field is changed.

■      Set up the URL of the success page (e.g., /success) in the workflow action.

**Example Workflow Configuration:**

●      Endpoint Name: *verification\_success\_redirect*

●      Actions:

○      Update User Record: Ensure the user’s verification status is updated.

○      Redirect User: Use “Go to page” action to direct the user to the success page.

Example Success Page

<figure><img src="/files/8FCnwG2DKMDWaY4sxIkH" alt=""><figcaption></figcaption></figure>

By setting up the redirection to a success page, you provide users with an explicit confirmation of their verification status, enhancing the overall user experience.

&#x20;

&#x20;

&#x20;

&#x20;

&#x20;

&#x20;


# FlutterFlow Identity Verification

Integrating FlutterFlow with Trust Swiftly can significantly enhance your app's security and user verification processes with ID checks, selfies, KYC, and more.

### Overview <a href="#oqkjd09v5117" id="oqkjd09v5117"></a>

Trust Swiftly provides powerful identity verification tools designed to help fast-moving businesses ensure secure and seamless customer onboarding. This guide demonstrates how to integrate Trust Swiftly's verification services into a [FlutterFlow ](https://flutterflow.io/)app. The example app allows users to register, complete ID verification, and view their verification status—all within the FlutterFlow platform. By following this guide, you'll learn how to create a user for verification, implement the verification process, and handle the verification status using Trust Swiftly’s API and webhooks.

{% hint style="info" %}
The following guide is for reference purposes only to integrate with FlutterFlow. For production and advanced usage, you may be required to customize the setup.&#x20;
{% endhint %}

### Prerequisites <a href="#ib80hoa63njf" id="ib80hoa63njf"></a>

* A [FlutterFlow account](https://app.flutterflow.io/create-account) with a basic understanding of how to create and manage FlutterFlow apps.
* API access to Trust Swiftly. Ensure you have your [API key ready](/api/getting-an-api-key).
* Familiarity with webhooks and FlutterFlow’s API workflows.

### Steps to Implement <a href="#vpk8v7qplj7v" id="vpk8v7qplj7v"></a>

#### Set Up API Key in FlutterFlow <a href="#e977opyntum1" id="e977opyntum1"></a>

Before you start making API calls to Trust Swiftly, you need to configure your API key in FlutterFlow.

* In your FlutterFlow app, navigate to the "API Calls" tab
* Click on the + Add API Call button to start creating a new API integration.

![](/files/uG0T07s7Ya9ScJkJsxAq)

#### Create a User for Verification <a href="#na5hpzqhvkrf" id="na5hpzqhvkrf"></a>

To verify a user through Trust Swiftly, you'll first need to create the user via their API. This user will undergo the ID verification process.

1. **Name the API Call**:
   * Give your API call a name, like “CreateUser”
2. **Set the API Details**:
   * **API Method**: Choose POST.
   * **API URL**: Enter the Trust Swiftly API endpoint URL where the user will be created.
3. **Add Headers**:
   * In the "Headers" section, click "Add header" and include the following:
     * **Authorization**:
       * **Key**: Authorization
       * **Value**: Bearer YOUR\_API\_KEY (replace YOUR\_API\_KEY with the actual API key provided by Trust Swiftly)
     * **Content-Type**:
       * **Key**: Content-Type
       * **Value**: application/json

<figure><img src="/files/OErXmeE4BZlnpCHKEKQO" alt=""><figcaption></figcaption></figure>

**Create Variables:**

* Go to the Variables section in Define API Call
* Click Add Variable and define your variables (e.g., email) Choose the appropriate type based on what the variable will hold (e.g., String).

<figure><img src="/files/JxESBft7eRtmXIFKLm2r" alt=""><figcaption></figcaption></figure>

1. **Set the Request Body**:

* Go to the Body section in Define API Call
  * **Body Type**: Select "JSON."
  * **JSON Body**: Enter the JSON body structure, drag and drop variables for dynamic values that will be filled in from your app’s data.

<figure><img src="/files/WnMDqKM3sOLFzhw9ThSk" alt=""><figcaption></figcaption></figure>

**6. Testing Your API Call**

1. **Set Variable Values:**
   * Go to the **Response and Test** tab in the API configuration.
   * Enter sample values for your variables to test the API call.
2. **Run the Test:**
   * Click “**Test API Call”** to execute the API call with the provided variable values.
   * Check the response to ensure that the API call is functioning as expected.

<figure><img src="/files/ZHLrVDlSzT56UMAjtZj1" alt=""><figcaption></figcaption></figure>

**7. Using API Responses**

1. **Handle API Responses:**
   * After Testing API call go to “Response Type” section which is just below “Preview and Test” section.
   * Click on “Add JSON path” of the JSON Path named “$.magic\_link”.
   * Give JSON Path a name, like “magicLink”

<figure><img src="/files/9mxQ2Q4fMgCP0csuTyMT" alt=""><figcaption></figcaption></figure>

1. **Initialize the API Call**:
   * After configuring all necessary parameters, request body, and endpoint details, click the “Add Call” button.
   * This action will save the API call configuration in your FlutterFlow project.

#### Setting Up Register Button Action

**1. Setting Up the API Action**

1. **Navigate to the Register Button:**
   * Locate the page containing the register button that will trigger the API call.
2. **Configure Button Click Action:**
   * Select the register button widget on your page.
   * In the widget properties panel, locate the **Actions** section.

<figure><img src="/files/Bo0D5g2JpMi6TjLdZsFO" alt="" width="356"><figcaption></figcaption></figure>

1. **Add API Call Action:**
   * Open Action Flow Editor
   * Click on **Add Action** to create a new action.
   * Choose **API Call** from the list of action types.
   * Drop down “Group or Call Name” and select your API i.e “createuser”.

<figure><img src="/files/Angya843cNOxaUyK2ODc" alt="" width="563"><figcaption></figcaption></figure>

1. **Map Button Inputs to API Call Parameters:**
   * “**Create User API**” requires parameters such as email, map these inputs to the corresponding fields in the API call configuration.
   * Click on “Set Additional Variable” and drop-down Variable name and select the variables needed by your API.
   * Click on dynamic value button (represented by orange icon)
   * Drop down “Widget State” and select the field corresponding to your variable.
   * Name “Action Output Variable Name” as APIResponse. Magic link will be stored in this variable

**2. Navigating to the Verification Page**

1. **Add Navigation Action:**
   * After configuring the API call, click **Add Action** again to create a new action.
   * Select **Navigate to Page** from the list of action types.
   * Choose the verification page you want to navigate to upon successful registration.
2. **Pass Parameters to Verification Page:**
   * Go to Verification Page and Click **Edit Parameters Icon.**
   * Click on “Add Parameters” and name your parameter as “email” and “magiclink” and define the type as string.

![](/files/KNrBCBO0ie4TE744sYFb)

![
](/files/2sMAOGVLt09mqYDoYEpI)

**3. Configuring Parameters**

1. **Click on “Pass” to Add New Parameters:**
   * Go to back to your **Action Flow Editor** in the signup page where your register button is located
   * In the navigation action settings, configure the parameters to be passed to the verification page.
   * Click on “Pass” to add new Parameters
   * Enter the required parameters, such as email and magic link, and assign dynamic values.

Example:

* **Parameter Name:** email
  * **Value Source:** Bind to the email input field or the result from the API call.

1. **Configuring the Magic Link Parameter**
   * For Magic link, drop-down “**Action Outputs**” and select “APIResponse”

<figure><img src="/files/VYiXo9i1fyGPsm08CNKJ" alt="" width="563"><figcaption></figcaption></figure>

* Provide the JSON path to extract the magic link from the API response.
* In **API Response Options**, drop-down and select “JSON Body”.
* In **Available Options,** select “JSON Path”.
* Provide the **JSON path** to extract the magic link from the API response. For example, if the API response contains the magic link at $.magic\_link, specify this path.
* After configuring the parameters and selecting the appropriate action outputs, click **“Confirm”** to save your changes.

![](/files/LYZZ7HWmNIfjMsuf9zWS)

By following these steps, you can configure an action to invoke an API call when a register button is clicked, and ensure that the application navigates to a verification page while passing essential parameters such as email and magic link. This setup streamlines the registration and verification process, enhancing user experience and interaction within your app.

#### Handle Verification Button and Email Magic Link

After successfully creating the user, the next step is to enable the user to initiate the ID verification process. When the user clicks the "Verify" button, they should receive a magic link via email, which they will use to complete the verification.

1. **Handle Redirection to Magic Link**:
   * When the user clicks the "Verify" button, you'll need to trigger an action that redirects the user to magic link.
   * Add an action “Launch URL” and set the URL Value Type to “From Variable”.
   * Drop-down page parameter and select “magiclink”.

This will redirect the user to magic link when the verify button is clicked

![
](/files/zLnPHDVIMUDosCYxX2TE) ![](/files/BpiWL4Fy7IRtpRbeXAhk)

**Set Up Email Notifications for Verification**

1. **Access Trust Swiftly Users Page:**
   * Log in to your Trust Swiftly account and navigate to the “Users” page.
2. **Find the User:**
   * Locate the user you want to verify by searching for their details (e.g., email or user ID).
3. **Click Verification Button:**
   * Select the user and click on the “Verification” button to access the verification settings.

![](/files/rQdTDF1BTyWZ6ar8ZOTW)

1. **Enable Email Notifications:**
   * In the verification settings, ensure that email notifications are enabled.
   * This setting allows Trust Swiftly to send the necessary verification emails to the user, including the magic link and any follow-up emails if additional verification is needed.

<img src="/files/GCUeYUEHGwa1TOVJw7As" alt="" width="448">

**Receive and Access the Magic Link**

1. **Initial Email with Magic Link:**
   * The user receives an email with a magic link from Trust Swiftly.
   * Clicking this link directs the user to a verification page with a "Verify" button.

**Click the Magic Link and Verify Identity**

1. **Verification Page:**
   * On the verification page, the user clicks the "Verify" button to start the verification process.

<img src="/files/vJRkpp7c8sbTgEMnf26B" alt="" width="347">

1. **Initial Verification Attempt:**
   * Trust Swiftly processes the verification request. If additional verification is required, the user will receive a follow-up email.

**Follow-Up Email**

1. **Receive Follow-Up Email:**
   * If further verification is necessary, Trust Swiftly sends a follow-up email.
   * Example Content:
     * “Due to an additional review we require another method of verification. Please complete the new request to verify yourself.”
     * Verify Identity Button: Includes a button or URL for completing the additional verification.

<img src="/files/a028wXfmEMfQHkCox7XV" alt="" width="355">

* * Click on Confirm Email button and it will redirect you another page
  * Enter your email in the field and click the “Send verification Email” button

<img src="/files/Bpig0CFrpkseqOkOpPK7" alt="" width="519">

#### Set Up Webhook for Verification Status <a href="#tw1o0sw15r4f" id="tw1o0sw15r4f"></a>

To keep track of the verification status, you need to set up a webhook with Trust Swiftly and configure FlutterFlow to handle the incoming webhook data. This will allow you to update the user’s verification status based on Trust Swiftly's notifications.

**1. Create a Webhook in Trust Swiftly**

1. **Log in** to your Trust Swiftly account and navigate to the Webhooks section in the dashboard under “Developers” tab.
2. **Create a New Webhook**:
   * Click on “Create Webhook” to start the setup process.

![](/files/wlFGrZSPViUJhqeIl7A2)

* **Webhook URL**: Enter the URL where Trust Swiftly will send the webhook notifications. This should be the endpoint of your FlutterFlow app that will handle incoming webhooks.
* **Verifications:** Select “Email”
* **Webhook Events**: Verification.completed
* **Save**: Complete the setup by saving the webhook configuration.

![](/files/DAsbQvOqPY9KwRQUe5zQ)

**2. Configure Workflow in FlutterFlow**

1. **Create new API Call**:

* In your FlutterFlow app, go to the "API Calls" section.
* Create a new API call. This will serve as the endpoint for handling webhook requests.
* Give your API call a name, like “verifyuser”.

1. **Set Up the Webhook Endpoint**:
   * **Endpoint Name**: Choose a meaningful name (e.g., handle\_verification\_webhook).
   * **Endpoint URL**: Generate a URL for this API. Copy this URL and use it as the Webhook URL in Trust Swiftly. The webhook URL format looks like

**https\://\<your-website>/\<your-webhook-endpoint>**

**For example,**

<https://app.flutterflow.io/project/demo-4d8110/verifyuser>

where “demo” is the name of the app, “4d8110” is the id of your project and “verifyuser” is the name of API.

1. **Set the API Details**:
   * **API Method**: Choose POST.
   * **API URL**: Enter the API end pint URL.
2. **Add Headers**:
   * In the "Headers" section, click "Add header" and include the following:
     * **Content-Type**:
       * **Key**: Content-Type
       * **Value**: application/json

By following these steps, you’ll be able to set up and handle webhooks from Trust Swiftly, ensuring your FlutterFlow app stays in sync with the latest verification status updates.

#### Redirect Users to Success Page Upon Verification <a href="#id-31b6j9ytejw8" id="id-31b6j9ytejw8"></a>

Once the user completes the verification process, you need to ensure they are redirected to a success page to confirm their verification status.

**1. Handle Verification Completion in FlutterFlow**

1. **Set Up Redirection Logic**:
   * **Trigger Redirection**:

* Go to your “Verification Page” and add action “Backend Call API”.
* Select “verifyuser” **as Group or Call Name**.
* **Name Action Variable Name** as “APIResult”.
* In conditional Action, under the **“True”** field in the Conditional Action, click on **Add**.
* Add new Action “Navigate to” and select “Verification Successful Page”

**Example Success Page**

By setting up the redirection to a success page, you provide users with a clear confirmation of their verification status, enhancing the overall user experience.


# Webflow ID Verification

Integrating Webflow with Trust Swiftly involves following our guide to configure your verification steps. Setup a robust no-code solution to verify your users through ID, selfie, KYC.

### Overview <a href="#oqkjd09v5117" id="oqkjd09v5117"></a>

Trust Swiftly provides powerful identity verification tools designed to help fast-moving businesses ensure secure and seamless customer onboarding. This guide demonstrates how to integrate Trust Swiftly's verification services into a [Webflow ](https://webflow.com/)app. We make it simple to verify identities through multiple ways such as ID documents, SMS, liveness checks and more to secure your application. The example app allows users to register, complete ID verification, and view their verification status—all within the Webflow platform. By following this guide, you'll learn how to create a user for verification, implement the verification process, and handle the verification status using Trust Swiftly’s API and webhooks.

{% hint style="info" %}
The following guide is for testing purposes and not intended to be used for a production or advanced setup app. We recommend you configure the settings according to your business and select unique verifications. For more help contact us for tips on creating a verification process.
{% endhint %}

### Prerequisites <a href="#ib80hoa63njf" id="ib80hoa63njf"></a>

* [A Webflow account](https://webflow.com/signup) with a basic understanding of how to create and manage Webflow apps.
* API access to Trust Swiftly. Ensure you have your [API key ](/api/getting-an-api-key)ready.
* Familiarity with webhooks and Webflow's API workflows.

### Steps to Implement <a href="#vpk8v7qplj7v" id="vpk8v7qplj7v"></a>

#### Set Up API Key in Webflow <a href="#e977opyntum1" id="e977opyntum1"></a>

Before you start making API calls to Trust Swiftly, you need to configure your API key in Webflow.

* In your Webflow app, navigate to the "Logics" tab and click on the “New Flow” button to begin setting up a new flow.
* Click on “Select a trigger to start this flow” and choose “Form submissions” as the trigger.

![](/files/l0Dx40g7ymW8IaKMiIXl)

* Assign a name to your flow, such as "Create user”.
* Click on the “+” icon, placed just below the trigger.
* Select “Make HTTP request” option from the list of available actions.

#### Create a User for Verification

After selecting "Make HTTP request," you will be prompted to configure the details of the request. Here’s what you need to do:

1. **Name the API Call**:
   * Assign a name to your API, such as "Create User API".
2. **Set the API Details**:
   * **API Method**: Choose POST.
   * **API URL**: Enter the Trust Swiftly API endpoint URL where the user will be created.
3. **Add Headers**:
   * In the "Headers" section, click "+" icon and include the following:
     * **Authorization**:
       * **Name**: Authorization
       * **Value**: Bearer YOUR\_API\_KEY (replace YOUR\_API\_KEY with the actual API key provided by Trust Swiftly)
     * **Content-Type**:
       * **Name**: Content-Type
       * **Value**: application/json
4. **Set the Request Body**:
   * **Body**: Enter the JSON body structure. To add dynamic value just click on the **Insert variable icon.**
   * Select the flow trigger and then select the corresponding variables.

![](/files/IUgK2pdwzXP5pL07ZsNW) ![](/files/P1XEqFzf2WgSqZQfiUwU)

1. **Test the API Call**:
   * Click on the “Run test to complete the setup” button. This initiates a test of the configured HTTP request to ensure that it functions correctly with the dynamic values and setup.
   * Enter the relevant sample data and click on the “Run test” button to execute the test with the provided sample data.
   * Review the response to ensure that the API call was successful, and that the data was correctly processed.
   * Click on “Add data” to finalize the setup.

![](/files/kAXk2a3B8qU8pZYBaYnt)

**Handle API Response: Storing the Magic Link**

When the API request is successful, Trust Swiftly will return a response containing the magic link, which the user can use to verify their identity. This magic link should be stored in your Webflow database for further use.

* If you are storing the data in a CMS collection, add an action to “Create Collection Item”.
* Specify the CMS collection where you want to store the data, such as “Users”.
* Map the fields from the API response and form submission to the corresponding CMS fields. For example, store the magic link and user details.

**Note:** Webflow does not allow usrs to store link dynamically, store the magic link in dummy field whose field type is “Plain Text”.

* For magic link, drop-down “Response Body” and select “magic\_link”.

![](/files/h9zbRu8nzXnkeEMJGWiv)

1. **Store Magic link in CMS as Link:**
   * In order to store magic link as a link type you will need to use Make
   * Note that Webflow does not support storing links dynamically. Therefore, use a third-party application, such as Make (formerly Integromat), to handle the storing link process.
2. **Set Up an Updating Item Scenario in Make**:
   * **Get CMS Item**
     * **Create a New Scenario in Make and** click on the “+” icon to add a new module.
     * Search for “Webflow” and select the Webflow app from the list.
     * Select the trigger action “Get an item” trigger to get item from CMS.

![](/files/4w9dWZA6nUT5qaX0EDzf)

* Configure this module to fetch the relevant item from your CMS. You can map your item using “By selecting” option in **Enter item ID** field.

![](/files/CduqoZHB6SUbb36ajnWi)

**Update CMS Item**

* Add another module and select "Update an Item" from the dropdown.
* Configure the update settings, and use the data fetched from the "Get Item from CMS" module to set the magic link.
* Map the magic link to dummy link field in which the original link is stored as plain text.
* Press “ok” to save your module.

![](/files/lHPcyGAqCZ5IVQVqJxV4)

1. **Verify Update Item Scenerio**:
   * Click on “Run once” to Update the Item.
   * Now you will be able to redirect to verify page using this link.

![](/files/gZmw0PUQLNwCMY6IjKqj)

#### Handle Verification Button and Email Magic Link <a href="#t1ykg098nfki" id="t1ykg098nfki"></a>

After successfully creating the user, the next step is to enable the user to initiate the ID verification process. When the user clicks the "Verify" button, they should receive a magic link via email, which they will use to complete the verification.

1. **Create Verification Page:**
   * Navigate to “Pages” tab.
   * In the "CMS Collection Pages" section, choose the appropriate collection template that corresponds to where you are storing user details.
   * Add a Form block named “Verify”.
   * Click the submit button and go to button settings.
   * Get the magic\_link URL from your CMS collection.
   * This will redirect the user to the magic link when verify button is pressed

!\[A screenshot of a computer

Description automatically generated]\(/files/RPf6IEUIPzcfyTrt56pH)

#### Setting Up Email Notifications and Handling the Verification Process <a href="#rqiru757dz1s" id="rqiru757dz1s"></a>

Follow these steps to set up email notifications and handle the verification process:

**Set Up Email Notifications for Verification**

1. **Access Trust Swiftly Users Page:**
   * Log in to your Trust Swiftly account and navigate to the “Users” page.
2. **Find the User:**
   * Locate the user you want to verify by searching for their details (e.g., email or user ID).
3. **Click Verification Button:**
   * Select the user and click on the “Verification” button to access the verification settings.

![](/files/QgqMJFBAIdQ0YtUxynYD)

1. **Enable Email Notifications:**
   * In the verification settings, ensure that email notifications are enabled.
   * This setting allows Trust Swiftly to send the necessary verification emails to the user, including the magic link and any follow-up emails if additional verification is needed.

![](/files/HS4O4n8SQt6EJiOSpMP7)

**Receive and Access the Magic Link**

1. **Initial Email with Magic Link:**
   * The user receives an email with a magic link from Trust Swiftly.
   * Clicking this link directs the user to a verification page with a "Verify" button.

**Click the Magic Link and Verify Identity**

1. **Verification Page:**
   * On the verification page, the user clicks the "Verify" button to start the verification process.

<img src="/files/foCKyXqiWtbKc8K6M3Xj" alt="" width="347">

1. **Initial Verification Attempt:**
   * Trust Swiftly processes the verification request. If additional verification is required, the user will receive a follow-up email.

**Follow-Up Email**

1. **Receive Follow-Up Email:**
   * If further verification is necessary, Trust Swiftly sends a follow-up email.
   * Example Content:
     * “Due to an additional review we require another method of verification. Please complete the new request to verify yourself.”
     * Verify Identity Button: Includes a button or URL for completing the additional verification.

<img src="/files/olCvnZYd6UZb8NZ5Qwpg" alt="" width="355">

* * Click on Confirm Email button and it will redirect you to another page
  * Enter your email in the field and click the “Send verification Email” button

<img src="/files/xed5UVTTfgRRHdhPHbK4" alt="" width="346">

#### Set Up Webhook for Verification Status <a href="#tw1o0sw15r4f" id="tw1o0sw15r4f"></a>

To keep track of the verification status, you need to set up a webhook with Trust Swiftly and configure Webflow to handle the incoming webhook data. This will allow you to update the user’s verification status based on Trust Swiftly's notifications.

**1. Create a Webhook in Trust Swiftly**

1. **Log in** to your Trust Swiftly account and navigate to the Webhooks section in the dashboard under “Developers” tab.
2. **Create a New Webhook**:
   * Click on “Create Webhook” to start the setup process.

<img src="/files/H5AVeOwaaNiQHNy36HEW" alt="" width="563">

* * **Webhook URL**: Enter the URL where Trust Swiftly will send the webhook notifications. This should be the endpoint of your Webflow app that will handle incoming webhooks. (See section “Setup Webhook in Webflow” below)
  * **Verifications:** Select “Email”
  * **Webhook Events**: Verification.completed
  * **Save**: Complete the setup by saving the webhook configuration.

![](/files/jIBNFTCtz96wh9D64O7C)

**2. Configure Verify flow in Webflow**

1. **Set Up the Webhook Endpoint**:
   * In your Webflow app, go to the "Logic" section.
   * Create a new flow and set “Incoming webhook” as trigger. This will serve as the endpoint for handling webhook requests.
   * **Trigger Name**: Choose a meaningful name (e.g. Verify).
   * **Endpoint URL**: Webflow will generate a URL for this workflow. Copy this URL and use it as the Webhook URL in Trust Swiftly.

![](/files/jNeT9LatQpzLfEtMOJv7)

1. **Update CMS Item**:
   * Create a new field for “User” collection named “isVerified” and set default value to “no”.
   * **Update the User Record**:
     * Use the "Update CMS item" action to update the user’s record in your Webflow database based on the information received.
     * For example, if the webhook indicates that the verification status is complete, update the isVerified field to yes in the user’s profile.

By following these steps, you’ll be able to set up and handle webhooks from Trust Swiftly, ensuring your Webflow app stays in sync with the latest verification status updates.

![](/files/0PX4vmArvpfbxGoHYk0m)

#### Redirect Users to Success Page Upon Verification

Once the user completes the verification process, you need to ensure they are redirected to a success page to confirm their verification status.

**1. Handle Verification Completion in Webflow**

* Navigate to your CMS template page in which your verify form is loacted.
* Configure form settings and change the form’s conditional visibility to “verify equals no”

![](/files/xmnPFGTId3fmModFossz)

* Add a text box with “Verification Completed Successfully” text
* Configure text settings and change the text’s conditional visibility to “verify equals yes”

**Example Success Page**

![](/files/aKTsZDVY2Da0xTY1etWs)

By setting up the redirection to a success page, you provide users with a clear confirmation of their verification status, enhancing the overall user experience.


# Zapier Identity Verification

Integrating Trust Swiftly with Zapier allows you to automate identity verification processes seamlessly across various apps and services, enhancing security and efficiency without the need for coding.

### **Set up your identity verification workflow automation with Zapier**

Ensuring trust in digital products is increasingly crucial. One effective method is using an identity verification solution like Trust Swiftly. With Trust Swiftly, you can authenticate users' true identities and effortlessly integrate the service with various apps and platforms via Zapier. This guide will demonstrate how to create automated workflows for identity verification, featuring biometric authentication, KYC, AML and ID verification, that seamlessly connect with spreadsheets, databases, communication tools, and CRMs. This no-code/low-code solution is accessible to both developers and non-technical users alike.

### **Prerequisites:**

* You need a Trust Swiftly account. If you don’t have one, navigate and [create one here](https://app.trustswiftly.com/create)
* A Zapier Account

#### **Step 1: Sign Up or Log In to Zapier**

1. Go to [Zapier’s website](https://zapier.com/).
2. If you don’t have an account, click on [**Sign Up**](https://zapier.com/sign-up) and create one. If you already have an account, click on [**Log In**](https://zapier.com/app/login).

#### **Step 2: Access Trust Swiftly on Zapier**

1. Once logged in, navigate to the [Trust Swiftly Zapier Integrations page](https://zapier.com/apps/trust-swiftly/integrations).
2. Click on an example connection [**Connect a new account**](https://zapier.com/apps/trust-swiftly/integrations/google-sheets) and search for **Trust Swiftly**.

#### **Step 3: Set Up a New Zap**

1. Click on [**Make a Zap**](https://zapier.com/app/zaps) to start creating a new Zap.

![](/files/GzmF3HNFszwZEubsVj1g)

1. Choose **Trust Swiftly** as your **Action**

![](/files/Ac5ZxhASK9TbwefZqilh)

#### **Step 4: Configure the Trigger**

1. Select a **Trigger Event** from the available options (e.g., **Get Verification Status**).
2. Click **Continue** and follow the prompts to connect your Trust Swiftly account. You will need your API Key and your URL i.e. \[mycompany].trustswiftly.com
3. Test the trigger to ensure it’s working correctly.

#### **Step 5: Choose an Action App**

1. After setting up the trigger, choose an **Action App** (e.g., Google Sheets, Slack).
2. Select an **Action Event** (e.g., **Create Spreadsheet Row** in Google Sheets).

#### **Step 6: Configure the Action**

1. Connect your chosen Action App account.
2. Set up the action by mapping the data from Trust Swiftly to the fields in your Action App. You can use dynamic data to set the email of the user. The template ID is used to set which verifications the user sees for example ID and Selfie.

<img src="/files/zi7QPghQwr3Crrd3nxmx" alt="" width="563">

1. Test the action to ensure it works as expected.

#### **Step 7: Finalize and Turn On Your Zap**

1. Review your Zap setup.
2. Click **Turn on Zap** to activate it.&#x20;

<figure><img src="/files/wgH05c63iNL6LftnB0eY" alt=""><figcaption></figcaption></figure>

#### **Step 8: Receive Webhooks in Zapier**

Using a [Zapier catch hook](https://help.zapier.com/hc/en-us/articles/8496288690317-Trigger-Zaps-from-webhooks) trigger allows you to receive any status updates from Trust Swiftly and create advanced configurations with thousands of integrations. You can quickly create using a [pre-filled Zap](https://api.zapier.com/v1/embed/trust-swiftly/create?steps\[0]\[app]=WebHookAPI\&steps\[0]\[action]=hook_v2\&steps\[1]\[app]=App210840CLIAPI@latest\&steps\[1]\[action]=identity_verification\&steps\[1]\[params]\[email]=ACTION_EMAIL).

1. Edit your Zap and add a trigger. Search for **Webhooks by Zapier.** Then select a Catch Hook.

![](/files/prLUsMEI6QN4LaPUmJ6a)

1. Copy the Webhook URL i.e. [`https://hooks.zapier.com/hooks/catch/XXX/XXX/`](https://hooks.zapier.com/hooks/catch/XXX/XXX/)
2. Go to the Developer section in the Trust Swiftly Admin and [Setup and Handling Webhooks.](https://docs.trustswiftly.com/webhooks/handling-webhooks) Paste the webhook URL into it and select an event to receive notifications about.

<img src="/files/G6DYQID9Dry8QdDHiAx8" alt="" width="375">

1. Test the webhook after you completed a test verification. The results will show similar as below depending on the method you completed.

<img src="/files/LMiYjBXd6hM9A2KCCuZE" alt="" width="563">

1. You can use the webhook data for subsequent steps by clicking the **+** icon and add another action such as sending a notification in a chat app or adding it to a database. Multiple steps can be used together to create complex automations.&#x20;

<img src="/files/8161TmUxlOaUd3uM0eND" alt="" width="563">

#### **Example Use Cases**

**Scenario**: Automatically log verification statuses in a various apps or trigger verifications from other apps.

1. **Trigger**: Trust Swiftly - Get Verification Status.
2. **Action** : Google Sheets - Create Spreadsheet Row.
3. **Databases:** Airtable, Firebase, PostgresSQL
4. **Communication Tools:** Discord, Gmail, Sendgrid, Mailchimp
5. **CRMs:** Hubspot, Salesforce, Pipedrive

By following these steps, you can seamlessly integrate Trust Swiftly with various apps on Zapier to automate your workflows and save time. Check out more possibilities for integrations by viewing [Explore All Apps | Zapier](https://zapier.com/apps).


# Getting an API Key

To access the Trust Swiftly API, you'll need an API key.

When you're ready to use the API in production using live data you can generate an API key in the menu for **Developer** settings. You must click Create Token and provide a name to track it.

{% hint style="warning" %}
**Keep your keys secure**

Your API keys carry many privileges, so be sure to keep them secure! Do not share your secret API keys in publicly accessible areas such as GitHub, client-side code, and so forth.
{% endhint %}

#### API Keys & Authentication

All API requests to the Trust Swiftly platform are authenticated using a secret API key. Think of this key as a unique password that identifies your application and grants it access to your account data.

You must include this key in every API request. Access to the API is only available on our paid plans.

**How to Generate Your API Key**

You can generate and manage your API keys from your Trust Swiftly dashboard.

1. Log in to your [Trust Swiftly Dashboard](https://app.trustswiftly.com/).
2. Navigate to **Settings** in the main menu, then select the **API** tab.
3. Click the **Generate New Key** button.
4. A new secret key will be generated for you.

![Token Creation Process](/files/-MZTgG8wLHY0Ngt29EI8)

> **Important: Copy Your Key Immediately**> \
> For your security, your secret API key is **only displayed once** at the time it is created. You must copy it and store it in a secure password manager or other secret store immediately. If you lose the key, you will need to revoke it and generate a new one.

***

#### Keeping Your API Key Secure

Your API key grants full access to your Trust Swiftly account data. You must treat it with the same care as you would a password.

**Security Best Practices:**

* **Do Not Share It:** Never share your key publicly, in client-side code, or in public code repositories like GitHub.
* **Use Environment Variables:** The best practice is to store the key in an environment variable on your server and load it into your application from there. This prevents the key from being hard-coded into your application source code.

  **Example:**

  ```bash
  # Set the environment variable on your server
  export TRUST_SWIFTLY_API_KEY="your_secret_key_goes_here"
  ```
* **Revoke Compromised Keys:** If you suspect a key has been exposed or compromised, go to the API settings page immediately and revoke it. Then, generate a new key and update your application.

***

#### What's Next?

Now that you have your API key, you're ready to make your first API call.

* **Quickstart Guide**: Follow our guide to create your first user and see the full workflow in action.
* **Create a User**: Dive straight into the API reference for creating and managing users.


# Authentication

This sample call, which shows the Users API, includes a bearer token in the Authorization request header.

#### Specifying the user agent <a href="#useragent" id="useragent"></a>

Each request to the API **must** be accompanied by a **user agent** request header. Typically this should be the name of the app consuming the service. A missing user agent will result in an HTTP 403 response. The user agent should accurately describe the nature of the API consumer such that it can be clearly identified in the request. Not doing so may result in the request being blocked. A valid request would look include the header:

```
Authorization: Bearer {api_key}
```

#### Example Authenticated Request

{% tabs %}
{% tab title="Successful Request" %}

```bash
curl --location --request GET 'https://{sub-domain}.trustswiftly.com/api/users' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'User-Agent: TrustSwiftly/1.0' \ \
--header 'Authorization: Bearer {api_key}'
```

{% endtab %}

{% tab title="Authorization Error Response" %}

```
{
    "error_code": "000",
    "error_message": "Api Key Wrong or Unauthorized User"
}
```

{% endtab %}
{% endtabs %}

Replace `{sub-domain}` with the relevant name of your Trust Swiftly account. i.e. the endpoint might be [https://example.trustswiftly.com](https://example.trustswiftly.com/)

#### Validate All Keys&#x20;

To check your credentials are correct you can use the verify-credentials endpoint with your API key.

```
POST /api/verify-credentials
```


# Users

The API Key can be generated within your developer settings.

## Get Users

<mark style="color:blue;">`GET`</mark> `https://{sub-domain}.trustswiftly.com/api/users`

List all the users currently assigned a profile.

#### Headers

| Name          | Type   | Description                                                                                                                                                                         |
| ------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization | string | <p><a href="/pages/-MQsT8b1Tu6E3aidz9Uf"><strong>API Key</strong></a></p><p>is used for server-to-server communication to fetch sensitive data that you already have access to.</p> |

{% tabs %}
{% tab title="200 Succesful response" %}

```
{
    "data": [
        {
            "id": 5,
            "first_name": "AutoTest",
            "last_name": "User",
            "username": "codecept_user",
            "email": "codecept_user@trustswiftly.dev",
            "verifications": [
                {
                    "id": 1,
                    "name": "Email",
                    "status": {
                        "value": 0,
                        "friendly": "Pending"
                    }
                },
                {
                    "id": 2,
                    "name": "Phone / SMS",
                    "status": {
                        "value": 0,
                        "friendly": "Pending"
                    }
                },
                {
                    "id": 3,
                    "name": "Document / ID",
                    "status": {
                        "value": 0,
                        "friendly": "Pending"
                    }
                },
                {
                    "id": 4,
                    "name": "PayPal",
                    "status": {
                        "value": 0,
                        "friendly": "Pending"
                    }
                },
                {
                    "id": 5,
                    "name": "Video",
                    "status": {
                        "value": 0,
                        "friendly": "Pending"
                    }
                },
                {
                    "id": 6,
                    "name": "Voice",
                    "status": {
                        "value": 0,
                        "friendly": "Pending"
                    }
                },
                {
                    "id": 7,
                    "name": "Secure Card",
                    "status": {
                        "value": 0,
                        "friendly": "Pending"
                    }
                },
                {
                    "id": 8,
                    "name": "Geolocation",
                    "status": {
                        "value": 0,
                        "friendly": "Pending"
                    }
                },
                {
                    "id": 9,
                    "name": "Social Account",
                    "status": {
                        "value": 0,
                        "friendly": "Pending"
                    }
                },
                {
                    "id": 10,
                    "name": "Two-Step Authentication",
                    "status": {
                        "value": 0,
                        "friendly": "Pending"
                    }
                }
            ],
            "phone": null,
            "avatar": "https://cdn.trustswiftly.com/assets/img/profile.png",
            "address": null,
            "country_id": null,
            "role_id": 2,
            "status": "Active",
            "birthday": null,
            "last_login": "2020-09-07 19:56:35",
            "two_factor_country_code": 0,
            "two_factor_phone": "",
            "two_factor_options": null,
            "email_verified_at": null,
            "created_at": "2020-09-11 01:33:51",
            "updated_at": "2020-09-11 01:33:51"
        }
    ]
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="cURL" %}

```bash
curl --location --request GET 'https://{sub-domain}.trustswiftly.com/api/users' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {api_key}' \
--header 'User-Agent: TrustSwiftly/1.0'
```

{% endtab %}
{% endtabs %}

## Get User

<mark style="color:blue;">`GET`</mark> `https://{sub-domain}.trustswiftly.com/api/users/{id}`

Retrieve a specific users profile.

#### Headers

| Name          | Type   | Description                                                                                                                               |
| ------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization | string | <p><strong>API Key</strong></p><p>is used for server-to-server communication to fetch sensitive data that you already have access to.</p> |

{% tabs %}
{% tab title="200 " %}

```
{
    "data": {
        "id": 7,
        "first_name": "New",
        "last_name": "Name",
        "username": "Verify_User2101131027492493",
        "email": "testing@test.com",
        "verifications": [
            {
                "id": 1,
                "name": "Email",
                "status": {
                    "value": 0,
                    "friendly": "Pending"
                }
            },
            {
                "id": 2,
                "name": "Phone / SMS",
                "status": {
                    "value": 0,
                    "friendly": "Pending"
                }
            },
            {
                "id": 3,
                "name": "Document / ID",
                "status": {
                    "value": 0,
                    "friendly": "Pending"
                }
            },
            {
                "id": 4,
                "name": "PayPal",
                "status": {
                    "value": 0,
                    "friendly": "Pending"
                }
            },
            {
                "id": 5,
                "name": "Video",
                "status": {
                    "value": 0,
                    "friendly": "Pending"
                }
            },
            {
                "id": 6,
                "name": "Voice",
                "status": {
                    "value": 0,
                    "friendly": "Pending"
                }
            },
            {
                "id": 7,
                "name": "Secure Card",
                "status": {
                    "value": 0,
                    "friendly": "Pending"
                }
            },
            {
                "id": 8,
                "name": "Geolocation",
                "status": {
                    "value": 0,
                    "friendly": "Pending"
                }
            },
            {
                "id": 9,
                "name": "Social Account",
                "status": {
                    "value": 0,
                    "friendly": "Pending"
                }
            },
            {
                "id": 10,
                "name": "Two-Step Authentication",
                "status": {
                    "value": 0,
                    "friendly": "Pending"
                }
            },
            {
                "id": 11,
                "name": "Bank",
                "status": {
                    "value": 0,
                    "friendly": "Pending"
                }
            },
            {
                "id": 12,
                "name": "Live Video",
                "status": {
                    "value": 0,
                    "friendly": "Pending"
                }
            }
        ],
        "phone": null,
        "avatar": "https://images.trustswiftly.com/public/avatars/none.png",
        "address": null,
        "country_id": null,
        "role_id": 2,
        "status": "Active",
        "birthday": null,
        "last_login": "2021-01-14 03:33:33",
        "two_factor_country_code": 0,
        "two_factor_phone": "",
        "two_factor_options": null,
        "email_verified_at": null,
        "created_at": "2021-01-13 22:27:49",
        "updated_at": "2021-01-14 03:33:33"
    }
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="cURL" %}

```bash
curl --location --request GET 'https://{sub-domain}.trustswiftly.com/api/users/2' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {api_key}' \
--header 'User-Agent: TrustSwiftly/1.0'
```

{% endtab %}
{% endtabs %}

## Create User

<mark style="color:green;">`POST`</mark> `https://{sub-domain}.trustswiftly.com/api/users`

Create a given users profile.

#### Headers

<table><thead><tr><th>Name</th><th width="162">Type</th><th>Description</th></tr></thead><tbody><tr><td>Authorization</td><td>string</td><td><p><a href="/pages/-MQsT8b1Tu6E3aidz9Uf"><strong>API Key</strong></a></p><p>is used for server-to-server communication to fetch sensitive data that you already have access to.</p></td></tr></tbody></table>

#### Request Body

<table><thead><tr><th>Name</th><th width="153">Type</th><th>Description</th></tr></thead><tbody><tr><td>notice</td><td>string</td><td>Display a notice on the dashboard for users such as custom instructions.</td></tr><tr><td>email</td><td>string</td><td><mark style="color:red;"><strong>Required.</strong></mark> Customer's email address.</td></tr><tr><td>send_link</td><td>boolean</td><td>Send a verify link to the user via email.</td></tr><tr><td>template_id</td><td>string</td><td>ID of the verification template you wish to assign to this user.</td></tr><tr><td>reference_id</td><td>string</td><td>An ID you can pass that correlates to your own system's user ID.</td></tr><tr><td>phone</td><td>string</td><td>Phone including international code. Example +13129450121. It must be in <a href="https://www.twilio.com/docs/glossary/what-e164">E164 format.</a></td></tr><tr><td>last_name</td><td>string</td><td>Users last name.</td></tr><tr><td>first_name</td><td>string</td><td>Users first name.</td></tr><tr><td>username</td><td>string</td><td>A unique username for the given user.</td></tr><tr><td>send_sms</td><td>boolean</td><td>Send a verify link to the user via SMS.</td></tr><tr><td>custom_verify_data</td><td>json string</td><td>A json string listing any data validation requirements for a user during document verification. i.e. "custom_verify_data": {"last_name": "Smith"}</td></tr><tr><td>order_id</td><td>string</td><td>If the user is associated with a specific order or transaction.</td></tr><tr><td>completion_url</td><td>string</td><td>Optional custom URL unique per user to redirect to when verifications are completed. Otherwise in General Settings a URL can be set as default.</td></tr><tr><td>deaNumber</td><td>string</td><td>Optional DEA Number for validating a registration with the government data source.</td></tr></tbody></table>

{% tabs %}
{% tab title="200 " %}

```javascript
{
  "status": "success",
  "id": 69,
  "magic_link": "https:\/\/test.trustswiftly.com\\/security-verify?expires=1325603631&key=16RWTtJRKTwjFIQCGWDEZrWkW4Qq2DdvfUQhdadug3AVwWu5mbZht&signature=768898ec51b20a623ba813969215f23785b784f213d04c0046265b3c6"
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="cURL" %}

```bash
curl --location --request POST 'https://{sub-domain}.trustswiftly.com/api/users' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {api_key}' \
--header 'User-Agent: TrustSwiftly/1.0' \
--data-raw '{
  "email": "testing@test.com",
  "template_id": "tmpl_MQ"
}'
```

{% endtab %}
{% endtabs %}

## Update User&#x20;

<mark style="color:purple;">`PATCH`</mark> `https://{sub-domain}.trustswiftly.com/api/users/{id}`

Update a provided user.

#### Headers

| Name          | Type   | Description                                                                                                                                                                         |
| ------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization | string | <p><a href="/pages/-MQsT8b1Tu6E3aidz9Uf"><strong>API Key</strong></a></p><p>is used for server-to-server communication to fetch sensitive data that you already have access to.</p> |

#### Request Body

| Name                 | Type   | Description                                                                                     |
| -------------------- | ------ | ----------------------------------------------------------------------------------------------- |
| email                | string | Customers email address.                                                                        |
| username             | string | A unique username for the given user.                                                           |
| first\_name          | string | Users first name                                                                                |
| last\_name           | string | Users last name                                                                                 |
| status               | string | The user's status. Accepted values: Unconfirmed, Active, Verified, Banned, Review.              |
| phone                | string | Phone including international code.                                                             |
| reference\_id        | string | An ID you can pass that correlates to your own systems user ID.                                 |
| template\_id         | string | ID of the verification template you wish to assign to this user.                                |
| custom\_verify\_data | String | A json string listing any data validation requirements for a user during document verification. |
| order\_id            | string | If the user is associated with a specific order or transaction.                                 |

{% tabs %}
{% tab title="200 " %}

```
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="cURL" %}

```bash
curl --location --request PATCH 'https://{sub-domain}.trustswiftly.com/api/users/1' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {api_key}' \
--header 'User-Agent: TrustSwiftly/1.0' \
--data-raw '{
    "first_name": "New",
    "last_name": "Name",
    "template_id": "tmpl_MQ"
}'
```

{% endtab %}
{% endtabs %}

## Update Verification

<mark style="color:purple;">`PATCH`</mark> `https://{sub-domain}.trustswiftly.com/api/users/{id}/verifications`

Update a status of a verification

#### Headers

| Name          | Type   | Description                                                                                                                                                                         |
| ------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization | string | <p><a href="/pages/-MQsT8b1Tu6E3aidz9Uf"><strong>API Key</strong></a></p><p>is used for server-to-server communication to fetch sensitive data that you already have access to.</p> |

#### Request Body

| Name                  | Type   | Description                                    |
| --------------------- | ------ | ---------------------------------------------- |
| verification\_id      | string | The ID corresponding to the verification name. |
| status                | string | The status to update the verification          |
| current\_workflow\_id | string | Optional unless verification\_id = 3           |

{% tabs %}
{% tab title="200 " %}

```
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="cURL" %}

```bash
curl --location --request PATCH 'https://{sub-domain}.trustswiftly.com/api/users/1/verifications' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {api_key}' \
--header 'User-Agent: TrustSwiftly/1.0' \
--data-raw '{
  "verification_id": "7",
	"status": "2"
}
```

{% endtab %}
{% endtabs %}

### Fetch verification mappings

```http
GET /api/settings/verifications
```

The response includes stable `key` values and numeric `id` values for verification methods and statuses. API requests accept either form.

Common method keys:

| Key            | ID | Name          |
| -------------- | -: | ------------- |
| `document_id`  |  3 | Document / ID |
| `secure_card`  |  7 | Secure Card   |
| `geolocation`  |  8 | Geolocation   |
| `biometric_id` | 13 | Biometric ID  |
| `liveness`     | 20 | Liveness      |
| `knowledge`    | 21 | Knowledge     |

Common status keys:

| Key                  | ID |
| -------------------- | -: |
| `assigned`           |  0 |
| `processing`         |  1 |
| `complete`           |  2 |
| `rejected`           |  3 |
| `complete_in_review` |  4 |
| `reset`              |  5 |
| `removed`            |  6 |

### Update a verification status

```http
PATCH /api/users/{user_id}/verifications
```

```json
{
  "verification_id": "geolocation",
  "status": "complete"
}
```

The legacy numeric form still works:

```json
{
  "verification_id": 8,
  "status": 2
}
```

### Mark a document workflow complete

For Document / ID, include `current_workflow_id`. Fetch workflow IDs from:

```http
GET /api/settings/workflow
```

That endpoint returns:

* `id`: legacy public ID, accepted by the update API.
* `encoded_id`: stable encoded ID, accepted by the update API.
* `raw_id`: internal workflow ID.

```http
PATCH /api/users/{user_id}/verifications
```

```json
{
  "verification_id": "document_id",
  "status": "complete",
  "current_workflow_id": "flow_MQ",
  "remarks": "Approved after manual review"
}
```

The API marks the selected user workflow complete. The overall `document_id` verification is marked complete once all of the user's assigned document workflows are complete or complete in review.

### Remove an assigned verification method

```http
DELETE /api/users/{user_id}/verifications/{verification_key_or_id}
```

Example:

```http
DELETE /api/users/123/verifications/secure_card
```

This removes a method only while it is still `assigned`. Completed or rejected methods return `verification_not_removable` so historical verification evidence is not deleted accidentally. For Document / ID, assigned document workflows are also removed when the method is removed.

## Delete User

<mark style="color:red;">`DELETE`</mark> `https://{sub-domain}.trustswiftly.com/api/users/{id}`

Delete a provided user.

#### Headers

| Name          | Type   | Description                                                                                                                                                                        |
| ------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization | string | <p><a href="/pages/-MQsT8b1Tu6E3aidz9Uf"><strong>API Key</strong></a></p><p>is used for server-to-server communication to fetch sensitive data that you already have access to</p> |

{% tabs %}
{% tab title="200 " %}

```
{
    "success": true
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="cURL" %}

```bash
curl --location --request DELETE 'https://{sub-domain}.trustswiftly.com/api/users/1' \
--header 'Authorization: Bearer {api_key}' \
--header 'User-Agent: TrustSwiftly/1.0' \
--data-raw ''
```

{% endtab %}
{% endtabs %}

## Get Verify Link

<mark style="color:green;">`POST`</mark> `https://{sub-domain}.trustswiftly.com/api/users/{id}/verify-url`

Generate a verify link used for user authentication

#### Headers

| Name          | Type   | Description                                                                                                                                                                                                      |
| ------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization | string | <p><a href="/pages/-MQsT8b1Tu6E3aidz9Uf#authorization-error-response"><strong>API Key</strong></a></p><p>is used for server-to-server communication to fetch sensitive data that you already have access to.</p> |

#### Request Body

| Name              | Type    | Description                                                        |
| ----------------- | ------- | ------------------------------------------------------------------ |
| expiration\_hours | integer | Hour(s) in which the magic link will remain alive before expiring. |

{% tabs %}
{% tab title="200 " %}

```
{
    "short_url": "https://tinyurl.com/y32d35rf",
    "full_url": "https://{sub-domain}.trustswiftly.com/security-verify?expires=1610753625&key=7&signature=3949637e17906a42bd3d0254af80a825f2696b9ba948cdf3654f0e354a2f6cef"
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="cURL" %}

```bash
curl --location --request POST 'https://{sub-domain}.trustswiftly.com/api/users/1/verify-url' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {api_key}' \
--header 'User-Agent: TrustSwiftly/1.0' \
--data-raw '{
  "expiration_hours": 24
}'
```

{% endtab %}
{% endtabs %}


# Reverify User

Use the reverify API to automatically verify the facial attributes of a user on subsequent verifications.

## Re-verify User Identity

This endpoint is designed for "step-up" authentication or low-friction re-verification. It allows you to dynamically switch a user from their initial, comprehensive verification process to a simpler one for subsequent checks.

The primary use case is to switch a user from an initial, high-assurance **Verification Template** (e.g., `ID Document + Selfie Scan`) to a subsequent, low-friction template (e.g., `Selfie Scan Only`).

This is ideal for scenarios where you need to re-confirm a user's identity without making them repeat the entire onboarding process.

**Common Use Cases**

* **Periodic Identity Check:** A user registered a month ago with their ID and a selfie. To access a high-value area of your service, you require them to quickly re-verify their identity with just a new selfie.
* **Password Reset:** Before allowing a password reset, you can require the user to pass a quick selfie check to ensure the legitimate owner is making the request.

> **Note:** This API is specifically for switching between verification templates, most commonly for facial re-verification. For other authentication methods like Passkeys or OTP, you should use the standard Update User endpoint to assign a different template.

***

### Reverify Endpoint

This endpoint assigns a new, temporary verification template to a user. All requests should be made to your account's specific sub-domain.

<mark style="color:green;">`POST`</mark> `https://{sub-domain}.trustswiftly.com/api/user/document/reverify`

**Request Body**

<table><thead><tr><th width="225.66668701171875">Parameter</th><th width="103.33331298828125">Type</th><th width="81.6666259765625">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>user_id</code></td><td>string</td><td>Yes</td><td>The <strong>Trust Swiftly User ID</strong> (e.g., <code>647</code>). <strong>Note:</strong> This is the internal <code>id</code> returned by the Trust Swiftly API when you created the user, not your own <code>reference_id</code>.</td></tr><tr><td><code>current_workflow_id</code></td><td>string</td><td>Yes</td><td>The ID of the <strong>Verification Template</strong> (workflow) that the user originally verified with. See below for how to find this ID.</td></tr><tr><td><code>re_verify_workflow_id</code></td><td>string</td><td>Yes</td><td>The ID of the new, simpler <strong>Verification Template</strong> you want to assign for this specific re-verification check.</td></tr></tbody></table>

**How to Find Workflow IDs**

Your "Verification Templates" are referred to as workflows in this API call. You can find the necessary `workflow_id` values in your Trust Swiftly dashboard.

1. Navigate to **Settings > Documents > User Verify WorkFlow**.
2. You will see a list of all your configured wrokflows. The ID (e.g., `flow_MzA`) for each is displayed next to its name.

<figure><img src="/files/Ke58BAUh25VAbUMbgpIF" alt=""><figcaption><p>Copy Workflow ID</p></figcaption></figure>

***

#### Example Request

In this example, we are switching user `647` from an "ID Document & Selfie" template (`flow_MzA`) to a new "Selfie Only" template (`flow_Mjk`).

```bash
curl --request POST \
  --url https://{sub-domain}.trustswiftly.com/api/user/document/reverify \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "user_id": "647",
    "current_workflow_id": "flow_MzA",
    "re_verify_workflow_id": "flow_Mjk"
  }'
```

***

#### Responses

**Success (200 OK)**

A successful request will return a `200 OK` status code. The user has now been assigned the new template. The next time they access their `magic_link`, they will be prompted with the re-verification flow.

```json
{
  "success": true
}
```

**Error Responses**

Your application should be prepared to handle the following errors.

* **User Already Assigned to Target Workflow**

  * This error occurs if the user is already assigned to the template specified in `re_verify_workflow_id`. This can happen if you make the same API call twice. The first call succeeds, and the second fails with this error.

  ```json
  {
    "Error_type": "already_assigned",
    "error_message": "Already assigned"
  }
  ```
* **User Not Found (`404 Not Found`)**

  * Returned if the `user_id` does not exist.

  ```json
  { "message": "User not found." }
  ```
* **Invalid Data (`422 Unprocessable Entity`)**

  * Returned if the `current_workflow_id` does not match the user's current template.

  ```json
  {
    "message": "The given data was invalid.",
    "errors": {
      "current_workflow_id": ["The selected current workflow id is invalid or does not match the user's workflow."]
    }
  }
  ```


# Documents

Create verification jobs through the API to analyze identities without going through Trust Swiftly's UI. Use the document status API to retrieve the results.

#### Direct Document Verification API

This API is for advanced use cases where you need to programmatically submit an identity document (e.g., a driver's license or passport) for analysis. This allows you to build your own document collection UI while still using Trust Swiftly's powerful verification engine on the backend.

{% hint style="danger" %}
**Warning: Advanced Use Only**\
By using this API, you are responsible for building your own secure document collection method. You may miss out on important security features and data collection checks provided by Trust Swiftly's hosted UI. We recommend our standard, hosted solution for the most secure and seamless experience.
{% endhint %}

***

#### How It Works: An Asynchronous Flow

Document verification is not instantaneous. The process is asynchronous and follows these steps:

1. **Prerequisite:** Ensure a user exists in Trust Swiftly and is assigned to a **Verification Template** that is configured for a single document check.
2. **Step 1: Create a Verification Job.** You upload the document image via a `multipart/form-data` request. The API accepts the job and immediately returns a unique `doc_id`.
3. **Step 2: Poll for Status.** You use the `doc_id` to periodically call the status endpoint. This endpoint will initially show a "processing" status.
4. **Step 3: Receive Results.** After a few seconds, the status endpoint will return a "Success" or "Failure" status, along with the complete analysis data. Alternatively, you can listen for a webhook to be notified of completion.

***

#### Prerequisite: Assign a Template to a User

Before you can submit a document for a user, that user must already exist in Trust Swiftly and be assigned to the correct **Verification Template**. This template tells our system what rules to apply to the document check.

You can do this by calling the Create User or Update User endpoint and providing the appropriate `template_id`.

***

#### Step 1: Create Document Verification Job

This endpoint accepts a document image and queues it for analysis.

<mark style="color:green;">`POST`</mark>`https://{sub-domain}.trustswiftly.com/api/verify/document`

**Request (multipart/form-data)**

<table><thead><tr><th width="147.33331298828125">Parameter</th><th width="97">Type</th><th width="94.333251953125">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>user_id</code></td><td>string</td><td>Yes</td><td>The user ID from Trust Swiftly (e.g., <code>645</code>).</td></tr><tr><td><code>template_id</code></td><td>string</td><td>Yes</td><td>The ID of the template assigned to the user (e.g., <code>tmpl_MTA</code>).</td></tr><tr><td><code>verify_image</code></td><td>file</td><td>Yes</td><td>The document image file (JPG, PNG, PDF). Must be less than 10MB.</td></tr></tbody></table>

**Example `cURL` Request**

**Note:** The `@` symbol before the file path tells `cURL` to upload the contents of the file.

```bash
curl --request POST \
  --url https://{sub-domain}.trustswiftly.com/api/verify/document \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: multipart/form-data' \
  --form 'user_id=645' \
  --form 'template_id=tmpl_MTA' \
  --form 'verify_image=@/path/to/your/drivers_license.jpg'
```

**Success Response**

A successful request returns a `200 OK` status and the `doc_id` for your new verification job. You must store this ID to check the status in the next step.

```json
{
    "success": true,
    "doc_id": "313237"
}
```

***

#### Step 2: Get Status of Document Verification Job

After waiting a few seconds, begin polling this endpoint with the `doc_id` from Step 1 to check the job status and retrieve the results once complete.

<mark style="color:green;">`POST`</mark>` ``https://{sub-domain}.trustswiftly.com/api/verify/document/status`

**Request (application/json)**

<table><thead><tr><th width="128.3333740234375">Parameter</th><th width="90.6666259765625">Type</th><th width="92">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>user_id</code></td><td>string</td><td>Yes</td><td>The user ID from the original request.</td></tr><tr><td><code>doc_id</code></td><td>string</td><td>Yes</td><td>The document ID received from the job creation endpoint.</td></tr></tbody></table>

**Example `cURL` Request**

```bash
curl --request POST \
  --url https://{sub-domain}.trustswiftly.com/api/verify/document/status \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "doc_id": "313237",
    "user_id": "645"
  }'
```

**Success Response**

When processing is complete, the `document_status` field will change from a processing state to `Success` or a failure state. The full extraction and analysis data is contained within the `document_data` object.

```json
{
  "success": true,
  "doc_id": "31323933",
  "document_status": "Success",
  "document_data": { ... }
}
```

***

#### Failure Response

```json
{
   "error_type": "invalid_document_id",
   "error_message": "Invalid Document Id"
}

Fail 2
{ "success": false, "doc_id": "31323930",
 "document_status": "Failed", "reason": null }
```

#### Understanding the `document_data` Object

The `document_data` object contains a rich set of information. Here are the key sections:

<details>

<summary><strong>Full Response Success (Click to expand)</strong></summary>

```json
{
  "success": true,
  "doc_id": "31323933",
  "document_status": "Success",
  "document_data": {
    "id": 1293,
    "name": "11/example@gmail.com_#11.jpg",
    "status": 1,
    "content": {
      "url": "https://sub-domain.trustswiftly.com/image/11?expires=11&signature=11",
      "hash": "a1efcda2122a20dda6d9ea89be9c62ac",
      "name": "11/example@gmail.com_#11.jpg",
      "size": 218545,
      "time": 1726768308,
      "type": "image/jpeg",
      "doc_type": "General process",
      "mrz_data": [],
      "exif_data": [],
      "extension": "jpg",
      "ai_analysis": {
        "name_match": {
          "full_name": false,
          "last_name": false
        },
        "selfie_check": true,
        "internet_detection": false,
        "internet_detection_location": {
          "guess_labels": [
            "document"
          ]
        }
      },
      "doc_type_id": 23,
      "dlp_analysis": {
        "info_types": [
          {
            "name": "US_STATE",
            "quote": "***",
            "likelihood": "VERY_LIKELY"
          },
          {
            "name": "US_DRIVERS_LICENSE_NUMBER",
            "quote": "***",
            "likelihood": "LIKELY"
          },
          {
            "name": "CREDIT_CARD_NUMBER",
            "quote": "***",
            "likelihood": "POSSIBLE"
          },
          {
            "name": "DATE",
            "quote": "08-29-1911",
            "likelihood": "LIKELY"
          },
          {
            "name": "DATE_OF_BIRTH",
            "quote": "08-29-1911",
            "likelihood": "LIKELY"
          },
          {
            "name": "PERSON_NAME",
            "quote": "Joe CHAMI",
            "likelihood": "LIKELY"
          },
          {
            "name": "FIRST_NAME",
            "quote": "Joe",
            "likelihood": "LIKELY"
          },
          {
            "name": "LAST_NAME",
            "quote": "CHAMI",
            "likelihood": "LIKELY"
          },
          {
            "name": "PERSON_NAME",
            "quote": "PAYNE",
            "likelihood": "LIKELY"
          },
          {
            "name": "LAST_NAME",
            "quote": "PAYNE",
            "likelihood": "LIKELY"
          },
          {
            "name": "STREET_ADDRESS",
            "quote": "111 PAYNE AVE EXAMPLE,MI 12345-1111",
            "likelihood": "LIKELY"
          },
          {
            "name": "DATE",
            "quote": "09-01-2017",
            "likelihood": "LIKELY"
          },
          {
            "name": "DATE",
            "quote": "08-29-2021",
            "likelihood": "LIKELY"
          },
          {
            "name": "DATE",
            "quote": "01-21-2011",
            "likelihood": "LIKELY"
          },
          {
            "name": "GENDER",
            "quote": "***",
            "likelihood": "POSSIBLE"
          }
        ]
      },
      "photoshopped": false,
      "original_name": "photo5827714315489229223_rotated.jpg",
      "valid_address": [],
      "dl_id_lookup_id": "",
      "face_annotation": {
        "joyLikelihood": "VERY_UNLIKELY",
        "angerLikelihood": "VERY_UNLIKELY",
        "sorrowLikelihood": "VERY_UNLIKELY",
        "blurredLikelihood": "VERY_UNLIKELY",
        "headwearLikelihood": "VERY_UNLIKELY",
        "surpriseLikelihood": "VERY_UNLIKELY",
        "underExposedLikelihood": "VERY_UNLIKELY"
      },
      "dl_id_lookup_data": "",
      "temporary_storage": "oss",
      "document_processor": {
        "Sex": {
          "value": "M",
          "confidence": 100
        },
        "age": {
          "value": 50,
          "confidence": 100
        },
        "Height": {
          "value": "170 cm",
          "confidence": 100
        },
        "Status": {
          "value": "Ok",
          "confidence": 100
        },
        "Address": {
          "value": "123 PAYNE AVE,EXAMPLE, MI 12345-1111",
          "confidence": 100
        },
        "DL Class": {
          "value": "O",
          "confidence": 100
        },
        "Position": {
          "value": {
            "x1": -3,
            "x2": 696,
            "y1": 11,
            "y2": 1034
          },
          "confidence": 100
        },
        "Full Name": {
          "value": "Joe CHAMI",
          "confidence": 100
        },
        "Eyes Color": {
          "value": "Brown",
          "confidence": 100
        },
        "DL Endorsed": {
          "value": "NONE",
          "confidence": 100
        },
        "countryName": {
          "value": "United States",
          "confidence": 100
        },
        "Address City": {
          "value": "EXAMPLE",
          "confidence": 100
        },
        "documentName": {
          "value": "Driver Licence",
          "confidence": 100
        },
        "Address State": {
          "value": "Michigan",
          "confidence": 100
        },
        "Date of Birth": {
          "value": "1911-08-29",
          "confidence": 100
        },
        "Date of Issue": {
          "value": "2012-09-01",
          "confidence": 100
        },
        "Document Name": {
          "value": "United States-Driver Licence",
          "confidence": 100
        },
        "Revision Date": {
          "value": "2011-01-11",
          "confidence": 100
        },
        "Address Street": {
          "value": "123 PAYNE AVE",
          "confidence": 100
        },
        "Date of Expiry": {
          "value": "2050-08-29",
          "confidence": 100
        },
        "Document Number": {
          "value": "111",
          "confidence": 100
        },
        "Portrait Position": {
          "value": {
            "x1": 26,
            "x2": 283,
            "y1": 167,
            "y2": 509
          },
          "confidence": 100
        },
        "Issuing State Code": {
          "value": "USA",
          "confidence": 100
        },
        "Issuing State Name": {
          "value": "United States",
          "confidence": 100
        },
        "Address Postal Code": {
          "value": "12345-1111",
          "confidence": 100
        },
        "DL Restriction Code": {
          "value": "NONE",
          "confidence": 100
        },
        "Document Discriminator": {
          "value": "11",
          "confidence": 100
        },
        "Address Jurisdiction Code": {
          "value": "MI",
          "confidence": 100
        }
      },
      "valid_user_address": []
    },
    "created_at": "2024-09-19T17:51:46.000000Z"
  }
}
```

</details>

<details>

<summary><strong>`document_processor` (Click to expand)</strong></summary>

This object contains the core data extracted from the document via Optical Character Recognition (OCR), such as name, date of birth, address, and document numbers, along with a confidence score for each field.

</details>

<details>

<summary><strong>`ai_analysis` (Click to expand)</strong></summary>

This provides signals about the authenticity of the document image itself, including checks for whether it's a picture of a screen (\`internet\_detection\`) or if it matches a known selfie (\`selfie\_check\`).

</details>

<details>

<summary><strong>`dlp_analysis` (Click to expand)</strong></summary>

This provides Data Loss Prevention (DLP) analysis, identifying all types of Personally Identifiable Information (PII) found in the document, such as names, addresses, and dates.

</details>

<details>

<summary><strong>`face_annotation` (Click to expand)</strong></summary>

If a face is present on the document, this provides analysis of the facial attributes, such as the likelihood of headwear or if the image is blurred.

</details>


# Stats

Get current stats for verifications.

## Get Account Statistics

This endpoint provides a high-level snapshot of your account's verification activity, including user registration volume, a breakdown of user statuses, and a list of the most recent user records.

This is useful for building dashboards or for periodic reporting on your verification funnel.

<mark style="color:blue;">`GET`</mark>` ``https://{sub-domain}.trustswiftly.com/api/stats`

***

#### Authentication

Authentication is handled via the `Authorization` header. There are no path or query parameters for this endpoint.

<table><thead><tr><th width="174">Header</th><th width="128.3333740234375">Type</th><th width="83">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>Authorization</code></td><td>string</td><td>Yes</td><td>Your secret API key, prefixed with <code>Bearer</code> .</td></tr><tr><td><code>Accept</code></td><td>string</td><td>Yes</td><td>Must be <code>application/json</code>.</td></tr></tbody></table>

***

#### Understanding the Response Body

The response object is composed of three main sections:

**`users_per_month`**

This object provides a monthly breakdown of total user registrations for the current calendar year.

```json
"users_per_month": {
    "January": 0,
    "February": 0,
    "March": 1,
    // ...etc
}
```

**`users_per_status`**

This object gives you a real-time count of users categorized by their current status within the Trust Swiftly system.

<table><thead><tr><th width="138.6666259765625">Status</th><th>Description</th></tr></thead><tbody><tr><td><code>total</code></td><td>The total number of user records associated with your account.</td></tr><tr><td><code>new</code></td><td>Users who have been created but have not yet started a verification flow.</td></tr><tr><td><code>banned</code></td><td>Users who have been explicitly banned.</td></tr><tr><td><code>unconfirmed</code></td><td>Users who are in a pending or processing state.</td></tr></tbody></table>

```json
"users_per_status": {
    "total": 3,
    "new": 2,
    "banned": 0,
    "unconfirmed": 1
}
```

**`latest_registrations`**

This is an array containing the full user objects for the most recently created users on your account. While the full object is returned, the most relevant fields for statistical purposes are typically:

<table><thead><tr><th width="190">Field</th><th>Description</th></tr></thead><tbody><tr><td><code>id</code></td><td>The user's unique ID within the Trust Swiftly system.</td></tr><tr><td><code>first_name</code></td><td>The user's first name.</td></tr><tr><td><code>last_name</code></td><td>The user's last name.</td></tr><tr><td><code>email</code></td><td>The user's email address.</td></tr><tr><td><code>status</code></td><td>The current status of the user (e.g., "Active", "Unconfirmed").</td></tr><tr><td><code>created_at</code></td><td>The timestamp when the user was created.</td></tr></tbody></table>

***

#### Example Request & Full Response

**Request**

```bash
curl --request GET \
  --url https://{sub-domain}.trustswiftly.com/api/stats \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Accept: application/json'
```

**Full Response**

<details>

<summary><strong>Click to expand the full example response</strong></summary>

```json
{
  "users_per_month": {
    "January": 0,
    "February": 0,
    "March": 1,
    "April": 0,
    "May": 0,
    "June": 0,
    "July": 0,
    "August": 2,
    "September": 0,
    "October": 0,
    "November": 0,
    "December": 0
  },
  "users_per_status": {
    "total": 3,
    "new": 2,
    "banned": 0,
    "unconfirmed": 1
  },
  "latest_registrations": [
    {
      "id": 123,
      "first_name": "John",
      "last_name": "Doe",
      "username": "johndoe",
      "email": "john.doe@gmail.com",
      "phone": "+381641234567",
      "avatar": "http://yourwebsite.com/users/milos-avatar.jpg",
      "address": "Some random street, 123, Serbia",
      "country_id": 688,
      "role_id": 1,
      "status": "Active",
      "birthday": "1989-01-03",
      "last_login": "2017-04-27 16:47:59",
      "two_factor_country_code": 381,
      "two_factor_phone": "6412345678",
      "two_factor_options": {
        "option1": 4,
        "option2": "option value"
      },
      "created_at": "2017-04-20 16:47:59",
      "updated_at": "2017-04-27 10:47:59"
    },
    {
      "id": 124,
      "first_name": "Jane",
      "last_name": "Smith",
      "username": "janesmith",
      "email": "jane.smith@gmail.com",
      "phone": "+1234567890",
      "avatar": null,
      "address": "123 Main St, Anytown, USA",
      "country_id": 840,
      "role_id": 1,
      "status": "Unconfirmed",
      "birthday": "1992-05-15",
      "last_login": null,
      "two_factor_country_code": null,
      "two_factor_phone": null,
      "two_factor_options": {},
      "created_at": "2024-09-20 11:30:00",
      "updated_at": "2024-09-20 11:30:00"
    }
  ]
}
```

</details>


# Templates

Get available verification templates

## List Verification Templates

Verification Templates define the specific sequence of checks a user must complete (e.g., "Email only", or "ID Document + Selfie Scan").

You can use this endpoint to programmatically fetch a list of all available templates configured in your account. This is essential for dynamically assigning the correct verification flow to a user when you create or update them via the API.

<mark style="color:blue;">`GET`</mark>` ``https://{sub-domain}.trustswiftly.com/api/settings/templates/verifications`

***

#### Authentication

Authentication is handled via the `Authorization` header. There are no path or query parameters for this endpoint.

<table><thead><tr><th width="162">Header</th><th width="115.66668701171875">Type</th><th width="124">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>Authorization</code></td><td>string</td><td>Yes</td><td>Your secret API key, prefixed with <code>Bearer</code> .</td></tr><tr><td><code>Accept</code></td><td>string</td><td>Yes</td><td>Must be <code>application/json</code>.</td></tr></tbody></table>

***

#### Understanding the Response Body

The endpoint returns an array of your configured Verification Template objects. Each object contains the template's ID and the types of checks it includes.

<table><thead><tr><th width="159">Field</th><th width="109.3333740234375">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>id</code></td><td>number</td><td>The internal numeric identifier for the template.</td></tr><tr><td><code>name</code></td><td>string</td><td>The <strong>Template ID</strong> (e.g., <code>tmpl_MQ</code>). <strong>This is the value you must use in the <code>template_id</code> field when creating or updating users.</strong></td></tr><tr><td><code>types</code></td><td>array</td><td>A list of the verification methods included in this template (e.g., "Email", "Document / ID").</td></tr></tbody></table>

***

#### Example Request & Response

**Request**

```bash
curl --request GET \
  --url 'https://{sub-domain}.trustswiftly.com/api/settings/templates/verifications' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Accept: application/json'
```

**Response**

The response will be an array of all templates available in your account.

```json
[
  {
    "id": 1,
    "name": "tmpl_MQ",
    "types": [
      "Email"
    ]
  },
  {
    "id": 2,
    "name": "tmpl_Mg",
    "types": [
      "Phone / SMS",
      "Document / ID"
    ]
  },
  {
    "id": 3,
    "name": "tmpl_Mw",
    "types": [
      "Phone / SMS",
      "Document / ID",
      "Selfie"
    ]
  }
]
```

***

#### What's Next: Using a Template ID

After you've fetched your templates, you can use the value from the `name` field to assign a verification flow to a user.

For example, if you want to assign the second template from the response above (`tmpl_Mg`) to a new user, your API call to create the user would look like this:

```bash
# Example of using a template_id when creating a user

curl --request POST \
  --url https://app.trustswiftly.com/api/users \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
    "reference_id": "user_12345",
    "email": "test@example.com",
    "template_id": "tmpl_Mg"  // <-- The ID from the templates endpoint
  }'
```

For more details, see the Create User API documentation.


# Errors

This page describes various error responses with our API.

#### Error Handling

Trust Swiftly uses conventional HTTP response codes to indicate the success or failure of an API request. In general: Codes in the `2xx` range indicate success. Codes in the `4xx` range indicate a client-side error. Codes in the `5xx` range indicate an error with Trust Swiftly's servers.

When an error occurs, the API will return a JSON object containing a specific `error_type` and a message to help you diagnose the issue.

***

#### HTTP Status Codes Summary

<table><thead><tr><th>Status Code</th><th width="158.333251953125">Meaning</th><th>Description</th></tr></thead><tbody><tr><td><code>200 OK</code></td><td>OK</td><td>Everything worked as expected.</td></tr><tr><td><code>201 Created</code></td><td>Created</td><td>The resource was created successfully.</td></tr><tr><td><code>400 Bad Request</code></td><td>Bad Request</td><td>The request was unacceptable, often due to malformed syntax or missing data.</td></tr><tr><td><code>401 Unauthorized</code></td><td>Unauthorized</td><td>No valid API key was provided or the key is invalid.</td></tr><tr><td><code>404 Not Found</code></td><td>Not Found</td><td>The requested resource (like a user) does not exist.</td></tr><tr><td><code>422 Unprocessable Entity</code></td><td>Unprocessable Entity</td><td>The request was well-formed, but the server was unable to process it due to validation errors.</td></tr><tr><td><code>500</code> / <code>5xx</code></td><td>Server Error</td><td>Something went wrong on Trust Swiftly's end.</td></tr></tbody></table>

***

#### Error Types & Examples

Here is a guide to the specific `error_type` codes returned by the API.

**`api_auth_error`**

* **HTTP Status:** `401 Unauthorized`
* **When:** This occurs if your API key is missing, incorrect, or disabled.
* **Response:**

  ```json
  {
    "error_type": "api_auth_error",
    "error_message": "Unauthenticated."
  }
  ```

***

**`api_user_error` or `api_resource_error`**

* **HTTP Status:** `404 Not Found`
* **When:** The resource you are trying to access does not exist. This commonly occurs when using an incorrect `user_id` or other resource identifier.
* **Response:**

  ```json
  {
    "error_type": "api_user_error",
    "error_message": "User Not Found"
  }
  ```

***

**`api_validation_error`**

* **HTTP Status:** `422 Unprocessable Entity`
* **When:** This is the most common error when creating or updating resources. It means the data provided failed server-side validation. The `errors` object gives a field-by-field breakdown of what went wrong.
* **Response:**

  ```json
  {
    "error_type": "api_validation_error",
    "error_message": "The given data was invalid.",
    "errors": {
      "email": [
        "The email has already been taken."
      ],
      "reference_id": [
        "The reference id field is required."
      ]
    }
  }
  ```

***

**`api_template_error`**

* **HTTP Status:** `422 Unprocessable Entity`
* **When:** The `template_id` you provided is invalid, does not exist, or is not accessible to your account.
* **Response:**

  ```json
  {
    "error_type": "api_template_error",
    "error_message": "Invalid templateId provided."
  }
  ```

***

**`api_invalid_error`**

* **HTTP Status:** `400 Bad Request`
* **When:** The request is malformed or missing data in a way that prevents processing. This is a more general error than a validation failure.
* **Response:**

  ```json
  {
    "error_type": "api_invalid_error",
    "error_message": "Invalid or No Data Provided for Update"
  }
  ```

***

**`api_internal_error`**

* **HTTP Status:** `500 Internal Server Error`
* **When:** An unexpected error occurred on Trust Swiftly's servers. These are rare. If you consistently receive a 500 error, please contact support.
* **Response:**

  ```json
  {
    "error_type": "api_internal_error",
    "error_message": "Internal Server Error"
  }
  ```


# Pagination

All top-level API endpoints have support for bulk fetches via "list" API methods.

#### Handling Paginated Responses

Endpoints that can return a large number of items (like listing users or documents) are **paginated**. This means that instead of returning all results in a single, massive response, the data is returned in "pages."

You must be prepared to handle this paginated structure to retrieve all the results you need. All paginated endpoints in the Trust Swiftly API share the same consistent structure.

***

#### Understanding the Paginated Response

A paginated response contains three top-level objects: `data`, `links`, and `meta`.

| Key     | Description                                                                   |
| ------- | ----------------------------------------------------------------------------- |
| `data`  | An array containing the list of resource objects for the current page.        |
| `links` | An object containing ready-to-use URLs for navigating through the pages.      |
| `meta`  | An object containing metadata about the paginated list, such as total counts. |

**The `links` Object**

This object provides full URLs for easy navigation.

<table><thead><tr><th width="265.33331298828125">Link</th><th>Description</th></tr></thead><tbody><tr><td><code>first</code></td><td>The URL for the first page of results.</td></tr><tr><td><code>last</code></td><td>The URL for the last page of results.</td></tr><tr><td><code>prev</code></td><td>The URL for the previous page. Will be <code>null</code> if you are on the first page.</td></tr><tr><td><code>next</code></td><td>The URL for the next page. Will be <code>null</code> if you are on the last page.</td></tr></tbody></table>

> **Best Practice:** For the most robust integration, your application should use the full URLs provided in the `links` object for navigation rather than constructing your own. This protects your application from potential future changes to the URL structure.

**The `meta` Object**

This object provides detailed information about the current state of the pagination.

<table><thead><tr><th width="228">Field</th><th>Description</th></tr></thead><tbody><tr><td><code>current_page</code></td><td>The page number you are currently viewing.</td></tr><tr><td><code>from</code></td><td>The item number of the first result on the current page.</td></tr><tr><td><code>last_page</code></td><td>The total number of pages available.</td></tr><tr><td><code>path</code></td><td>The base URL for the resource.</td></tr><tr><td><code>per_page</code></td><td>The number of items requested per page.</td></tr><tr><td><code>to</code></td><td>The item number of the last result on the current page.</td></tr><tr><td><code>total</code></td><td>The total number of items in the entire collection.</td></tr></tbody></table>

***

#### Controlling Pagination

You can control pagination using query parameters in your request URL.

**Changing the Page Size (`per_page`)**

To specify how many records you want per page, append the `per_page` parameter.

* **Default:** 15 items per page.
* **Maximum:** 100 items per page. If you request more than 100, the API will return 100.

**Example: Requesting 50 users per page.**`GET /api/users?per_page=50`

**Requesting a Specific Page (`page`)**

To navigate to a specific page, use the `page` parameter.

**Example: Requesting the second page of 50 users.**`GET /api/users?per_page=50&page=2`

***

#### Complete Example

**Request**

Here is a `curl` example requesting the first page of users, with a page size of 2.

```bash
curl --request GET \
  --url 'https://{sub-domain}.trustswiftly.com/api/users?per_page=2&page=1' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Accept: application/json'
```

**Response**

```json
{
    "data": [
        {
            "id": 1,
            "first_name": "John",
            "last_name": "Doe",
            // ... more user fields
        },
        {
            "id": 2,
            "first_name": "Jane",
            "last_name": "Smith",
            // ... more user fields
        }
    ],
    "links": {
        "first": "https://{sub-domain}.trustswiftly.com/api/users?page=1",
        "last": "https://{sub-domain}.trustswiftly.com/api/users?page=5",
        "prev": null,
        "next": "https://{sub-domain}.trustswiftly.com/api/users?page=2"
    },
    "meta": {
        "current_page": 1,
        "from": 1,
        "last_page": 5,
        "path": "https://{sub-domain}.trustswiftly.com/api/users",
        "per_page": 2,
        "to": 2,
        "total": 10
    }
}
```


# Filtering and Sorting Users

Filtering and sorting results can help speed up responses and data collection by allowing you to request only the data you need.

You can refine the results from list endpoints by using `filter` and `sort` query parameters. This allows you to request only the data you need and in the order you want it.

These parameters can be combined with each other and with our Pagination parameters for powerful, precise queries.

***

**Filtering Results**

To filter a list, use the `filter` query parameter with a specific field name in square brackets.

**Syntax:** `?filter[parameter_name]=value`

There are two types of filters available, depending on the parameter. Each endpoint's documentation will specify which filters are available and what type they are.

| Filter Type       | Description                                                             | Example Use Case                                        |
| ----------------- | ----------------------------------------------------------------------- | ------------------------------------------------------- |
| **Exact Match**   | Returns records where the attribute exactly matches the provided value. | Filtering for a specific status, like `active` users.   |
| **Partial Match** | Performs a "wildcard" or "contains" search on a text-based field.       | Searching for a user by a piece of their name or email. |

**Example: Filtering by a partial search term**

This request will return all users where the searchable fields (like name or email) contain the string "John".

```bash
curl --request GET \
  --url 'https://{sub-domain}.trustswiftly.com/api/users?filter[search]=John' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Accept: application/json'
```

***

**Sorting Results**

To sort a list, use the `sort` query parameter followed by the field name you wish to sort by.

| Sort Order     | Syntax              | Description                                                            |
| -------------- | ------------------- | ---------------------------------------------------------------------- |
| **Ascending**  | `?sort=field_name`  | Sorts from A-Z, or oldest to newest.                                   |
| **Descending** | `?sort=-field_name` | **Prefix with a minus sign (-)**. Sorts from Z-A, or newest to oldest. |

**Example: Sorting by creation date**

This request will return all users sorted by their creation date, with the newest users appearing first.

```bash
curl --request GET \
  --url 'https://{sub-domain}.trustswiftly.com/api/users?sort=-created_at' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Accept: application/json'
```

***

**Combining Operations**

You can combine filtering, sorting, and pagination into a single request by separating the parameters with an ampersand (`&`).

**Example 1: Filtering and Sorting**

This request demonstrates a powerful combination:

1. **Filters** for users with an `active` status.
2. **Sorts** the results to show the newest active users first.
3. **Paginates** the results to show only the first 10.

```bash
curl --request GET \
  --url 'https://{sub-domain}.trustswiftly.com/api/users?filter[status]=active&sort=-created_at&per_page=10' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Accept: application/json'
```

**Example 2: Combining Multiple Filters**

This request combines two different filters to find users who have "john" in their name/username **AND** whose email is exactly `support@example.com`.

```bash
curl --request GET \
  --url 'https://{sub-domain}.trustswiftly.com/api/users?filter[search]=john&filter[email]=support@example.com' \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Accept: application/json'
```

***

**Available Fields for `/api/users`**

The following tables outline the specific filtering and sorting capabilities for the `/users` endpoint.

**Filtering:**

| Parameter        | Filter Type   | Description                                                                                        |
| ---------------- | ------------- | -------------------------------------------------------------------------------------------------- |
| `filter[search]` | Partial Match | Performs a "contains" search across the `username`, `first_name`, `last_name`, and `email` fields. |
| `filter[email]`  | Exact Match   | Finds a user with the exact email address specified.                                               |
| `filter[status]` | Exact Match   | Finds all users with a specific status (e.g., `active`, `banned`, `unconfirmed`).                  |

**Sorting:**

| Parameter | Available Fields                                                               |
| --------- | ------------------------------------------------------------------------------ |
| `sort`    | `id` (default), `first_name`, `last_name`, `email`, `created_at`, `updated_at` |


# Rate Limits

Learn about API rate limits and how to work with them.

To ensure the stability and fair use of our platform for all users, the Trust Swiftly API imposes rate limits on incoming requests. If you send too many requests in a short period, the API will respond with an error code.

This guide explains our limits, how to monitor your usage, and how to handle rate-limiting errors gracefully.

***

#### Default Limits

Our default rate limits are designed to be sufficient for most applications.

* **300 requests per minute**
* **5 requests per second**

If your application has high-volume needs, please see the section on "Increasing Your Limits" below.

***

#### Monitoring Your Usage with HTTP Headers

Every API response includes HTTP headers that provide real-time visibility into your current rate limit status. By programmatically inspecting these headers, your application can avoid exceeding the limit.

<table><thead><tr><th width="239.99993896484375">Header</th><th>Description</th></tr></thead><tbody><tr><td><code>X-RateLimit-Limit</code></td><td>The total number of requests allowed in the current time window.</td></tr><tr><td><code>X-RateLimit-Remaining</code></td><td>The number of requests you have left in the current time window.</td></tr><tr><td><code>X-RateLimit-Reset</code></td><td>The Coordinated Universal Time (UTC) timestamp when the current time window resets.</td></tr></tbody></table>

**Example Response Headers:**

```http
HTTP/1.1 200 OK
Content-Type: application/json
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 299
X-RateLimit-Reset: 1672531260
```

***

#### Handling Exceeded Limits

If you exceed the rate limit, the API will stop processing your requests and respond with an HTTP `429 Too Many Requests` error code.

```json
{
  "error_type": "api_rate_limit_error",
  "error_message": "Too Many Requests"
}
```

**Recommended Strategy: Exponential Backoff**

The best way to handle `429` errors is to implement a retry mechanism with **exponential backoff and jitter**. This pattern improves the reliability of your application by automatically retrying the failed request after waiting for a progressively longer amount of time.

**How it works:**

1. When you receive a `429` error, don't retry immediately.
2. Wait for a short, increasing duration (e.g., 1s, then 2s, then 4s, etc.).
3. Add a small, random delay ("jitter") to the wait time to prevent all instances of your application from retrying at the exact same moment.
4. After waiting, try the request again.
5. Stop retrying after a certain number of attempts to avoid an infinite loop.

**Pseudo-code Example:**

```
// A simple exponential backoff implementation
retries = 0
max_retries = 5

loop:
  try:
    response = make_api_request()
    break // Success, exit the loop

  catch (error):
    if error.status_code == 429 and retries < max_retries:
      retries += 1
      // Calculate wait time: 1s, 2s, 4s, etc. + random jitter
      wait_time = (2 ** retries) * 1000 + random_integer(0, 1000)
      wait(wait_time) // Wait in milliseconds
      continue loop // Retry the request
    else:
      // If it's not a 429 error or we've run out of retries,
      // re-throw the error to be handled by other logic.
      throw error
```

***

#### Increasing Your Limits

For applications with high-volume requirements or for specific batch processing tasks, we offer increased rate limits. This is a standard feature for our Enterprise plans.

If you anticipate needing a higher limit, please contact our support team to discuss your use case.


# Setup and Handling Webhooks

Our webhooks allow you to receive real-time notifications about verification events, enabling you to automate your workflows. This guide provides the necessary information to securely and reliably set up, handle, and troubleshoot these webhooks.

### Step 1: Configure Your Endpoint in Trust Swiftly

1. Navigate to the Webhooks section in your settings page: `https://{your-subdomain}.trustswiftly.com/admin/settings/webhooks`
2. Click the **Add Webhook** button.
3. Enter your publicly accessible endpoint URL and select the events you want to subscribe to. If you need a temporary URL for testing, services like [webhook.site](https://webhook.site/) are excellent for inspecting payloads.

### Step 2: Secure Your Endpoint with Signature Verification

For each event, Trust Swiftly sends a `Signature` header in the HTTP POST request. You **must** verify this signature to confirm that the request originated from us and was not altered during transmission.

The signature is an HMAC-SHA256 hash, generated using your unique **Webhook Signing Secret** and the **raw, unmodified request body**.

Your server-side code must perform the same calculation and compare the result with the signature we sent. Use a secure, constant-time comparison function to prevent timing attacks.

```php
// Pseudocode for verification
$secret = 'your_webhook_signing_secret';
$receivedSignature = $_SERVER['HTTP_SIGNATURE'];
$rawPayload = file_get_contents('php://input');

$computedSignature = hash_hmac('sha256', $rawPayload, $secret);

// Use a secure comparison function
if (!hash_equals($computedSignature, $receivedSignature)) {
  // The request is invalid - reject it
  http_response_code(403);
  exit('Invalid signature.');
}

// The signature is valid - proceed to process the payload
```

For full, production-ready code, see our detailed **Webhook Code Examples**.

### Step 3: Understand the Webhook Payload

After verifying the signature, you can safely parse the JSON payload. Our webhooks follow a standardized structure.

#### Key Identifiers

* `relationships.user_uuid`: The internal Trust Swiftly UUID for the user.
* `relationships.user_id`: The internal Trust Swiftly ID for the user.
* `data.reference_id`: **(Most Important)** This is *your* internal identifier for the user. When you initiate a verification, you can pass your system's `user_id` in this field. We return it in the webhook so you can easily map the event back to the correct user in your database.

#### Event Types

Your handler should be built to recognize the `type` field in the payload. Common event types include:

| Event Type                | Description                                                                         |
| ------------------------- | ----------------------------------------------------------------------------------- |
| `verification.pending`    | Fired when a verification process has been initiated but is not yet complete.       |
| `verification.in-process` | Fired when a multi-step verification is partially complete.                         |
| `verification.completed`  | Fired when a verification has been successfully approved.                           |
| `verification.rejected`   | Fired when a verification has been reviewed and rejected.                           |
| `user.status.changed`     | Fired when a user status has been changed from Active, Verified, Review, or Banned. |

### Step 4: Best Practices for Reliable Handling

A production-grade webhook handler must be fast and resilient.

#### Acknowledge First, Process Later (Asynchronous Processing)

To acknowledge receipt of an event, your endpoint must return a `2xx` HTTP status code quickly. If we don't receive a `2xx` response in a timely manner, we will assume the delivery failed and will retry.

To avoid timeouts, your endpoint should do the absolute minimum amount of work before responding. The best practice is to hand off complex business logic to a background job or queue.

1. Receive the request.
2. Verify the signature.
3. Add the payload to a queue (like RabbitMQ, SQS, or a database queue).
4. Immediately return a `200 OK` response.
5. A separate background worker can then pull jobs from the queue and process them without risk of a timeout.

#### Handle Retries with Idempotency

Because network issues can occur, your system may receive the same webhook event more than once. Your endpoint must be **idempotent**, meaning it can safely process the same event multiple times without causing duplicate data or errors.

The easiest way to achieve this is to track the unique `id` of every webhook payload.

```
// Pseudocode for an idempotent check
function handleWebhook(event) {
  if (hasEventBeenProcessed(event.id)) {
    // Already handled, so just acknowledge success
    return 200; 
  }

  // Add to queue for processing
  addEventToQueue(event);
  logEventAsProcessed(event.id);

  return 200;
}
```

### Step 5: Development and Troubleshooting

#### Testing Locally

Webhooks require a public URL, which can be a challenge during local development. We recommend using a tool like [**ngrok**](https://ngrok.com/) to create a secure tunnel to your local server.

1. Run your application locally (e.g., on `localhost:3000`).
2. Run ngrok: `ngrok http 3000`.
3. Ngrok will provide a public URL (e.g., `https://random-string.ngrok.io`).
4. Use this URL as your webhook endpoint in the Trust Swiftly dashboard. Requests will be forwarded to your local application.

#### Delivery Logs, Retention, and Test Identities

Every delivery attempt is recorded under **Settings → Webhooks → View Logs**, including the request headers, response status, and attempt count.

To protect end-user privacy, webhook logs follow a tiered retention policy:

* **Payload bodies** are viewable for **30 days** after delivery. Within this window you can inspect the full payload and retry failed deliveries. Payloads are shown masked by default; revealing the full payload is recorded in the audit log.
* **Delivery metadata** (event type, endpoint, status code, attempts, timestamps) remains available for **90 days** for troubleshooting delivery health.
* When a user is deleted, all webhook log entries about that user are removed **immediately**.

**Testing tip:** when building your integration, create a dedicated test user whose username starts with `TRUSTSWIFTLY_WEBHOOK_TESTING` (e.g. `TRUSTSWIFTLY_WEBHOOK_TESTING_493`) or whose email contains that marker. Deliveries about test identities are badged **Test** in the log view and keep their full payloads for the entire 90-day window, so you can compare payloads across integration changes. Test identities must only ever contain synthetic data — never real documents, photos, or contact details. For a quick connectivity check without any user at all, use the **Send Test Payload** button, which fires a synthetic sample event.

#### Troubleshooting Signature Mismatches

A signature mismatch is the most common issue. If you encounter this, check the following:

1. **Are you using the raw request body?** This is critical. Do not parse and re-stringify the JSON before verification, as this will alter the content and cause the signature to fail.
2. **Is your Webhook Signing Secret correct?** Double-check that you are using the correct secret from the dashboard and that it has no leading/trailing whitespace.
3. **Are you checking the correct header?** The header name is `Signature`. Be aware that some frameworks may transform this to `HTTP_SIGNATURE` or `Http-Signature`.

### Manage and Test Your Webhooks

Once configured, you can test, view logs, edit, or delete a webhook using the action buttons in the dashboard. Sending a test webhook is an excellent way to debug your endpoint and ensure your signature verification logic is working correctly.

<figure><img src="/files/KZNj0sUk3cR33cR68GU6" alt=""><figcaption></figcaption></figure>


# Webhook Code Examples

To ensure the integrity and authenticity of the webhooks sent from Trust Swiftly, we sign every request sent to your endpoint. By verifying this signature, you can confirm that the webhook was sent by Trust Swiftly and that its payload has not been tampered with during transmission.

The signature is an **HMAC-SHA256 hash**, generated using your unique webhook signing secret and the raw request body. This signature is passed in the **`Signature` HTTP header** with each request.

Below are code examples demonstrating how to properly verify the webhook signature in several common languages and frameworks. It is crucial to use a secure, constant-time comparison method to prevent timing attacks.

* PHP (Procedural)
* PHP (Laravel)
* JavaScript (Express.js)
* Python (Flask)

***

### Example Payload (`verification.completed`)

The new webhook format encapsulates the main payload within `data` and `relationships` objects. All custom business logic should now access data through these keys.

```json
{
  "id": "4e057b68-0d5f-40ad-b84a-a4d878b738fd",
  "type": "verification.completed",
  "subject": "verification",
  "spec_version": "2025-10-08",
  "occurred_at": "2025-10-08T23:55:09+00:00",
  "resource_id": 1,
  "relationships": {
    "user_id": 172,
    "user_uuid": "0199c63f-a1d4-7400-bc22-8cdfaad82084"
  },
  "data": {
    "verification_id": 1,
    "verification_name": "Email verification",
    "email": "testwebhook@trustswiftly.com",
    "user_status": "Active",
    "order_id": null,
    "ip": "172.19.0.7",
    "ip_country": "US",
    "reference_id": "5122",
    "last_activity": "2025-10-08T23:54:50+00:00",
    "verifications": [
      {
        "id": 1,
        "name": "Email",
        "status": {
          "value": 2,
          "friendly": "Complete"
        },
        "attributes": {
          "email": "testwebhook@trustswiftly.com",
          "paypal_email": "testwebhook@trustswiftly.com",
          "paypal_email_verified": 0
        },
        "start_time": "2025-10-08 23:54:43",
        "completion_time": "2025-10-08 23:55(0 h 0 m 26 s)",
        "completed_at": "2025-10-08 23:55"
      },
      {
        "id": 3,
        "name": "Document / ID",
        "status": {
          "value": 0,
          "friendly": "Assigned"
        },
        "attributes": {
          "verify_documents": [],
          "workflow": "ID + Selfie"
        }
      }
    ]
  }
}
```

***

### PHP (Procedural) Example

```php
<?php

/**
 * Procedural PHP example for verifying Trust Swiftly Webhooks.
 */

// --- 1. Configuration ---
// It is a critical security practice to store your secret outside of your codebase.
// $webhookSecret = getenv('TRUST_SWIFTLY_SECRET');
$webhookSecret = 'XXXX'; // Replace with your actual webhook signing secret.

// --- 2. Get Request Data ---
$payload = file_get_contents('php://input');
if ($payload === false || empty($payload)) {
    http_response_code(400);
    exit('Error: Could not read request body.');
}

if (!isset($_SERVER['HTTP_SIGNATURE'])) {
    http_response_code(400);
    exit('Error: Signature header is missing.');
}
$receivedSignature = $_SERVER['HTTP_SIGNATURE'];


// --- 3. Verify the Signature ---
$computedSignature = hash_hmac('sha256', $payload, $webhookSecret);

// Use hash_equals() for a secure, constant-time comparison to prevent timing attacks.
if (!hash_equals($computedSignature, $receivedSignature)) {
    http_response_code(403);
    exit('Tampered Request: Invalid signature.');
}


// --- 4. Process the Payload ---
$webhookData = json_decode($payload, true);

if (json_last_error() !== JSON_ERROR_NONE) {
    http_response_code(400);
    exit('Error: Invalid JSON payload.');
}

// **UPDATED FOR NEW FORMAT**: Access data from the 'data' and 'relationships' objects.
$data = $webhookData['data'] ?? [];
$relationships = $webhookData['relationships'] ?? [];
$eventType = $webhookData['type'] ?? 'unknown';

$referenceId = $data['reference_id'] ?? null; // Your internal user ID
$verifications = $data['verifications'] ?? [];
$trustSwiftlyUserId = $relationships['user_id'] ?? null;

// TODO: Add your business logic here.
// Find the user in your system using $referenceId.
// error_log("Processing event '{$eventType}' for reference ID: {$referenceId}");

foreach ($verifications as $verification) {
    $name = $verification['name'] ?? 'Unknown';
    $status = $verification['status']['friendly'] ?? 'unknown';

    // Example: Log the result for the specific user
    // error_log("Verification for user {$referenceId}: {$name} - Status: {$status}");
}

// --- 5. Send a Success Response ---
// Acknowledge receipt to prevent retries from Trust Swiftly.
http_response_code(200);
echo 'Webhook received successfully.';

?>
```

***

### PHP (Laravel) Example

```php
<?php

namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

class TrustSwiftlyWebhookController extends Controller
{
    /**
     * Handle a Trust Swiftly webhook request.
     */
    public function handle(Request $request)
    {
        // 1. Get the signature from the headers.
        $receivedSignature = $request->header('Signature');
        if (!$receivedSignature) {
            Log::warning('Trust Swiftly Webhook: Signature header not found.');
            return response('Signature header is required.', 400);
        }

        // 2. Get the secret key from your configuration (e.g., config/services.php).
        $secret = config('services.trustswiftly.signature_secret');
        if (!$secret) {
            Log::error('Trust Swiftly Webhook: Signature secret is not configured.');
            return response('Server configuration error.', 500);
        }

        // 3. Compute the expected signature from the raw request body.
        $payload = $request->getContent();
        $computedSignature = hash_hmac('sha256', $payload, $secret);

        // 4. Securely compare signatures to prevent timing attacks.
        if (!hash_equals($computedSignature, $receivedSignature)) {
            Log::warning('Trust Swiftly Webhook: Signature mismatch.');
            return response('Tampered Request: Invalid signature.', 403);
        }

        // 5. Process the payload now that the signature is verified.
        Log::info('Trust Swiftly Webhook: Signature verified successfully!');
        $webhookData = json_decode($payload, true);
        
        // **UPDATED FOR NEW FORMAT**: Access data from the 'data' and 'relationships' objects.
        $data = $webhookData['data'] ?? [];
        
        $referenceId = $data['reference_id'] ?? null;
        if (!$referenceId) {
            Log::info('Trust Swiftly Webhook: reference_id not found in payload.');
            return response('Webhook processed, no reference_id.', 200);
        }
        
        $user = User::find($referenceId);
        if (!$user) {
            Log::info("Trust Swiftly Webhook: User not found for reference_id: {$referenceId}.");
            return response('User not found.', 200); // Respond 200 to acknowledge.
        }

        // Example logic: Save the verification data to a user meta field.
        $verifications = $data['verifications'] ?? [];
        $user->trustswiftly_verifications = $verifications;
        $user->save();

        Log::info("Trust Swiftly Webhook: Updated verifications for User ID {$user->id}.");
        
        return response('Webhook received.', 200);
    }
}
```

***

### JavaScript (Express.js) Example

```javascript
// Import required modules
const express = require('express');
const crypto = require('crypto');

// --- Configuration ---
// It is a critical security practice to store your secret outside of your codebase.
// Use environment variables: export TRUST_SWIFTLY_SECRET=your_secret_key
const webhookSecret = process.env.TRUST_SWIFTLY_SECRET;
if (!webhookSecret) {
    console.error("FATAL ERROR: TRUST_SWIFTLY_SECRET environment variable not set.");
    process.exit(1);
}

const app = express();
const PORT = process.env.PORT || 3000;

// --- Express App Setup ---
// Capture the raw request body as a Buffer, which is required for signature verification.
app.use(express.json({
    verify: (req, res, buf) => {
        req.rawBody = buf;
    },
}));

// --- Webhook Verification Middleware ---
// Verifies the signature *before* your route handler runs.
const verifyTrustSwiftlyWebhook = (req, res, next) => {
    const receivedSignature = req.get('Signature');
    if (!receivedSignature) {
        console.warn('Webhook failed: Signature header missing.');
        return res.status(400).send('Signature header is required.');
    }

    const hmac = crypto.createHmac('sha256', webhookSecret);
    // Use the raw body buffer saved by the express.json middleware
    hmac.update(req.rawBody); 
    const computedSignature = hmac.digest('hex');

    // Use crypto.timingSafeEqual for a secure, constant-time comparison.
    try {
        const receivedSigBuffer = Buffer.from(receivedSignature, 'utf8');
        const computedSigBuffer = Buffer.from(computedSignature, 'utf8');
        if (!crypto.timingSafeEqual(receivedSigBuffer, computedSigBuffer)) {
             console.warn('Webhook failed: Invalid signature.');
             return res.status(403).send('Tampered Request: Invalid signature.');
        }
    } catch (error) {
        console.warn('Webhook failed: Error during signature comparison.');
        return res.status(403).send('Tampered Request: Invalid signature.');
    }

    // Signature is valid, proceed to the route handler.
    next();
};


// --- Webhook Route ---
app.post('/webhooks/trustswiftly', verifyTrustSwiftlyWebhook, (req, res) => {
    console.log('Webhook signature verified successfully!');

    // **UPDATED FOR NEW FORMAT**: Access data from the 'data' and 'relationships' objects.
    const { type, data, relationships } = req.body;
    console.log(`Received event: ${type}`);

    // Your business logic goes here.
    if (data && relationships) {
        const { reference_id, verifications } = data;
        const { user_id } = relationships;
        
        console.log(`Processing data for your user ID (reference_id): ${reference_id}`);
        // Example: updateUserVerificationStatus(reference_id, verifications);
    }
    
    // Acknowledge receipt with a 200 OK response.
    res.status(200).json({ status: 'success', message: 'Webhook received' });
});

app.listen(PORT, () => console.log(`Server listening on port ${PORT}`));
```

***

### Python (Flask) Example

```python
import hmac
import hashlib
import os
import json
from flask import Flask, request, abort

app =Flask(__name__)

# --- Configuration ---
# Load the webhook secret from an environment variable for security.
# NEVER hardcode secrets.
# export TRUST_SWIFTLY_WEBHOOK_SECRET='your_secret'
TRUST_SWIFTLY_WEBHOOK_SECRET = os.environ.get('TRUST_SWIFTLY_WEBHOOK_SECRET')
if not TRUST_SWIFTLY_WEBHOOK_SECRET:
    raise ValueError("TRUST_SWIFTLY_WEBHOOK_SECRET environment variable not set.")


@app.route('/webhooks/trustswiftly', methods=['POST'])
def trust_swiftly_webhook():
    """Receives and securely verifies a webhook from Trust Swiftly."""
    
    # --- 1. Signature Verification ---
    received_signature = request.headers.get('Signature')
    if not received_signature:
        print("Webhook failed: 'Signature' header not found.")
        abort(400, "Signature header is required.")

    # Get the raw request body as bytes (`request.data`).
    payload_bytes = request.data

    # Compute the expected signature using the shared secret.
    # Note: The secret must be encoded to bytes before use in hmac.new.
    computed_hash = hmac.new(
        TRUST_SWIFTLY_WEBHOOK_SECRET.encode('utf-8'),
        payload_bytes,
        hashlib.sha256
    )
    computed_signature = computed_hash.hexdigest()

    # Use hmac.compare_digest for secure, constant-time comparison to prevent timing attacks.
    if not hmac.compare_digest(computed_signature, received_signature):
        print("Webhook failed: Signature mismatch.")
        abort(403, "Tampered Request: Signature mismatch.")

    print("Signature verified successfully!")

    # --- 2. Process the Webhook Payload ---
    try:
        webhook_data = json.loads(payload_bytes)
    except json.JSONDecodeError:
        print("Webhook failed: Invalid JSON payload.")
        abort(400, "Invalid JSON.")
    
    # **UPDATED FOR NEW FORMAT**: Access data from nested objects.
    event_type = webhook_data.get('type', 'unknown')
    data = webhook_data.get('data', {})
    relationships = webhook_data.get('relationships', {})

    reference_id = data.get('reference_id')
    user_uuid = relationships.get('user_uuid')

    # TODO: Add your business logic here.
    print(f"Received event '{event_type}' for user UUID: {user_uuid} (Reference ID: {reference_id})")

    # --- 3. Acknowledge Receipt ---
    # Respond with 200 OK to prevent webhook retries.
    return "Webhook received and verified.", 200


if __name__ == '__main__':
    # For development only. Use a production WSGI server (like Gunicorn) in production.
    app.run(port=5000, debug=True)
```


# Share hosted link

Learn how to manually generate and share a unique verification link for a single user directly from the Trust Swiftly dashboard. This simple, no-code method is ideal for one-off verifications or proof

## Sharing a Manual Verification Link

This guide covers the simplest, no-code method for verifying a single user by sharing a unique link directly from your Trust Swiftly dashboard.

This method is ideal for:

* Quickly verifying a specific individual.
* Getting started without writing any code.
* Proof-of-concept testing.

When you need to automate this process for many users, we recommend using the Trust Swiftly API to create users and retrieve their links programmatically.

***

#### How it Works

The process involves two main stages: first creating a user in the dashboard, and then generating and sharing their unique verification link.

**Step 1: Create the User**

Before you can get a verification link, a user must exist in the Trust Swiftly system.

1. From your Trust Swiftly dashboard, navigate to the **Users** page.
2. Click the **Add User** button.
3. Fill in the user's details and click **Save**.

**Step 2: Generate and Share the Verification Link**

Once the user has been created, they will appear in the user list.

1. Find the user in the list on the **Users** page.
2. Click the **Share Verify URL** button.

<figure><img src="/files/BUuR6SyVDCI3Ax0mlnGk" alt=""><figcaption></figcaption></figure>

**Step 3: Choose Your Sharing Method**

A dialog box will appear with several options for sharing the link.

<figure><img src="/files/M8oK7y3MumjpdaTUi5mN" alt=""><figcaption></figcaption></figure>

* **Copy Link:** Click the copy icon to copy the full verification URL to your clipboard. You can then paste this link into an email, SMS, live chat, or use it to generate a QR code.
* **Send Email:** Enter the user's email address and click **Send Email** to have Trust Swiftly send a notification directly to the user with their link.
* **Send SMS:** If the phone is provided during user creation a SMS can be sent to their phone with a link to start the verification.&#x20;
* **Modify Expiration:** By default, the link has a set expiration time for security. You can adjust this duration here if needed.

> **Important: This Link is a One-Time Secret**> \
> The verification link is sensitive and provides direct access to a user's verification session.
>
> * **Share it only with the intended user.**
> * **Do not post it in a public place.**
> * Once a user starts or completes the verification, the link cannot be reused.

***

#### The User's Experience

When your user clicks the link, they will be taken to your branded, hosted verification page where they can complete the required steps (e.g., uploading an ID, taking a selfie).

Once they are finished, their status will be updated in your Trust Swiftly dashboard, and a webhook will be sent to your endpoint if you have one configured.


# Configure self verifications

Self-verifications are a quick way to get started with Trust Swiftly. This feature allows your users to create their own accounts and complete verifications without requiring any code or integration on your part. You can always add other integration options later to further automate the process.

To configure the self-verification process, navigate to your registration settings page at `https://{sub-domain}.trustswiftly.com/settings/auth`.

**General Settings (Registration Tab)**

These settings control the core sign-up experience for your users.

* **Allow customer sign up?:** This is the primary switch to enable the self-verification page (`/signup`). This page should be shared directly with your customers.
* **Registration Password:** When disabled, it allows for a passwordless registration process. If enabled, users will be required to create a password when signing up.
* **Terms and Conditions:** Enable this to require users to agree to your terms and conditions before creating an account.
* **Email Confirmation:** When enabled, users must verify their email address before they can log in to their account.

After configuring these options, click **Update Settings** to save them.

**Verification Templates (Registration Tab)**

You can direct users to complete a specific set of verifications after they sign up.

* **Default Verification Template:** This sets a global default template for any user who signs up through the general `.../signup` URL. After creating an account, they will be prompted to complete the verifications defined in this template (e.g., ID Assist Apply).
* **Signup Verification Template URLs:** For more specific needs, you can use unique URLs that send users to a particular verification flow. This is useful if you want to give different user groups different verification tasks. For example:
  * To have a user complete only the "Reverify ID" flow, direct them to: `https://{sub-domain}.trustswiftly.com/signup/reverify-id`
  * To have them complete the "ID Assist Apply" flow, use: `https://{sub-domain}.trustswiftly.com/signup/id-assist-apply`

**Social Media Registration (Registration Tab)**

Simplify the registration process by allowing users to sign up using their existing social media accounts.

* **Social Account:** Select which social media platforms (e.g., Google, LinkedIn) users are permitted to register with.

Click **Update Settings** in this section to save your social media registration preferences.

**Customizing Signup Page Content (Signup Content Tab)**

You can add custom text and information to the top of your signup page to provide context or specific instructions to your users. This is useful for explaining the purpose of the verification, what documents are required, or setting other expectations.

To add custom content:

1. Navigate to the **Signup Content** tab.
2. Use the rich text editor to add your desired content. You can format text, add headings, and structure the information clearly.
3. For example, you could add a notice for users who need temporary verification for a specific purpose:

   > **Welcome to our enhanced verification process for P2P crypto buyers.** To ensure the security of our marketplace and comply with KYC (Know Your Customer) regulations, we require additional verification for high-value transactions.
   >
   > Please be prepared to submit a government-issued ID and a proof of address. This one-time verification will unlock higher trading limits and help protect our community from fraud.
4. Click **Update Details** to save the content and publish it to your signup page.

**Directing Users to Verify**

Once configured, you can add a link or button on your website that directs users to the appropriate Trust Swiftly sign-up page.

**General Sign-up Link:**

```html
<a href="https://{sub-domain}.trustswiftly.com/signup" target="_blank">
Verify yourself at Trust Swiftly</a>
```

**Pre-Populating User Data**

You can make the sign-up process even easier for your users by pre-populating fields in the registration form. Add the following parameters to any of your signup URLs: `email`, `first_name`, `last_name`, and `phone`.

**Example URL with pre-populated data:**`/signup?email=test@example.com&first_name=test&last_name=test&phone=%2B13129450121`

![Options to enable for self sign up](/files/-MVO52FMBX523Mdu5Kpg)

Example signup page with custom content. This /signup URL can be shared for the quickest and least effort verifications.

<figure><img src="/files/A43PcStTEtsI7oiCKizb" alt=""><figcaption><p>Example Sign Up Register page</p></figcaption></figure>


# Quick Create: Prefill User Data

**Streamline manual user creation by pre-filling profile information via URL.**

This feature is designed for administrators who need to manually create users but want to skip the repetitive data entry. By passing user data directly into the URL, you can load the User Creation page with fields already completed, reducing errors and saving clicks.

#### How It Works

To prefill the form, construct a URL pointing to the `/admin/user/quick_create` endpoint and append the user's data as query parameters.

When an administrator clicks this link, they are taken to the creation page with the data populated. They simply need to review and click **Create**.

**Base URL:** `https://{your_subdomain}.trustswiftly.com/admin/user/quick_create`

#### Available Parameters

Append these optional parameters to the Base URL to pre-populate specific fields.

| Parameter      | Description                                | Example              |
| -------------- | ------------------------------------------ | -------------------- |
| `first_name`   | The user's first name.                     | `John`               |
| `last_name`    | The user's last name.                      | `Smith`              |
| `email`        | The user's email address.                  | `jsmith@example.com` |
| `phone`        | Phone number (must be URL-encoded).        | `%2B13125551234`     |
| `template_id`  | ID of the verification template to assign. | `tmpl_MQ`            |
| `email_notify` | Set to `1` to enable email notifications.  | `1`                  |
| `sms_notify`   | Set to `1` to enable SMS notifications.    | `1`                  |

***

#### ⚡ Pro Tip: Generate Links with Excel (No-Code)

If you have a list of users in a spreadsheet (Excel or Google Sheets), you can generate these links automatically without any coding. This is perfect for onboarding batches of users quickly.

**Step 1: Organize your data** Ensure your spreadsheet has the user data in the following columns:

* **Column A:** First Name
* **Column B:** Last Name
* **Column C:** Email
* **Column D:** Phone Number (digits only, e.g., `15551234567`)

**Step 2: Use the Formula** Paste the following formula into **Column E** (or any empty column):

```excel
="https://{your_subdomain}.trustswiftly.com/admin/user/quick_create?first_name="&A2&"&last_name="&B2&"&email="&C2&"&phone=%2B"&D2&"&email_notify=1&sms_notify=1"
```

*(**Note:** Replace `{your_subdomain}` with your actual Trust Swiftly subdomain).*

**Step 3: Drag and Click** Drag the formula down for all your rows. You now have a clickable link for every user that will instantly set up their account creation page.

> **Need a starting point?** Create a CSV and copy the data below into your spreadsheet to test the formula immediately.
>
> ```csv
> First Name,Last Name,Email,Phone
> John,Smith,jsmith@example.com,13125551234
> Jane,Doe,jdoe@test.com,14155559876
> ```

***

#### Example Usage

**Scenario:** You need to create a user named **John Smith**, assign the template `tmpl_MQ`, and turn on all notifications.

**Constructed URL:**

```
https://demo1.trustswiftly.com/admin/user/quick_create?first_name=John&last_name=Smith&email=jsmith@example.com&phone=%2B13125551234&template_id=tmpl_MQ&email_notify=1&sms_notify=1
```

**Result:** The administrator accesses the URL, reviews the pre-filled data, and clicks **"Create"** to finalize the account.

<figure><img src="https://1722465976-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MQXj2cAjHd66kg8IboI%2Fuploads%2FJInsdASedWtzbLSc8IeR%2Fimage.png?alt=media&#x26;token=165eb3d6-40e8-4169-8c37-4f3b38a4afe4" alt="User Creation Screen populated with data"><figcaption></figcaption></figure>


# SAML2 SSO (Okta, etc)

Setup SAML2 authentication for your Trust Swiftly instance. This adds additional safeguards to access the admin dashboard and quicker onboarding for your team by centralizing user management.

Integrating Trust Swiftly with a SAML 2.0 identity provider (IdP) like Okta, Azure AD, or others centralizes user management, enhances security, and simplifies the login process. This guide will walk you through the setup process.

{% stepper %}
{% step %}

## Configure Your Identity Provider (Okta Example)

First, create a new application within your identity provider. The following steps use Okta as an example.

1. Log in to your Okta organization with administrative privileges.
2. Navigate to **Applications** > **Applications**, and click **Create App Integration**.
3. In the pop-up window, select **SAML 2.0** as the sign-in method and click **Next**.
4. **General Settings:**
   * Give the application a name, such as "Trust Swiftly".
   * *Optional:* Upload the Trust Swiftly logo using this URL: `https://app.trustswiftly.com/assets/images/icon.png`
   * Click **Next**.
5. **Configure SAML:** Enter the following values into the corresponding fields (replacing `{subdomain}` with your actual Trust Swiftly subdomain):
   * **Single sign-on URL:** `https://{subdomain}.trustswiftly.com/auth/saml2/callback`
   * **Audience URI (SP Entity ID):** `https://{subdomain}.trustswiftly.com/auth/saml2`
   * **Name ID format:** `EmailAddress`
   * **Application username:** `Email` (or `Okta username` if your Okta usernames are emails)
6. **Attribute Statements:** Configure an attribute to pass the user's email address to Trust Swiftly:
   * **Name:** `email`
   * **Name format:** `Unspecified`
   * **Value:** `user.email`
7. Click **Next**. On the feedback page, select *"I'm an Okta customer adding an internal app"* and click **Finish**.
8. **Get Metadata URL:** After creating the app, go to the **Sign On** tab. In the "SAML 2.0" section, find the link labeled **Identity Provider metadata**. Right-click and copy this URL. *(The URL will look similar to: `https://your-org.okta.com/app/xxxxxxxx/sso/saml/metadata`)*
   {% endstep %}

{% step %}

## Configure Trust Swiftly

Provide the Identity Provider details to your Trust Swiftly instance. (Contact <support@trustswiftly.com> with the URL for setup if your account does not have permission)

1. Log in to your Trust Swiftly dashboard with an administrator account.
2. Navigate to **Settings** > **Auth & Registration**.
3. On the **Authentication** tab, locate the **Single Sign On** section.
4. Paste the **Metadata URL** you copied from Okta into the text field.
5. Click **Update Settings** at the bottom of the page to save the configurations.
   {% endstep %}

{% step %}

## Enforce Single Sign-On (Optional)

You can require all administrators and analysts to log in exclusively through SSO, disabling password-based login for those roles.

{% hint style="warning" %}
**Important Warning:** Do not enable this setting until you have successfully tested the SSO login flow in a separate, incognito/private browser window. Keep your current administrator session active during testing to avoid locking yourself out of the dashboard.
{% endhint %}

1. While still on the **Auth & Registration** page, locate the **Enforce Single Sign On** toggle.
2. Enable this option to restrict admins and analysts to SSO logins only.
3. Click **Update Settings** to save your changes.
   {% endstep %}

{% step %}

## Logging In via SSO

To log in, users must first be assigned the application within Okta. Once assigned, they can log in using either of the following methods:

* **Identity Provider (IdP) Initiated:** Users click the **Trust Swiftly** application tile on their Okta dashboard. They will be automatically redirected and logged in.
* **Service Provider (SP) Initiated:** Users navigate directly to `https://{subdomain}.trustswiftly.com/auth/saml2/login` (replacing `{subdomain}` with your company's subdomain). This will automatically redirect them to Okta to authenticate before returning to the dashboard.
  {% endstep %}
  {% endstepper %}


# Rippling SSO App

Setup SSO with Rippling using a custom application

1. Add a Custom App in Rippling.&#x20;
2. Go to **IT Management** > **Custom App** from the left navigation menu.&#x20;
3. Click **Create New App** button to create a new application.

   From the next screen, fill in the following fields:

   * **App Name -** TrustSwiftly
   * **Select Categories**&#x20;
   * **Upload Logo -** You can download <https://app.trustswiftly.com/assets/images/icon.png> and use as an icon or download the below.

   <figure><img src="/files/iI1NeGYiGgqt9Sjmc417" alt="" width="188"><figcaption></figcaption></figure>

   * **What type of app would you like to create?** - Make sure you select **Single Sign-On (SAML)** from the list.

   <br>
4. Copy the IdP Metadata URL from Rippling. i.e. similar too

<pre class="language-html"><code class="lang-html"><strong>https://app.rippling.com/api/platform/sso/idp-metadata/XXXXXXXXXXXXXX
</strong></code></pre>

5. Paste it in your Trust Swiftly Auth settings /settings/auth and save it.
6. In Rippling for the paste the Trust Swiftly metadata URL&#x20;

```
https://[COMPANY].trustswiftly.com/auth/saml2/metadata
```

7. Edit the app for advanced SSO configuration to match the below settings. Make sure SP initiated login is checked.&#x20;

<figure><img src="/files/FeR0N8EgHtIRSFwKA6bS" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/43Xjbvcy9kgXgv3atqRT" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/1ktty3kdx5qz2JjpxUxV" alt=""><figcaption></figcaption></figure>


# Azure Entra ID SAML

For added security Trust Swiftly is compatible with Azure SSO which allows your admins to not reenter their password to access the app. Setup SSO with Entra using a custom app for SAML authentication.

1. Add a Custom Enterprise App - <https://entra.microsoft.com/#view/Microsoft_AAD_IAM/StartboardApplicationsMenuBlade/~/AppAppsPreview>

2. Go to **+ New Application** > **Create your Own application** from the top navigation menu.&#x20;

3. Click **Integrate any other application you don't find in the gallery (Non-gallery)** radio to create a new application.

   From the next screen, fill in the following fields:

   * **App Name -** Trust Swiftly
   * **Upload Logo -** You can download <https://app.trustswiftly.com/assets/images/icon.png> and use as an icon or download the below. Go to **Properties** of the app then you can modify the logo.&#x20;

   <figure><img src="/files/iI1NeGYiGgqt9Sjmc417" alt="" width="188"><figcaption></figcaption></figure>

4. In the **Manage** section of the app select **Single sign-on** then click the **SAML** box.

5. Click **Edit** next to the Basic SAML Configuration. Then copy and paste the below into their respective inputs. Click Save to complete. Replace \[COMPANY] with your actual name.

```html
https://[COMPANY].trustswiftly.com/auth/saml2
https://[COMPANY].trustswiftly.com/auth/saml2/callback
https://[COMPANY].trustswiftly.com/auth/saml2/login
```

<figure><img src="/files/K2PZONeH5HfNeXYWM9PV" alt=""><figcaption></figcaption></figure>

6. In the **Attributes & Claims** section click Edit. On this popup edit the Unique User Identifier (Name ID) so the identifier format is set to **Email address.**

<figure><img src="/files/Xoq8iwB9ydoo6qJeec5Y" alt=""><figcaption></figcaption></figure>

7. Next update the **Claim name:** *name* by clicking the edit icon and changing the value to **user.displayname**

<figure><img src="/files/YWVmJiNBRs3bWjkVwKzl" alt=""><figcaption></figcaption></figure>

8. In the SAML Certificates section copy the App Federation Metadata Url and paste it in your Trust Swiftly Auth settings page `https://[COMPANY].trustswiftly.com/settings/auth` and save it for the Single Sign On input.

<figure><img src="/files/1glbs53cZxuKVDZ4ITEa" alt=""><figcaption></figcaption></figure>

9. After this is completed and tested you can enable the Enforce Single Sign On setting for added security. Only SAML authenticated sessions will be allowed.&#x20;


# Slack

Setup Slack notifications to be alerted about new verification statuses.

**Configuring Slack Notifications**

Stay informed about key verification events in real-time by integrating Trust Swiftly with your Slack workspace. This setup allows you to receive instant notifications, enabling your team to monitor statuses and respond quickly to verifications that require manual review.

**Step 1: Create an Incoming Webhook in Slack**

First, you need to generate a unique webhook URL from your Slack account. This URL will be used by Trust Swiftly to send notifications directly to a channel of your choice.

1. **Create or Choose a Slack Channel:** Decide which channel you want to receive notifications in. It's often best to create a new, dedicated channel, such as `#verification-alerts` or `#trust-swiftly-logs`, to keep these updates organized.
2. **Generate the Webhook URL:**
   * Navigate to the Slack API documentation for Incoming Webhooks: <https://api.slack.com/messaging/webhooks>
   * Follow the on-screen instructions to create a new webhook. You will be prompted to select the channel you prepared in the previous step.
   * Once created, Slack will generate a unique Webhook URL. It will look something like this:     `https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX`
   * Click **Copy** to save this URL for the next step.

**Step 2: Configure Notification Events in Trust Swiftly**

Next, add the webhook URL to your Trust Swiftly settings and select which events you want to be notified about.

1. **Navigate to Notification Settings:** In your Trust Swiftly dashboard, go to **Settings** -> **Notifications** and select the **Slack** tab.
2. **Add Webhook URL:** Paste the Slack webhook URL you copied into the **Webhook URL** field.
3. **Subscribe to Events:** Below the URL field, you will see a list of available notification events. You can subscribe to the events that are most relevant to your workflow. For example:
   * **Document Verification Complete:** Receive an alert only when a document verification is finished. This is highly useful for teams that need to perform manual reviews of submitted documents.
   * **New User Registered:** Get notified every time a new user signs up.
   * **Verification Status Changed:** Stay updated on every change in a verification's lifecycle.
4. **Save Your Settings:** After configuring your webhook and event subscriptions, click **Update Settings** to save the configuration.

Your Slack integration is now active! Notifications for the events you subscribed to will be sent to your designated Slack channel, providing your team with timely and actionable updates.

<figure><img src="/files/I2LPlQTT9Wl2v2WwvHAj" alt=""><figcaption></figcaption></figure>


# Zoho Cliq

Zoho Cliq can be used to receive notifications from Trust Swiftly about verification statuses.

**Configuring Zoho Cliq Notifications**

Integrate Trust Swiftly with Zoho Cliq to receive real-time notifications about verification events. This allows your team to monitor statuses directly within your Cliq channels, ensuring prompt awareness and action.

This integration requires creating a custom bot in Zoho Cliq to handle incoming messages from Trust Swiftly.

**Step 1: Create a Bot and Incoming Webhook in Zoho Cliq**

First, you need to set up a bot in Zoho Cliq that will receive and post the notifications.

1. **Follow the Zoho Cliq Guide:** Use Zoho's official guide to create a bot with an "Incoming Webhook Handler." You can find the detailed steps here: [Zoho Cliq - Incoming Webhook Handler Guide](https://help.zoho.com/portal/en/community/topic/cliq-bots-get-notifications-about-any-action-on-an-application-with-the-incoming-webhook-handler).
2. **During Setup, You Will:**
   * **Create a Bot:** Give your bot a descriptive name, like "Trust Swiftly," and an icon for easy identification.
   * **Enable the Incoming Webhook Handler:** This is the core component that allows the bot to receive external data.

**Step 2: Configure the Bot's Handler Code**

The handler determines how the bot processes and displays the information it receives from Trust Swiftly.

1. In your bot's settings, navigate to the **Code** or **Handler** section.
2. Delete any placeholder code and paste the following code snippet into the editor. This code is pre-configured to format Trust Swiftly's notifications into readable messages.

```javascript
// Incoming Webhook Handler Code for Trust Swiftly
response = Map();
verification_name = body.get("verification_name");
email = body.get("email");
user_url = body.get("user_url");
user_id = body.get("user_id");
status = body.get("verification_status");
first_name = body.get("first_name");
last_name = body.get("last_name");
phone = body.get("phone");
date = body.get("date");
userids = body.get("userids");
verification_data = body.get("verification_data");

// This block handles general verification updates.
if(body.get("userids") == null)
{
	response = {"text":"A new verification was updated: \n Method: " + verification_name + " \n Data: " + verification_data + " \n Email: " + email + "\n Phone: " + phone + " \n User ID:" + user_id + "\n [View User URL](" + user_url + ") \n Status: " + status + " \n Date: " + date,"card":{"title":"Verification Update","theme":"modern-inline"},"buttons":{{"label":"View Details","type":"+","action":{"type":"open.url","data":{"web":user_url}}}}};
	response.put('bot',{"name":"Trust Swiftly","image":"https://trustswiftly.com/assets/img/favicon.png"});
	
    // IMPORTANT: Change 'trustswiftly' to your desired channel's unique name.
	zoho.cliq.postToChannelAsBot('trustswiftly','trustswiftly',response);
	return response;
}
// This block handles notifications that require a specific user's review.
else
{
	response = {"text":"A new verification requires review: \n " + verification_data + " \n Email: " + email + "\n Phone: " + phone + " \n User ID:" + user_id + "\n [View User URL](" + user_url + ") \n Reviewer: " + userids,"card":{"title":"Verification Update","theme":"modern-inline"},"buttons":{{"label":"View Details","type":"+","action":{"type":"open.url","data":{"web":user_url}}}}};
	response.put('bot',{"name":"Trust Swiftly","image":"https://trustswiftly.com/assets/img/favicon.png"});
	response.put("userids",userids);
	return response;
}
```

3. **Important:** In the code above, locate the line `zoho.cliq.postToChannelAsBot('trustswiftly', ...);`. You **must** change the first `'trustswiftly'` to the unique name of the Zoho Cliq channel where you want the bot to post messages.
4. **Save and Publish** the handler code.

**Step 3: Get Your Unique Webhook URL**

After setting up the handler, you need to get the unique URL for Trust Swiftly to send data to.

1. In your bot's settings, find the **Incoming Webhook Endpoint**.
2. Next, go to the **Webhook Tokens** section to generate a token if one doesn't already exist.
3. Combine these pieces to form your final URL, which will look like this:   `https://cliq.zoho.com/company/{zoho_company_id}/api/v2/bots/{bot_unique_name}/incoming?zapikey={your_token}`

**Step 4: Configure Trust Swiftly**

1. In your Trust Swiftly dashboard, navigate to **Settings** -> **Notifications** and select the **Zoho Cliq** tab.
2. Paste the complete Webhook URL you constructed in the previous step into the **Webhook URL** field.
3. **Subscribe to Events** that you want to be notified about (e.g., Document Verification Complete).
4. Click **Update Settings**.

**Step 5: Add the Bot to Your Cliq Channel**

Finally, for the bot to be able to post messages, you must add it to the channel you specified in the handler code.

1. Go to the desired channel in Zoho Cliq.
2. Type `@` followed by your bot's name (e.g., `@Trust Swiftly`) and send the message.
3. Follow the prompts to add the bot to the channel.

Your integration is now complete! Notifications from Trust Swiftly will appear in your configured Zoho Cliq channel.

<figure><img src="/files/k2SGHz4ZgHPRHI9QEJez" alt=""><figcaption><p>Find the webhook endpoint</p></figcaption></figure>

* Add the Trust Swiftly bot to any channels you require

<figure><img src="/files/nRSgEsAZ7CGXfA0XvYsi" alt=""><figcaption><p>Make sure to add the bot to your channel.</p></figcaption></figure>

<figure><img src="/files/zCylO7JaIlT7RRzXzNqe" alt=""><figcaption><p>Example Notification in Cliq</p></figcaption></figure>


# Email and Chat

Setup email and live chat options from Trust Swiftly for additional communications.

**Configuring Email and Live Chat Notifications**

Keep your team and users informed by setting up email notifications for key events. Additionally, you can provide real-time support to your users during the verification process by integrating a live chat widget directly onto the verification page.

**Email Notifications**

You can configure various email alerts to be sent to administrators when certain events occur.

**To configure email notifications:**

1. Navigate to **Settings** -> **Notifications**.
2. Select the **Email** tab.

**Email Notification Settings:**

* **Admin Notification Email:** Set the primary email address where all administrative alerts will be sent. This is the central point for receiving important updates.
* **Subscriptions:** For more granular control, you can subscribe to notifications for specific events. This allows you to be alerted only for the events that matter most to your workflow.
  * Click **+ Add Subscription**.
  * Select the **Event** you want to monitor (e.g., Phone / SMS).
  * Choose the specific **Event Status** (e.g., `verification.completed`).
  * Click **Add**. An email will now be sent to your admin address whenever a user successfully completes a phone verification.

**General Email Settings:**

On the right side of the page, you can manage global email settings:

* **New Account Notification:** Enable this to notify administrators whenever a new user signs up.
* **Disable Reject Email Notification:** By default, users receive an email if their verification is rejected. Enable this to turn that notification off.
* **Disable Reset/Reassign Verification Updated Email for Users:** Turn off the email that is sent to a user when their verification is reset or reassigned by an admin.
* **Send Verification Completed Email:** Enable this to send an email to a user once they have successfully completed all of their required verifications.

<figure><img src="/files/vy96oEsPdveGtnKmoMOh" alt=""><figcaption></figcaption></figure>

**Live Chat Integration**

Provide instant support to your users by embedding a live chat widget directly on the verification pages. This allows users to ask questions and get help if they encounter any issues.

**To enable Live Chat:**

1. Navigate to **Settings** -> **Notifications**.
2. Select the **Live Chat** tab.
3. **Enable** the "Enable or disable live chat" toggle.
4. From the **Chat** dropdown menu, select your live chat provider (e.g., Zendesk, Comm100, Zoho).
5. In the key field below (e.g., **Zendesk Key**), enter the unique integration key or ID provided by your chat service.
6. Click **Update Settings** to save the configuration.

Once enabled, the live chat widget will appear on the verification pages, giving your users a direct line to your support team.


# Install and Demo Guide

The below instructions can be used for demo purposes and for live transactions you can consult with our team for optimal setup with Radar rules.

**Stripe App Integration Guide**

Automate your payment review process, reduce manual work, and fight fraud by integrating Trust Swiftly directly with your Stripe account. This guide will walk you through setting up the Trust Swiftly Stripe App, configuring Stripe Radar rules, and testing the end-to-end workflow.

When a payment is sent to your review queue in Stripe, Trust Swiftly automatically triggers a verification process for the customer. If they pass, the review is approved automatically.

**Prerequisites**

Before you begin, ensure you have the following:

* **A Trust Swiftly Account:** Sign up at [trustswiftly.com](https://trustswiftly.com).
  * **Free Radar Consultation:** To help you maximize revenue, we offer a free initial consultation on optimizing your Stripe Radar rules for new customers with a deposit of $300 or more.
* **A Stripe Account** with administrator access.

***

#### **Part 1: Installation and Connection**

First, you'll log in to Trust Swiftly and install the app from the Stripe Marketplace.

1. **Sign in to Trust Swiftly**
   * Navigate to your tenant URL: `https://[COMPANY].trustswiftly.com/login` (replace `[COMPANY]` with your unique name).
   * Enter your admin username and password.
2. **Install the Trust Swiftly Stripe App**
   * Go to the Stripe App connection page in your settings: `https://[COMPANY].trustswiftly.com/settings/stripe_app`
   * You will be guided to find the **Trust Swiftly** app in the Stripe Marketplace (under the "Compliance & Identity" category).
   * During the installation process in Stripe, you will be asked to provide your domain. Enter your full Trust Swiftly tenant URL: `https://[COMPANY].trustswiftly.com`.
3. **Verify the Installation**
   * After the app is installed, return to the Trust Swiftly settings page.
   * The status should update automatically. If it doesn't, click the **Verify Install** button.

> **Important Note on Test Mode:** If you are operating in Stripe's test mode, you must enable "Test mode" on the Trust Swiftly Stripe App connection page to ensure transactions are handled correctly.

***

#### **Part 2: Configuration in Trust Swiftly**

Next, configure how the app behaves within your Trust Swiftly dashboard.

1. Navigate back to the **Connect Stripe App** page (`.../settings/stripe_app`).
2. **Default Verification Template:** Select a verification template that will be sent to customers whose payments are sent to review.
3. **Approve Reviews Automatically:** Enable this toggle so that when a user successfully passes verification, the corresponding review in Stripe is automatically approved.
4. **User Email Notifications:** Enable this to ensure users receive an email with the link to complete their verification.
5. Click **Update Settings** to save.

***

#### **Part 3: Configure Stripe Radar Rules**

For the integration to work, you must tell Stripe which payments to send to the review queue.

1. Navigate to your **Stripe Radar rules**: [dashboard.stripe.com/settings/radar/rules](https://dashboard.stripe.com/settings/radar/rules).
2. Scroll down to the **"When should a payment be placed in review?"** section.
3. Click **+ Add rule**.
4. Create a condition to trigger a review. For example, you can create a rule for high-risk payments:   `Request a review if :risk_score: > 50 and :amount_in_usd: > 500.00`
5. Click **Test rule** to see how it behaves, then click **Save** to enable it.

> **Need help with Radar?** Setting up effective Radar rules is key to maximizing revenue and minimizing fraud. [**Contact our team**](https://trustswiftly.com/contact) for help with a custom-tailored optimization service.

***

#### **Part 4: Demo and Test the Workflow**

Follow these steps to perform an end-to-end test and see the integration in action.

1. **Create a Test Payment**
   * In your Stripe dashboard, go to **Payment Links** and create a new link.
   * Add a new product with a price that will be triggered by the Radar rule you just created (e.g., $501).
   * Under the advanced options, ensure you **require customers to provide a phone number**.
   * Click **Create link**.
2. **Simulate a Customer Purchase**
   * Copy the payment link and open it in a **new incognito browser window**. This prevents session conflicts.
   * Fill out the payment details using a test email and credit card, then click **Pay**.
3. **Verify the Payment is in Review**
   * Navigate to your **Radar for Reviews** queue in Stripe: [dashboard.stripe.com/radar/reviews](https://dashboard.stripe.com/radar/reviews).
   * You should see the payment you just made listed here.
4. **Complete the Verification (as the customer)**
   * Check the inbox for the email address you used in the test payment.
   * Open the email from Trust Swiftly and click the **Verify** button.
   * You will be taken to the verification flow. Complete the steps (e.g., enter an SMS code).
5. **Confirm Automatic Approval**
   * Return to your Radar review queue in Stripe.
   * Once the verification is passed, the payment should automatically disappear from the review list, indicating it has been approved.


# Disconnect Stripe App

To uninstall the Stripe App click the Uninstall App button on the settings page.

Visit your apps page to select Trust Swiftly <https://dashboard.stripe.com/apps> then uninstall it.

![](/files/za9jTcBsUgalWmImqf5P)


# Supported Documents

We support 300+ different types of documents. Not only government identity documents but also any type of document with a picture. Furthermore, we support Bank statements, Bills,  PDFs, and more.

**Verify Anything: AI-Powered Document & Data Analysis**

Trust Swiftly offers the most flexible verification platform on the market, capable of analyzing virtually any document, image, video, or audio recording. We combine our robust, pre-trained models for standard IDs with the power of cutting-edge AI to create custom verification solutions for any business need.

***

**AI-Powered Custom Verification: Go Beyond the Standard**

Our platform leverages the advanced analytical power of leading AI and Large Language Models (LLMs) from providers like **Google (Gemini), OpenAI (ChatGPT), Mistral, Anthropic,** and more. This allows us to design and deploy verification flows for virtually any use case you can imagine.

If you have a unique verification challenge, we can build a solution for it.

**Examples of Custom AI Verification:**

* **Niche Communities:** A dating app exclusive to firefighters could require users to upload a photo of their **fireman's badge**, which our AI can analyze for authenticity.
* **Professional Credentials:** A marketplace for freelance engineers could verify a **professional engineering license** or a **university degree**.
* **Membership & Status:** A loyalty program could verify a user's **student ID card** to grant a discount or a **military dependent's ID** for special access.
* **Asset Verification:** A P2P rental service could analyze a photo of a vehicle's **registration document** or a short video of an item's condition.

Our AI can be trained to check for specific text, logos, photo comparisons, structural integrity, and other unique markers of authenticity. **If you can dream up a verification scenario, we can help you build it.**

***

**Broad Support for Standard Documents**

While our custom AI solutions are limitless, our platform comes with out-of-the-box support for over 300 types of documents from around the globe. Our base AI model is expertly trained to handle government-issued IDs, proof of address documents, and much more.

**Examples of Commonly Supported Documents:**

| Identity & Government IDs                 | Financial & Proof of Address        | Credentials & Other Documents    |
| ----------------------------------------- | ----------------------------------- | -------------------------------- |
| Passport or Passport Card                 | Utility Bill (Water, Gas, Electric) | Company ID Card / Facility Badge |
| Driver's License (including temporary)    | Bank or Mortgage Statement          | Medical Marijuana Card           |
| State or National ID Card                 | Property Tax Bill                   | Hunting or Fishing Permit        |
| Permanent Resident Card                   | Internet or Cable TV Bill           | Gun or Firearms Permit           |
| US Military Card (front & back)           | Telephone Bill                      | Veteran Health ID Card           |
| Certificate of Citizenship/Naturalization | W-2 Form / Pay Stub                 | Voter Registration Card          |
| Employment Authorization Document         | Social Security Card                | Native American Tribal Document  |
| Agency ID Badge (Federal, State, Local)   | Official Birth Certificate          |                                  |

If a specific document is not on this list, please [**contact us**](https://trustswiftly.com/contact). We are constantly expanding our support.

***

**Global Coverage for Standard IDs**

We support standard government-issued identity documents (Passport, Driver's License, National ID Card) for the following countries and territories:

<table><thead><tr><th width="153">Country</th><th width="139">Abreviation</th><th width="115">Continent</th><th width="250">Supported ID Documents</th></tr></thead><tbody><tr><td>Afghanistan</td><td>AFG</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Albania</td><td>ALB</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Algeria</td><td>DZA</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Andorra</td><td>AND</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Angola</td><td>AGO</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Antigua and Barbuda</td><td>ATG</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Argentina</td><td>ARG</td><td>S. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Armenia</td><td>ARM</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Australia</td><td>AUS</td><td>Australia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Austria</td><td>AUT</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Azerbaijan</td><td>AZE</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Bahamas</td><td>BHS</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Bahrain</td><td>BHR</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Bangladesh</td><td>BGD</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Barbados</td><td>BRB</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Belarus</td><td>BLR</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Belgium</td><td>BEL</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Belize</td><td>BLZ</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Benin</td><td>BEN</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Bhutan</td><td>BTN</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Bolivia</td><td>BOL</td><td>S. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Bosnia and Herzegovina</td><td>BIH</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Botswana</td><td>BWA</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Brazil</td><td>BRA</td><td>S. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Brunei</td><td>BRN</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Bulgaria</td><td>BGR</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Burkina Faso</td><td>BFA</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Burundi</td><td>BDI</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Cabo Verde</td><td>CPV</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Cambodia</td><td>KHM</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Cameroon</td><td>CMR</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Canada</td><td>CAN</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Central African Republic</td><td>CAF</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Chad</td><td>TCD</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Chile</td><td>CHL</td><td>S. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>China</td><td>CHN</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Colombia</td><td>COL</td><td>S. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Comoros</td><td>COM</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Congo</td><td>COG</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Costa Rica</td><td>CRI</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Côte d'Ivoire</td><td>CIV</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Croatia</td><td>HRV</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Cyprus</td><td>CYP</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Czech Republic (Czechia)</td><td>CZE</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Denmark</td><td>DNK</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Djibouti</td><td>DJI</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Dominica</td><td>DMA</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Dominican Republic</td><td>DOM</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>DR Congo</td><td>COD</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Ecuador</td><td>ECU</td><td>S. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Egypt</td><td>EGY</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>El Salvador</td><td>SLV</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Equatorial Guinea</td><td>GNQ</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Eritrea</td><td>ERI</td><td>Africa</td><td>Passport</td></tr><tr><td>Estonia</td><td>EST</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Eswatini</td><td>SWZ</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Ethiopia</td><td>ETH</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Fiji</td><td>FJI</td><td>Australia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Finland</td><td>FIN</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>France</td><td>FRA</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Gabon</td><td>GAB</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Gambia</td><td>GMB</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Georgia</td><td>GEO</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Germany</td><td>DEU</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Ghana</td><td>GHA</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Greece</td><td>GRC</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Grenada</td><td>GRD</td><td>N. America</td><td>Driver License, Passport</td></tr><tr><td>Guatemala</td><td>GTM</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Guinea</td><td>GIN</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Guinea-Bissau</td><td>GNB</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Guyana</td><td>GUY</td><td>S. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Haiti</td><td>HTI</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Holy See</td><td>VAT</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Honduras</td><td>HND</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Hungary</td><td>HUN</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Iceland</td><td>ISL</td><td>Europe</td><td>Driver License, Passport</td></tr><tr><td>India</td><td>IND</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Indonesia</td><td>IDN</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Iraq</td><td>IRQ</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Ireland</td><td>IRL</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Israel</td><td>ISR</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Italy</td><td>ITA</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Jamaica</td><td>JAM</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Japan</td><td>JPN</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Jordan</td><td>JOR</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Kazakhstan</td><td>KAZ</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Kenya</td><td>KEN</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Kiribati</td><td>KIR</td><td>Australia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Kuwait</td><td>KWT</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Kyrgyzstan</td><td>KGZ</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Laos</td><td>LAO</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Latvia</td><td>LVA</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Lebanon</td><td>LBN</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Lesotho</td><td>LSO</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Liberia</td><td>LBR</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Libya</td><td>LBY</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Liechtenstein</td><td>LIE</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Lithuania</td><td>LTU</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Luxembourg</td><td>LUX</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Madagascar</td><td>MDG</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Malawi</td><td>MWI</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Malaysia</td><td>MYS</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Maldives</td><td>MDV</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Mali</td><td>MLI</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Malta</td><td>MLT</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Marshall Islands</td><td>MHL</td><td>Australia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Mauritania</td><td>MRT</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Mauritius</td><td>MUS</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Mexico</td><td>MEX</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Micronesia</td><td>FSM</td><td>Australia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Moldova</td><td>MDA</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Monaco</td><td>MCO</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Mongolia</td><td>MNG</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Montenegro</td><td>MNE</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Morocco</td><td>MAR</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Mozambique</td><td>MOZ</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Myanmar</td><td>MMR</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Namibia</td><td>NAM</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Nauru</td><td>NRU</td><td>Australia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Nepal</td><td>NPL</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Netherlands</td><td>NLD</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>New Zealand</td><td>NZL</td><td>Australia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Nicaragua</td><td>NIC</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Niger</td><td>NER</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Nigeria</td><td>NGA</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>North Macedonia</td><td>MKD</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Norway</td><td>NOR</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Oman</td><td>OMN</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Pakistan</td><td>PAK</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Palau</td><td>PLW</td><td>Australia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Panama</td><td>PAN</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Papua New Guinea</td><td>PNG</td><td>Australia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Paraguay</td><td>PRY</td><td>S. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Peru</td><td>PER</td><td>S. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Philippines</td><td>PHL</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Poland</td><td>POL</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Portugal</td><td>PRT</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Qatar</td><td>QAT</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Romania</td><td>ROM</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Rwanda</td><td>RWA</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Saint Kitts &#x26; Nevis</td><td>KNA</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Saint Lucia</td><td>LCA</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Samoa</td><td>WSM</td><td>Australia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>San Marino</td><td>SMR</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Sao Tome &#x26; Principe</td><td>STP</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Saudi Arabia</td><td>SAU</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Senegal</td><td>SEN</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Serbia</td><td>SRB</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Seychelles</td><td>SYC</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Sierra Leone</td><td>SLE</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Singapore</td><td>SGP</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Slovakia</td><td>SVK</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Slovenia</td><td>SVN</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Solomon Islands</td><td>SLB</td><td>Australia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Somalia</td><td>SOM</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>South Africa</td><td>ZAF</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>South Korea</td><td>KOR</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>South Sudan</td><td>SSD</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Spain</td><td>ESP</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Sri Lanka</td><td>LKA</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>St. Vincent &#x26; Grenadines</td><td>VCT</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>State of Palestine</td><td>PSE</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Sudan</td><td>SDN</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Suriname</td><td>SUR</td><td>S. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Sweden</td><td>SWE</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Switzerland</td><td>CHE</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Tajikistan</td><td>TJK</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Tanzania</td><td>TZA</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Thailand</td><td>THA</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Timor-Leste</td><td>TLS</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Togo</td><td>TGO</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Tonga</td><td>TON</td><td>Australia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Trinidad and Tobago</td><td>TTO</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Tunisia</td><td>TUN</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Turkey</td><td>TUR</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Turkmenistan</td><td>TKM</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Tuvalu</td><td>TUV</td><td>Australia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Uganda</td><td>UGA</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Ukraine</td><td>UKR</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>United Arab Emirates</td><td>ARE</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>United Kingdom</td><td>GBR</td><td>Europe</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>United States</td><td>USA</td><td>N. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Uruguay</td><td>URY</td><td>S. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Uzbekistan</td><td>UZB</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Vanuatu</td><td>VUT</td><td>Australia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Venezuela</td><td>VEN</td><td>S. America</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Vietnam</td><td>VNM</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Yemen</td><td>YEM</td><td>Asia</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Zambia</td><td>ZMB</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr><tr><td>Zimbabwe</td><td>ZWE</td><td>Africa</td><td>Driver License, Identity Card, Passport</td></tr></tbody></table>


