ZTM Integration Guide

ZTM Integration Guide

Spidr's Zero Touch Monitoring (ZTM) provides real-time fraud detection and compliance checks across your embedded finance operations. This guide covers how to integrate ZTM into your application, from SDK setup through transaction monitoring.


How ZTM Works

Architecture Overview

ZTM checks always require the following:

  1. Create a session and initialize the Sardine SDK (or use an existing session if applicable). Spidr recommends setting a session expiration of no more than 30 minutes.
  2. Pass the sessionKey and false for bypassZtm in your request to Spidr's Unified API endpoint.

Step 1: Generate or Use an Existing sessionKey

Generate or use existing sessionKey

Your backend calls POST /ztm/v1/session/create to obtain a sessionKey. Pass this key to your frontend, which initializes the Sardine SDK. The SDK immediately begins collecting device fingerprint and behavioral biometrics data, linking it to the session in Sardine's cloud. This data collection should start as early as possible -- ideally before the user begins filling out any forms -- to capture the richest behavioral signals.

Tip: You can reuse a sessionKey across multiple API calls. Create a new session when the previous session has aged out (we recommend a 30-minute expiry enforced on your end).

Step 2: Call Unified API / ZTM

Call Unified/ZTM

When your backend makes a Unified API call with bypassZtm: false and the sessionKey, ZTM checks are ran against the data provided in the call. Spidr's workflow engine reaches out to configured providers in parallel -- Sardine reads the device/behavior data collected via the session, and Hawk runs transaction and AML checks (if applicable). The combined risk score is evaluated:

  • Low risk -- The request proceeds to the processor, and the action (with its risk score) is viewable in SST.
  • Medium / High risk -- The call is blocked before reaching the processor. The action is added to the SST queue for your Fraud & Compliance team to review and decision.

Note: All actions are viewable in SST regardless of risk level. The risk score is always attached to the action.

Key concepts:

  • Session: A short-lived token linking device intelligence data (collected by the Sardine SDK) to backend API calls. Created via the ZTM API, passed to both the Sardine SDK and included with your Unified API requests.
  • Action: Every operation that runs through ZTM creates a SpidrAction record tracking the risk assessment, decision, and audit trail. Actions are routed to specific queues in SST for review by your Fraud & Compliance team.
  • bypassZtm: A boolean flag on Unified API requests. Set to false to run ZTM checks; defaults to true (no checks).
  • Risk Levels: low, medium, high, pending -- determined by aggregating scores from configured providers (Sardine, Hawk, Plaid). Risk thresholds and rules can be configured with Spidr.
  • Decision: The overall outcome for an action -- approved or declined. Decisions can be posted manually via the API or through SST. Approving an action lets it proceed to completion; declining blocks it.
  • Feedback: After a decision is made, you can submit feedback (agree or disagree) to help train the ZTM model and its underlying providers, improving future risk assessments.

Request Flow (Step by Step)

  1. Create a ZTM session -- POST /ztm/v1/session/create
  2. Initialize the Sardine SDK on the client with the sessionKey
  3. Make your Unified API call (e.g., Create User) with bypassZtm: false and the sessionKey
  4. Spidr's workflow engine calls configured providers (Sardine, Hawk, Plaid) in parallel
  5. Provider scores are aggregated into a single risk level
  6. The action is created with a risk level and routed for decisioning (per your program configuration)
  7. The response includes spidrActionId and ZTM data; a webhook with risk data is also sent to your endpoint

Sardine SDK Integration

If your program is utilizing Sardine for device and behavior checks, you'll need to install and configure the Sardine SDK. The SDK collects device intelligence (fingerprinting, behavioral biometrics) from the user's browser or mobile device. This data is linked to your backend API calls via the sessionKey.

Prerequisites: Access to the Sardine dashboard and Sardine docs. Check with a Spidr team member if you need access.

For the full Sardine SDK guide, see: https://docs.sardine.ai/guides/integration/risksdk/overview

What Spidr Provides

1. .npmrc File

Spidr will provide a pre-configured .npmrc file containing the authentication and private registry access required to install the Sardine SDK packages.

  • Place the .npmrc file in your project root (same directory as package.json)
  • Run your package install command (npm install / yarn install / pnpm install)

Do not commit the .npmrc to version control -- it contains authentication tokens. Add it to your .gitignore.

