When a machine breaches, or is forecast to, open a Salesforce Case so field service can dispatch a technician with the reading already in hand.
| Salesforce Case field | Source | Example |
|---|---|---|
Subject | trigger name + machine | Bearing temp critical on mint_7f3a91c4 |
Description | field, value, threshold, timestamp, recommended action | multi-line, see payload |
Priority | fixed per trigger | "High" |
Status | fixed | "New" |
Origin | fixed | "Forge Automation" |
Type | fixed | "Field Service" |
Reason | fixed | "Equipment Failure" |
AssetId | your Salesforce Asset record for the machine | 02i5f000000XyZaAAK |
AccountId | the customer account that owns the machine | 0015f00000LmNoPQAZ |
INVALID_OR_NULL_FOR_RESTRICTED_PICKLIST. Add Forge Automation to the Case Origin picklist before the first run, or use a value your org already has.
In Salesforce: Setup → App Manager → New Connected App. Enable OAuth settings, set the callback URL to anything valid if you are using the JWT or client-credentials flow, and select the api and refresh_token scopes. Note the consumer key and secret.
For a server-to-server integration, the client-credentials flow is the simplest. Under the Connected App's policies, set Run As to an integration user with permission to create Cases.
curl -sS -X POST https://YOUR_DOMAIN.my.salesforce.com/services/oauth2/token \ -d "grant_type=client_credentials" \ -d "client_id=YOUR_CONSUMER_KEY" \ -d "client_secret=YOUR_CONSUMER_SECRET"
The response carries access_token and instance_url. You need both.
curl -sS -X POST https://forge.foundrynet.io/v1/tools \
-H "Authorization: Bearer $FORGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Salesforce Case (field service, high)",
"description": "Open a high-priority field service Case for a machine breach",
"url": "https://YOUR_DOMAIN.my.salesforce.com/services/data/v61.0/sobjects/Case",
"method": "POST",
"auth_type": "bearer",
"auth_secret": "YOUR_SALESFORCE_ACCESS_TOKEN",
"payload_template": {
"Subject": "{{trigger_name}} on {{machine_id}}",
"Description": "Forge detected a machine condition requiring field service.\n\nMachine: {{machine_id}}\nOEM / model: {{oem}} {{model}}\nSite: {{site}}\nCanonical field: {{field}}\nActual value: {{value}}\nThreshold: {{threshold}}\nDetected at: {{timestamp}}\n\nRecommended action: dispatch for bearing inspection and lubrication service. Bring a replacement bearing set for this model. Confirm the reading at the controller before teardown.\n\nForge trigger: {{trigger_name}} ({{trigger_id}})",
"Priority": "High",
"Status": "New",
"Origin": "Forge Automation",
"Type": "Field Service",
"Reason": "Equipment Failure",
"AssetId": "YOUR_ASSET_ID",
"AccountId": "YOUR_ACCOUNT_ID"
}
}'
In plain terms: when bearing temperature crosses 95 degrees, open a field service Case with the machine ID, the reading, and the recommended action.
curl -sS -X POST https://forge.foundrynet.io/v1/triggers \
-H "Authorization: Bearer $FORGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Bearing temp critical",
"machine_id": "YOUR_MACHINE_ID",
"condition": { "field": "sensor_readings.bearing_temp", "op": "gt", "value": 95 },
"actions": [ { "tool_id": "TOOL_ID_FROM_STEP_2" } ],
"enabled": true
}'
To dispatch on a forecast instead of an actual, use a predicted_breach condition. That path delivers to a plain webhook_url with a fixed body and no tool auth, so it needs a small forwarding endpoint. The ServiceNow template documents that payload in full; the shim logic is identical, only the destination changes.
Salesforce access tokens expire. Forge stores the secret encrypted and cannot refresh it for you, so rotate it on a schedule with PUT /v1/tools/{id}. A daily cron is enough for most session policies.
#!/usr/bin/env bash
# rotate-salesforce-token.sh — run daily
TOKEN=$(curl -sS -X POST https://YOUR_DOMAIN.my.salesforce.com/services/oauth2/token \
-d "grant_type=client_credentials" \
-d "client_id=$SF_CLIENT_ID" \
-d "client_secret=$SF_CLIENT_SECRET" | python3 -c "import sys,json;print(json.load(sys.stdin)['access_token'])")
curl -sS -X PUT "https://forge.foundrynet.io/v1/tools/$FORGE_TOOL_ID" \
-H "Authorization: Bearer $FORGE_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"auth_secret\": \"$TOKEN\"}"
401 INVALID_SESSION_ID and Forge records it on the execution log rather than retrying indefinitely. Check /v1/triggers/{id}/executions when Cases stop appearing.
POST /services/data/v61.0/sobjects/Case
Authorization: Bearer 00D5f000008xYzA!AQEAQ...
Content-Type: application/json
X-FoundryNet-Trigger-Id: 7b1e4c92-3d05-4a61-9f28-c4a70d1b8e33
{
"Subject": "Bearing temp critical on mint_7f3a91c4",
"Description": "Forge detected a machine condition requiring field service.\n\nMachine: mint_7f3a91c4\nOEM / model: Haas VF-2\nSite: Plant 3 / Cell B\nCanonical field: sensor_readings.bearing_temp\nActual value: 97.2\nThreshold: 95\nDetected at: 2026-07-28T18:04:11.882714+00:00\n\nRecommended action: dispatch for bearing inspection and lubrication service...",
"Priority": "High",
"Status": "New",
"Origin": "Forge Automation",
"Type": "Field Service",
"Reason": "Equipment Failure",
"AssetId": "02i5f000000XyZaAAK",
"AccountId": "0015f00000LmNoPQAZ"
}
Salesforce responds with the new record:
{ "id": "5005f00000BqRstAAF", "success": true, "errors": [] }