1 Create an API key
In Fortza, open Connect a system and find Generate key. Give your key a recognizable name, such as salesforce-test, then generate it.
Learn how to authenticate, send records to your model, read anomaly results, and connect Salesforce Flow.
GET STARTED
You’ll need a Fortza account, a live model, and an API key from the same organization.
In Fortza, open Connect a system and find Generate key. Give your key a recognizable name, such as salesforce-test, then generate it.
Open Models. Copy a live model’s full name and the field names listed on its card. Use the types and formats from the data you trained it with.
This guide uses fortza-acme-ops-demo. Replace the example model, fields, and values with your own.
| Field | Example type | Example value |
|---|---|---|
recorded_at | Date and time | 2026-10-22T09:15:00Z |
source_id | Text | SRC-104 |
category | Text | standard |
amount | Number | 1250 |
quantity | Number | 12 |
duration_seconds | Number | 48.5 |
Replace YOUR_API_KEY, the model name, and the record fields. Use a key and model from the environment selected above.
curl -X POST "https://api.fortza.ai/api/v1/inference" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model_name": "fortza-acme-ops-demo",
"records": [
{
"recorded_at": "2026-10-22T09:15:00Z",
"source_id": "SRC-104",
"category": "standard",
"amount": 1250,
"quantity": 12,
"duration_seconds": 48.5
},
{
"recorded_at": "2026-10-22T09:16:00Z",
"source_id": "SRC-104",
"category": "standard",
"amount": 98400,
"quantity": 1,
"duration_seconds": 2.1
}
]
}'Run this in Bash (macOS, Linux, or Git Bash on Windows). For a visual option, import the cURL example into Postman and select Send. This multiline command uses Bash syntax, not PowerShell syntax.
READ THE RESULTS
A successful request returns one result per record. Here is an example response; your scores and explanations depend on your model and the records you send.
{
"run_id": "00000000-0000-4000-8000-000000000001",
"record_count": 2,
"anomaly_count": 1,
"not_anomaly_count": 1,
"model_artifact_id": "00000000-0000-4000-8000-000000000002",
"model_name": "fortza-acme-ops-demo",
"applied_threshold_percentile": 90,
"applied_decision_threshold": 0.85,
"results": [
{
"index": 0,
"result": "Not Anomaly",
"anomaly_score": 0.28,
"anomaly_percentile": 0.42,
"evidence": {
"schema_version": 1,
"model": "Fortza Detection Engine",
"reasons": []
}
},
{
"index": 1,
"result": "Anomaly",
"anomaly_score": 0.94,
"anomaly_percentile": 0.99,
"evidence": {
"schema_version": 1,
"model": "Fortza Detection Engine",
"reasons": [
{ "message": "Amount is higher than usual." }
]
}
}
]
}result"Anomaly" or "Not Anomaly". Use this value for the verdict.indexanomaly_percentilenull for models trained without a reference score distribution.anomaly_scoreevidencereasons[].message; a reason can include extra fields, and reasons can be empty. evidence is null if no explanation could be produced. Show reasons only when result is "Anomaly".CONNECT YOUR TOOLS
Send a record after it saves, then write Fortza’s verdict back to Salesforce. Test the flow before activating it, using a Fortza key and model from the selected environment.
In Salesforce Setup, create an External Credential using custom authentication and a named principal. Store your Fortza key as an authentication parameter named ApiKey.
Configure the Authorization header to send Bearer followed by that parameter. Create a Named Credential, Fortza_API, pointing to your environment’s API host and linked to the External Credential. Grant the flow’s running user access to the principal through a permission set.
Keep the key in credentials, rather than a flow variable or formula. Follow Salesforce’s Named Credentials documentation ↗ for the settings available in your org.
| Suggested field | Type | Value to store |
|---|---|---|
Fortza_Is_Anomaly__c | Checkbox | result = "Anomaly" |
Fortza_Percentile__c | Number (6, 4) | anomaly_percentile, 0–1, may be blank |
Fortza_Reason__c | Long Text Area | Reason messages, only when result = "Anomaly" |
Fortza_Scored_At__c | Date/Time | Time of successful scoring |
Map each trained Fortza field to a Salesforce field, preserving its training format. For example, your model’s amount might map to Opportunity Amount. This mapping depends on your own model.
In Flow Builder, create an HTTP Callout action using Fortza_API, method POST, and path /api/v1/inference. Use a one-record version of the request example and the response example to define the action. Read the returned results collection, rather than expecting a top-level verdict.
See Salesforce’s HTTP Callout guide ↗. Check that nested evidence and nullable values work with the generated types; a simplified response mapping or custom action may be needed.
Create a record-triggered flow optimized for Actions and Related Records. Put the HTTP callout on its Run Asynchronously path. After success, write the verdict, percentile, and current time back to the record, plus the reasons when the verdict is an anomaly. Branch on the HTTP status listed in Errors.
Only trigger when relevant input fields change. Updating Fortza’s output fields must not trigger another check. Add a fault path and handle unsuccessful HTTP responses so an admin can investigate. An owner review task for an anomaly is optional.
Check a successful response, missing-field error, invalid key, unavailable model, and empty evidence. Confirm that writing the results back does not cause repeated callouts. Plan batches and monthly row usage before a mass import; never automatically replay a failed batch without checking whether it was processed.
API REFERENCE
/api/v1/inference| Setting | Current contract |
|---|---|
| API host | https://api.fortza.ai |
| Authentication | Authorization: Bearer YOUR_API_KEY |
| Content type | application/json |
| Records | 1–100 objects per request; up to 200 fields per record. |
| Model name | Use the exact live model name from your organization. Required when multiple live customer models exist; otherwise it can be omitted. |
| Required fields | Every record must include all trained field names, with matching spelling and case. Send a value for every field; blank values may be rejected, depending on the model. |
| Usage | Each record counts as one inference row in the organization’s allowance. |
| CSV alternative | Use Check a file in the app for CSVs up to 10,000 rows or 10 MB, subject to your allowance. |
Find your model name and required field names on the Models page in Fortza.
HOW IT WORKS
Fortza compares a record’s score to the model’s stored reference score distribution. Your organization’s threshold percentile determines the cutoff. The current default is 90; an organization admin can adjust it in Settings → Organization.
A lower percentile produces more flags; a higher percentile produces fewer. The setting does not guarantee a particular fraction of future records will be flagged. Use result for the verdict and the returned applied_threshold_percentile and applied_decision_threshold to see the policy used for that run.
TROUBLESHOOTING
Expected API errors return a plain-English message and structured details. Read details.code to identify the problem.
{
"message": "Some records are missing fields required by this model.",
"details": {
"code": "VALIDATION_FAILED",
"missing_columns": ["source_id"],
"record_index": 0,
"errors": [
{ "record_index": 0, "missing_columns": ["source_id"] }
],
"reason": "Some records failed validation."
}
}| Status | Code | What to check |
|---|---|---|
| 400 | VALIDATION_FAILED | Include every required field. Check missing_columns and the zero-based record index. |
| 400 | SCHEMA_MISMATCHINVALID_REQUEST | Send the field names and value formats your model was trained with. |
| 422 | REQUEST_VALIDATION_FAILED | Check the JSON structure, model-name format, 1–100 record limit, and 200-field limit. |
| 401 | API_KEY_MISSINGINVALID_AUTHORIZATION_HEADERINVALID_API_KEY | Send a valid, unrevoked key with the Bearer authorization header. |
| 404 | MODEL_NOT_FOUND | Use the exact name of a live model from the same organization as the API key. |
| 409 | MODEL_NOT_READYARTIFACT_NOT_READY | The organization has no ready live model, or the named model isn’t live yet. Wait for training to finish or make a model live. |
| 400 | MODEL_SELECTION_REQUIRED | Include the full model_name in your request. |
| 403 | INFERENCE_QUOTA_EXCEEDED | Check remaining rows and your plan in the app. |
| 403 | ORGANIZATION_INACTIVEPLAN_CONFIGURATION_REQUIRED | Contact Fortza support about the organization’s status or plan. |
| 503 | ML_SERVICE_UNAVAILABLE | Fortza is temporarily unavailable. Check the request’s outcome before retrying to avoid duplicate runs. |
| Other | Any other code, such as HTTP_500 | Read message, then contact support with the request time and code. |
Send the request time, run ID if available, and error code to our team. Leave out your API key and customer records.