2. Sardine Client IDs

Spidr will provide separate clientId values for each environment:

EnvironmentPurpose
CV (Certification/Validation)Testing and certification
ProductionLive environment

Platform-Specific Setup

Both the web and React Native SDK packages are private. You must have the .npmrc (provided by Spidr) in your project root before running the install steps in the Sardine docs.

SDK Usage

Once the SDK is installed, you'll use it for three things:

  1. Initialize the SDK with the sessionKey returned from POST /ztm/v1/session/create. This ties the user's device to the session and allows device/behavior data to be associated with it.
  2. Update Sardine context on login -- upon user login, update the Sardine context with the user's Spidr userId.
  3. Ad hoc checks -- if you are performing an ad hoc check via POST /ztm/v1/user/other, update the SDK with the flowName you are passing in.

Flow Types

When initializing or updating the SDK, you specify a flow type to tell Sardine what kind of activity the user is performing. Spidr handles the passing the appropriate flow for Unified API calls. However, you can pass in a custom flow when risk checking non-Unified actions. Some examples are listed below:

FlowWhen to Use
loginReturning user authentication
password_resetPassword reset flows
update_preferencesProfile or app preferences

Best Practice: Initialize the SDK as early as possible in the user flow so it can collect behavioral data (typing patterns, mouse movements) before the user submits a form. Create the session and update the Sardine config before showing the form.

Session Expiry: Spidr does not enforce session expiration server-side. We recommend enforcing a 30-minute expiry on your end.

Quick Setup Checklist

  • Receive .npmrc and Client IDs (CV + Production) from Spidr
  • Place .npmrc in project root (add to .gitignore)
  • Install the appropriate SDK package for your platform (see Sardine docs above)
  • Set clientId in your environment config
  • Initialize SDK with session key from POST /ztm/v1/session/create
  • Update Sardine context with Spidr userId on login
  • Test onboarding flow in CV environment

Use Case Walkthroughs

Each use case below describes the API flow, the relevant ZTM action type, and what to look for when verifying the integration. For full request/response schemas, see the API Reference.

Please note that the examples below are not all-inclusive. For a full list of endpoints that support ZTM checks, please see Endpoints Supporting ZTM.

User Onboarding (KYC)

This is the foundational flow -- most other operations require a user to exist first.

IDV/Onboarding through ZTM

The diagram above shows the full onboarding flow including ZTM risk checks, Plaid IDV (if configured), manual review paths, and CIP status outcomes. A failed CIP status will prevent account creation for that user.

Flow: Session Create -> SDK Init -> Create User (with ZTM checks) -> Decision

Steps:

  1. Create a ZTM session via POST /ztm/v1/session/create. Pass userId if the user already exists; omit it for new users. As soon as you receive a userId from Spidr, update the Sardine context with the ID.

  2. Initialize the Sardine SDK with the returned sessionKey.

  3. Create the user via POST /v1/user/create with:

    • bypassZtm: false
    • sessionKey (from step 1)
    • User PII (name, DOB, email, phone, SSN, address)
    • initialProductId (your product ID)
    • idvTemplateId (if using Plaid IDV)
  4. Handle the response:

    • userId -- the Spidr user ID (store this)
    • spidrActionId -- ZTM action ID for tracking
    • ztmData -- risk level and provider details
    • If Plaid IDV is configured, the response may include a shareableUrl for the user to complete identity verification

What happens behind the scenes:

  • Sardine runs customer + device checkpoints using SDK-collected data
  • If Plaid IDV is configured, an IDV session is created
  • If watchlist screening is configured, AML checks run
  • Provider scores are aggregated into a risk level

After onboarding, create an account via POST /v1/account/create with the userId and productId. Note that a Spidr account can only be created for users with a CIP status of pass.

You will receive a webhook when a user's CIP status has been updated, see user.cipStatusUpdate. You can use this event to trigger onboarding rejection/acceptance logic in your app.

ZTM Action Type: user_create


Incoming ACHs & Card Authorizations)

Direct deposits, other incoming ACH credits and debits, and card authorizations are processor-initiated -- they are not triggered by your API calls. ZTM monitors these automatically based on your product's workflow configuration.

Incoming ACH/Card Auth Checks

