Docs / Surface / contact-integration

Contact Integration

Surface integrates with Contact so you can screen message payloads for threats and trigger Strand workflows based on scan results.

How it works

When a message arrives in Contact and matches a flow with tags, the flow system can trigger Strand workflows that include Surface scan steps. The tag-matching mechanism connects Contact messages to Strand workflows automatically:

  1. A message arrives at a Contact entity with tags (e.g. ["scan", "incoming"])
  2. Contact checks for Strand workflows whose trigger tags overlap with the message tags
  3. Any matching workflow is triggered with the message data as the workflow payload
  4. If the workflow includes a surface.platform node, the payload is scanned

The scan runs as part of the Strand workflow execution; it does not block or delay Contact message delivery.

Tag-matching mechanism

Workflow triggering and connector routing match tags differently, and this is the most common integration mistake:

For example, a message tagged ["environmental", "data_quality"] does not fire a workflow whose trigger tags are only ["data_quality"], because that workflow is missing environmental. A workflow tagged ["environmental", "data_quality"] does fire for a message tagged ["data_quality"]. Keep message tags minimal and give workflows every tag they should respond to.

Contact trigger payload

When Contact triggers a Strand workflow, the trigger payload has this structure:

json

{
  "accountId": "12345",
  "flowId": "flow_abc",
  "flowName": "sensor_validation",
  "executionId": "exec_xyz",
  "tags": ["environmental", "data_quality"],
  "entityId": "entities/temperature_sensor_01",
  "entityName": "temperature_sensor_01",
  "messageId": "6614abcd1234ef5678901234",
  "data": {
    "temperature": 85.2,
    "humidity": 45,
    "timestamp": "2025-03-24T10:00:00Z"
  },
  "timestamp": "2025-03-24T10:00:01Z"
}

Accessing fields in Strand workflows

In Strand workflow nodes, the Contact trigger data is available via the data field in the payload. Because the trigger payload wraps the message data inside a data key, the actual message content is accessed as:

code

{{ payload.data }}

For example, to scan the message content in a Surface node:

code

{{ payload.data | tojson }}

To access specific fields from the original message:

code

{{ payload.data.temperature }}
{{ payload.entity.name }}
{{ payload.tags }}

Available trigger fields

Field Type Description
payload.data object The actual message data payload
payload.tags array Tags that matched the trigger
payload.messageId string Contact message ID
payload.timestamp string ISO 8601 timestamp of the trigger
payload.entity.id string Entity resource path
payload.entity.name string Entity display name
payload.contactFlow.flowId string Contact flow ID that triggered
payload.contactFlow.flowName string Contact flow name
payload.contactFlow.executionId string Unique execution ID for this trigger
meta.account_id string Tendrl account ID

Setup

Surface scanning in Contact runs through a Strand workflow that contains a Surface scan node. To set it up:

  1. In Strand, build a workflow with a Surface scan node (see Strand integration) and give the workflow trigger tags (e.g. ["scan"])
  2. In Contact, tag the messages you want screened, using only tags the workflow also has (the workflow's tags must cover every tag on the message)
  3. Matching messages automatically trigger the workflow, which scans the payload

No additional API key configuration is required; the platform handles authentication internally. Your account determines the monthly scan limit.

Scan result variables

When a Strand workflow triggered from Contact includes a Surface scan node, the scan result fields are available for downstream conditions:

Variable Type Description
payload.threat_level string Clean, Informational, Suspicious, or Malicious
payload.score integer 0-100 safety score (higher is safer)
payload.recommended_action string Allow, Review, or Block
payload.safe boolean true when threat_level is not in reject_on
payload.primary_threat string Top matched threat label, or empty string
payload.request_id string Scan correlation ID
payload.iocs array Indicators of compromise

Example branch condition

code

{{ payload.threat_level == "Malicious" }}  ->  block or alert
{{ payload.safe == true }}                 ->  forward to downstream connector

Flow execution details

In the Contact flow detail view, each step shows its result, including the Surface scan node's output: threat level, safety score (higher is safer), recommended action, and IOCs.

Limits

Scans in Contact-triggered workflows count against your Surface monthly scan quota. When the quota is exhausted, payloads are forwarded without scanning; no messages are dropped.