Submitting Results
How to submit activity results to Reten via the API.
After an activity is executed (task completed, message delivered), submit a result to Reten to track the outcome. Results drive the activity lifecycle — submitting a result automatically transitions the parent activity's status.
Creating a Task Result
Use POST /api/activity-results/tasks to submit a result.
Result Statuses
| Status | Description | Activity Transition |
|---|---|---|
PENDING | Received but not fully processed | No change |
COMPLETED | Task fully executed | Activity → COMPLETED |
NOT_EXECUTED | Task was not executed | Activity → FAILED |
CANCELED | Task was canceled | Activity → CANCELED |
TRANSFERRED | Transferred to another operator | Activity → COMPLETED |
All non-PENDING statuses are terminal — no further transitions are allowed.
Result Sources
Results can be linked to activities in two ways:
RETEN_ACTIVITY— Linked viaactivity_id(UUID) orprovider_activity_id(external ID). The parent activity's status is automatically synced.STANDALONE— No matching activity found. A standalone result is created with a commerce reference.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
activity_id | UUID | No | Reten activity ID |
provider_activity_id | string | No | External provider activity ID |
commerce_external_id | string | Yes | External ID of the commerce |
occurred_at | ISO 8601 | Yes | When the result occurred |
status | string | Yes | Result status (see table above) |
external_status | string | No | Provider-specific status string |
hard_override | boolean | No | Skip state transition validation |
raw_payload | object | No | Raw provider payload (stored as-is) |
task_result | object | Yes | Task-specific result details (see below) |
task_result Object
| Field | Type | Required | Description |
|---|---|---|---|
result | string | Yes | Task result type code (e.g., success, not_home) |
comment | string | No | Free text comment |
contact_type | string | No | INBOUND or OUTBOUND |
operator_external_id | string | No | External operator ID |
future_scheduled_at | ISO 8601 | No | Suggested date for a follow-up activity |
payload | object | No | Additional task-specific data |
curl -X POST https://api.reten.ai/api/activity-results/tasks \
-H "Authorization: Bearer <token>" \
-H "x-tenant-id: <tenant-id>" \
-H "Content-Type: application/json" \
-d '{
"provider_activity_id": "ext-123",
"commerce_external_id": "store-001",
"status": "COMPLETED",
"occurred_at": "2025-01-16T14:30:00.000Z",
"task_result": {
"result": "success",
"comment": "Order placed successfully",
"contact_type": "OUTBOUND"
}
}'import axios from 'axios';
const response = await axios.post(
'https://api.reten.ai/api/activity-results/tasks',
{
provider_activity_id: 'ext-123',
commerce_external_id: 'store-001',
status: 'COMPLETED',
occurred_at: '2025-01-16T14:30:00.000Z',
task_result: {
result: 'success',
comment: 'Order placed successfully',
contact_type: 'OUTBOUND',
},
},
{
headers: {
Authorization: 'Bearer <token>',
'x-tenant-id': '<tenant-id>',
},
}
);
const result = response.data;Response 201 Created
{
"id": "770e8400-e29b-41d4-a716-446655440000",
"activityId": "ee0e8400-e29b-41d4-a716-446655440000",
"source": "RETEN_ACTIVITY",
"resultStatus": "COMPLETED",
"occurredAt": "2025-01-16T14:30:00.000Z",
"taskDetails": {
"result": "success",
"comment": "Order placed successfully",
"contactType": "OUTBOUND"
},
"createdAt": "2025-01-16T14:30:05.000Z",
"updatedAt": "2025-01-16T14:30:05.000Z"
}Task Result Types
Results reference a result type code via the task_result.result field from a global catalog of possible outcomes:
| Code | Label |
|---|---|
success | Exito |
not_home | No se encontro |
is_closed | Cerrado |
no_interest | Sin interes |
rescheduled | Reagendado |
wrong_address | Direccion incorrecta |
b2b_purchase | Compra B2B |
no_answer | Sin respuesta |
callback_requested | Solicita devolucion de llamada |
other | Otro |
Each tenant can configure which result types are active and classify them as positive or negative.
Update Guards
Results have two protection layers:
- Temporal guard — Rejects if
occurred_at <= existingResult.updatedAt(always enforced) - State transition guard — Validates status transitions via the status machine (skipped with
hard_override: true)
Contact Direction
| Direction | Description |
|---|---|
INBOUND | Merchant contacted operator/system |
OUTBOUND | Operator/system contacted merchant |
Required Permission
Creating results requires the CREATE_ACTIVITY permission, available to SUPER_ADMIN, ADMIN, and FDE roles.