When the processor receives a card authorization or incoming ACH transaction, Spidr's webhook handler picks it up and sends it through ZTM for risk evaluation (Hawk transaction/AML checks). The result -- including the risk score -- is attached to the action and delivered to your webhook endpoint. Low-risk transactions proceed normally; non-low-risk transactions are added to the SST queue for review.

Incoming ACH:

  • Initiated by a third party (e.g., an employer's payroll system)
  • Monitored via the transaction_ach_incoming action type
  • No API call or bypassZtm parameter needed on your side

Card Authorizations & Settlements:

  • Card-not-present (online) and card-present (point-of-sale) purchases
  • The card network sends authorization requests to your processor, which Spidr processes
  • Monitored via the transaction_card_auth action type
  • For BYOP clients, card transactions are instead reported to Spidr via POST /v1/transaction/createTransaction with bypassZtm: false (see below)

What to verify:

  • The transaction appears in the user's transaction history via GET /v1/transactions
  • The ztmData on the transaction record shows the risk assessment
  • Your webhook endpoint receives the transaction event with risk data

For testing card flows in sandbox:

BYOP (Bring Your Own Processor) clients report card transactions via POST /v1/transaction/createTransaction with:

  • accountId, cardId
  • txnKey -- unique transaction reference from your processor
  • txnType -- e.g., purchase.authorization, purchase.settlement
  • amount, status, txnDate
  • merchant details (name, MCC, city, state, country)
  • entryMode -- card_not_present, chip, swipe, contactless, or manual
  • bypassZtm: false to enable ZTM checks
ZTM Action TypeTrigger
transaction_ach_incomingIncoming ACH (processor-initiated)
transaction_card_authCard authorization (processor-initiated)
transaction_createCard transaction reported via BYOP endpoint

ACH Transfers

ACH transfers move money between a user's Spidr account and their linked external bank account.

Flow: Session Create -> SDK Init -> Create ACH Transfer (with ZTM checks)

Steps:

  1. Create a ZTM session via POST /ztm/v1/session/create with the userId or use an existing sessionKey.

  2. Update the Sardine SDK with the sessionKey.

  3. Create the ACH transfer via POST /v1/transaction/createAchTransfer with:

    • bypassZtm: false
    • sessionKey
    • accountId -- the user's Spidr account
    • achAccountId -- the linked ACH account
    • amount
    • description
    • debitCreditIndicator -- "credit" (push to external bank) or "debit" (pull from external bank)
  4. Handle the response:

    • achRequestId -- ACH request tracking ID
    • spidrActionId -- ZTM action ID
    • ztmData -- risk assessment and provider details
    • Medium/High risk levels are auto-blocked and will not make it to the processor. You will receive a ZTM 'No Go' error if a call is blocked due to ZTM. If the call is deemed low-risk after review, you must resubmit the request with bypassZtm set to true.

ACH Credit (outbound push): Money goes from the user's Spidr account to their external bank. ZTM assesses risk of the outbound transfer.

ACH Debit (outbound pull): Money comes from the user's external bank into their Spidr account. ZTM can also trigger a balance check on the linked account via Plaid before processing.

ZTM Action Type: transaction_ach_create


A2A Transfers

Use the Create A2A Transfer endpoint to move funds between two Spidr accounts.

Flow: Session Create -> SDK Init -> Create A2A Transfer (with ZTM)

Steps:

  1. Create a ZTM session via POST /ztm/v1/session/create with the sender's userId or use an existing sessionKey.

  2. Update the Sardine SDK with the sessionKey.

  3. Create the A2A transfer via POST /v1/transaction/createA2ATransfer with:

    • bypassZtm: false
    • sessionKey
    • senderAccountId
    • receiverAccountId
    • amount
    • description
  4. Handle the response:

    • spidrActionId -- ZTM action ID
    • ztmData -- risk assessment
    • Medium/High risk levels are auto-blocked and will not make it to the processor. You will receive a ZTM 'No Go' error if a call is blocked due to ZTM. If the call is deemed low-risk after review, you must resubmit the request with bypassZtm set to true.

ZTM evaluates A2A transfers assessing both the sender and receiver in the risk calculation.

ZTM Action Type: transaction_a2a


Understanding the ztmData Response

Every ZTM-enabled request returns a ztmData object alongside the primary response data. Here's what to pay attention to.

Top-Level Fields

FieldDescription
riskLevelThe overall aggregated risk level (low, medium, high, pending). This is the primary value your app should use for routing logic.
providerSummaryShows which providers ran and each one's individual risk level via providerLevels. Useful when the overall level is elevated and you need to see which provider flagged it.
providerResponsesDetailed per-provider response data. See below.
providerErrorsAny errors from providers. Always verify this is empty -- if not, the risk assessment may be incomplete.
isTrainingModeWhen true, risk checks run but actions are not blocked regardless of risk level.

Sardine Response (in providerResponses)

FieldDescription
levelSardine's overall risk level for this action.
sessionKeyCross-reference this in the Sardine dashboard to inspect device/behavior data.
flowName / flowTypeWhich flow was evaluated (e.g., flow-user-create / onboarding).
customer.scoreNumeric risk score (0--99, lower = less risky).
customer.levelRisk level derived from the score.
customer.signalsIndividual risk signals (address, email, phone, PEP, sanctions, etc.) -- check these to understand why a score was assigned.
aml(Transaction flows only) AML-specific risk level and triggered rules.
checkpointsRule categories evaluated by Sardine (e.g., customer, onboarding, aml). Each has a riskLevel.
rulesRules that fired. isLive: true means the rule is enforced; isLive: false means it's in shadow/testing mode and doesn't affect the outcome.

Hawk Response (in providerResponses)

FieldDescription
levelHawk's risk level for this action.
providerData.caseIdUse this to look up the case in the Hawk dashboard.
providerData.proceedtrue = proceed, false = review/block.

Decisions, Feedback, and Actions

Understanding Actions

Every interaction with the Spidr platform -- whether initiated by your app or through SST -- is logged as a Spidr Action. When ZTM is enabled (i.e., bypassZtm: false), the action includes risk data from configured providers.

Each action includes:

  • Status: pending, success, blocked, failed
    • success -- processed successfully by Spidr and the underlying processor
    • blocked -- prevented from reaching the processor due to risk level
    • failed -- error encountered during processing
  • Risk Level: low, medium, high, pending
  • Decision: approved or declined (or null if awaiting decision)
  • Bypass ZTM: Whether ZTM checks ran on this action

Checking Action Status

Every ZTM-monitored operation returns a spidrActionId. Query the action via:

GET /ztm/v1/action/{spidrActionId}

The response includes status, decision, riskLevel, providerSummary (risk levels per provider), and decisionDetails.

Posting a Decision

Actions with a pending status require a decision. Post a decision via POST /ztm/v1/action/decision with:

  • id -- the spidrActionId
  • actionType -- must match the original action type (e.g., user_create)
  • decision -- "approved" or "declined"
  • reason -- text explanation for the decision

Approving an action lets it proceed to completion. Declining an action blocks it from proceeding further. Decisions can also be made through SST by users with the Compliance role.

Some actions may be auto-decisioned per your configuration with Spidr. Auto-decisioned actions receive a decision from ZTM based on the risk level.

Providing Feedback

After a decision has been made on an action (either auto-decisioned or manual decision), you can submit feedback to help train the ZTM model and its underlying providers. Post feedback via POST /ztm/v1/action/feedback with:

  • feedbackType -- "agree" or "disagree"
  • reason -- text explanation
  • feedbackUpdates -- array of { spidrActionId } objects (batch feedback supported)

In SST, feedback is submitted through the Feedback Queue under the ZTM section. Only the Compliance role can submit feedback.

Listing Actions

Query actions via GET /ztm/v1/action with query parameters for filtering.

Supported filters: status, decision, riskLevel, userId, accountId, transactionId, bypassZtm, actionType, and more.


Verification and Debugging

When integrating, it's important to confirm that data reaches all layers of the platform. Here's how to trace a request end-to-end:

1. Spidr API Response

Every ZTM-enabled request returns:

  • spidrActionId -- unique action identifier
  • ztmData -- risk level and provider details (when ZTM runs)

Store the spidrActionId for all subsequent lookups.

2. ZTM Action (ZTM API)

Query the action directly via GET /ztm/v1/action/{spidrActionId} and check:

  • status -- Is it pending, success, or blocked?
  • riskLevel -- What risk level was assigned?
  • providerSummary -- Which providers ran and what did each return?
  • decision / decisionDetails -- Was it decisioned? By whom?
  • bypassZtm -- Confirm it's false (ZTM actually ran)

3. Sardine Dashboard

If Sardine is a configured provider, verify the session in the Sardine Dashboard:

  • Log in to your Sardine dashboard (reach out to Spidr if you need access)
  • Search by the sessionKey used in your request
  • Verify device intelligence data was collected (device fingerprint, behavioral signals)
  • Check the customer risk score and any triggered rules
  • Confirm the flow type matches the type of action (onboarding, transaction, etc.)

4. SST (Spidr Service Tool)

SST is Spidr's admin tool for account maintenance and operational activities. It's powered by the Unified API and provides real-time visibility into ZTM data. See the SST User Guide for full details.

Key SST screens for verification:

  • User Actions / Account Actions tabs -- Every action is logged here. Click "View Details" on any action to see the full Action Details Modal which includes:

    • Summary -- Status, risk level, decision, provider summary with per-provider risk breakdown, and decision details
    • Provider Details -- Raw data from Sardine, Hawk, etc. Includes a link to jump out to the vendor dashboard
    • Change History -- Before/after values for any updates
    • Errors -- Any failures at the Unified or ZTM level
  • ZTM Queues (sidebar) -- Specialized queues for reviewing ZTM-scored actions:

QueuePurpose
IDV & MonitoringAll user_create and watchlist actions for programs enrolled in IDV/watchlist monitoring. Used for manual review and decisioning.
FeedbackActions that have been decisioned but need feedback (agree/disagree). Only visible to Compliance roles.
  • CIP Tab (User Details) -- If your program uses IDV and/or watchlist screening:

    • Shows current CIP Status (pending, pass, fail)
    • Shows Watchlist Status and any hits requiring review
    • IDV session details and document review
  • Linked Institutions Tab (User Details) -- Review all linked external bank accounts and their underlying institution accounts.

5. Webhooks

Spidr sends webhooks for ZTM events. Verify your webhook endpoint receives the relevant webhooks listed here: ZTM webhooks.

Common Troubleshooting

SymptomLikely CauseFix
No ZTM data in responsebypassZtm is true (default)Set bypassZtm: false in your request
Device data missing in SardineSDK not initialized with session keyEnsure Sardine SDK is updated with sessionKey before the user submits the form
Session key errorSession expired or wrong companyCreate a fresh session; ensure your API key matches the environment
Risk level is pendingProvider returned inconclusive resultCheck the Plaid dashboard; may require the user to complete IDV or manual review may be required.
CIP status is pendingIDV or watchlist review not completeComplete IDV manual review and/or watchlist hit review in SST.

Endpoints Supporting ZTM

The following Unified API endpoints accept the bypassZtm parameter. When set to false, ZTM checks run. When true (default), they are skipped.

User Operations

EndpointMethodDescription
/v1/user/createPOSTCreate a new user (KYC)
/v1/user/:idPATCHEdit user information

Account Operations

EndpointMethodDescription
/v1/account/createPOSTCreate a new account
/v1/account/:idPATCHEdit account details
/v1/account/:id/featuresPATCHEdit account features
/v1/achaccount/createPOSTLink an ACH account

Transaction Operations

EndpointMethodDescription
/v1/transaction/createAchTransferPOSTCreate an ACH transfer
/v1/transaction/createA2ATransferPOSTCreate an A2A (P2P) transfer
/v1/transaction/createTransactionPOSTCreate a transaction (BYOP)
/v1/transaction/createAdjustmentPOSTCreate an adjustment

Card Operations

EndpointMethodDescription
/v1/card/:id/activatePOSTActivate a card
/v1/card/:id/statusPATCHModify card status
/v1/card/:id/reissuePOSTReissue a card
/v1/card/:id/replacePOSTReplace a card
/v1/card/:id/mobileWalletProvisioningPOSTProvision mobile wallet
/v1/card/:id/pinChangeTokenGETGet PIN change token
/v1/card/:id/displayUrlGETGet card display URL

Entity Operations

EndpointMethodDescription
/v1/entity/createPOSTCreate an entity (KYB)

For the full API reference, see docs.gospidr.com/reference. For SST guidance, see the SST User Guide.