Skip to main content

Tasks — Create, Update & Cancel

Write tasks from your own systems (CRM, call-center, IoT). Three operations cover the full write lifecycle:

  • POST creates a task or a batch of up to 50.
  • PUT applies a partial update to an existing task.
  • DELETE cancels a task.

Every operation accepts either a single object or a batch wrapper { "items": [...] } (1 to 50 items) and returns a per-item result: one item can succeed while another fails, so a batch is never all-or-nothing once it passes shape validation.

Prerequisites

All endpoints require a valid JWT token, API key, and tenant header. See Authentication. The company (ciaid) and acting user are taken from your credentials — never from the request body.

IDs and dates

IDs are opaque strings (BigInt) — never parse them as numbers. Timestamps are sent and returned without timezone (e.g., "2026-04-04T14:32:00"). Do not append Z or apply UTC conversion. All request fields use snake_case.


Three identifiers in every response

Every successful write returns the three identifiers a task carries:

FieldTypeDescription
seridstringInternal task identifier (BigInt as string).
service_numberstringService number, assigned by the system on creation.
assistance_numberstringAssistance number (links related child tasks to a parent).

The external_id you send is not echoed in the result item — it is your own key. To update or cancel later, you may identify the task by serid, service_number, or external_id (see Identifying a task).


Classification — Motive OR provision+cause+subcause

A task must be classified down two parallel axes. For each axis you choose one of two paths:

AxisPath APath B
Productprocedence + productmotive
Provisionprovision + origin_cause + origin_subcausemotive

When you send motive, the matching provision, cause, and subcause are filled in automatically from the reason's configuration — you don't need to send them. If you send both motive and an explicit provision/cause/subcause, the motive wins (it overwrites the others).

coverage is always optional.

If neither path is satisfied on an axis, the item fails with MOTIVE_OR_CLASSIFICATION_REQUIRED.

Resolution by name

Catalog and geographic fields accept either an id (opaque string) or a name. The system resolves the name to its id (e.g., a motive name to its motive, a country name to its country). When a name can't be resolved, the item either fails (hard) or proceeds with a warning, depending on the field — see Errors.


Create Task

POST/apidev/v1/tasks
PermissionAPICLI_TASKS_CREATE
Rate Limit20 req/min (sliding window)
CacheNone

Creates a task in initial state SA (or ASI when an assignment block is sent). A batch counts as one request against the rate limit.

Request Body — top-level fields

FieldTypeRequiredMaxDescription
contactstringYes200Name of the person requesting the task.
external_idstringNo200Your own identifier for the task.
service_numberstringNo40Service number (numeric string). Omit or 0 to auto-number.
assistance_numberstringNo40Assistance number (numeric string). A value links this task to a parent.
phone_mobilestringNo50Mobile phone of the contact.
phonestringNo50Landline phone of the contact.
prioritystringNo200Priority id or value. Resolved against the company's priority table; omitted → default priority.
detailstringNoFree-text detail of the request.
notesstringNoInternal notes.
scheduled_atstringNo40Scheduled date/time (ISO without timezone).
scheduled_untilstringNo40Scheduled-until date/time (ISO without timezone).
automatebooleanNoWhether the task is automated.
pending_unconfirmedbooleanNoMark as pending / unconfirmed.
computesbooleanNoDefault true. false → does not consume coverage quota.
delay_minutesstringNo20GPS delay tolerance, in whole minutes.
communication_mediumstringNo200Communication template (id or name). Unresolved → warning.
shiftstringNo200Shift (id or name). Unresolved → warning.
telephonist_emailstringNo200Operator email. Defaults to your credentials' user; unresolved → hard fail.
no_notify_mobilebooleanNoSuppress the mobile notification (mainly relevant on update).
assignment_alertstringNo2000Assignment alert text stored on the task.
vehicle_typesstring[]No200 eachRequested mobile types (ids or names). An invalid one fails the item.
classificationobjectYesSee Classification rule and classification fields.
originobjectYesOrigin address. country + department + street are required. See geo fields.
destinationobjectConditionalRequired or optional depending on the product (e.g., tow / move products require it).
reserveobjectNoReserve a resource without assigning. See reserve fields.
assignmentobjectNoAssign the task on creation (state ASI; mobile notification only when notify_mobile is true). See assignment fields.
accountobjectYesRequesting account. Auto-created from the origin address if it doesn't exist. See account fields.
dynamic_fieldsarrayConditionalOAV dynamic fields. Required when the product has mandatory OAV fields. See dynamic fields.
attachmentsarrayNoAttachments by URL — stored as an external link (the URL is saved as-is to open from web/app; not downloaded). See attachment fields.
loadobjectNoCargo data (weight, volume, packages, handling requirements). Gated by the product's cargo profile. See load.

classification fields

FieldTypeRequiredDescription
procedencestringConditionalOrigin/source (id or name). Required with product unless motive is sent.
productstringConditionalProduct (id, line, or name). Requires procedence.
coveragestringNoCoverage (id or name).
motivestringConditionalReason (id or name). Fills in provision/cause/subcause automatically.
provisionstringConditionalProvision (id or name). Required with the two causes unless motive is sent.
origin_causestringConditionalOrigin cause (id or name).
origin_subcausestringConditionalOrigin subcause (id or name).
destination_causestringNoDestination cause (id or name).
destination_subcausestringNoDestination subcause (id or name).

origin / destination fields

origin and destination share the same shape. Geographic and special-place fields accept an id or a name.

FieldTypeRequired (origin)Description
countrystringYesCountry (id or name).
departmentstringYesDepartment / province (id or name).
citystringNoCity (id or name).
zonestringNoZone (id or name). Unresolved → warning.
streetstringYesStreet. Required in origin (unless inherited from the account).
cornerstringNoCross street. Max 500.
corner2stringNoSecond cross street. Max 500.
door_numberstringNoDoor number (text — accepts "1234", "S/N", "12-A"). Max 50.
apartmentstringNoApartment / suite. Max 50.
facingstringNoFacing reference. Max 200.
special_placestringNoSpecial place (id or name). Unresolved → warning.
latstringNoLatitude. 0 or omitted → geocoding fallback.
lngstringNoLongitude. 0 or omitted → geocoding fallback.
Geocoding fallback

When lat/lng are missing or 0, the task is located using the company's own geo infrastructure (account georeference → address geocoding → geographic centroid). If nothing resolves, the task is created without coordinates (it does not fail) and a warning is returned.

reserve fields

Reserving a resource keeps the task in state SA (it does not assign it).

FieldTypeDescription
personnelstringPersonnel to reserve (id or name). Unresolved → warning.
providerstringProvider to reserve (id or name). Unresolved → hard fail.
mobilestringMobile to reserve (id or name). Unresolved → hard fail.
user_emailstringUser to reserve. Unresolved → hard fail.
notify_mobilebooleanNotify the mobile when reserving (default: no). If true, the reservation notification flow runs.

assignment fields

Assigning moves the task to state ASI and sets the assignment date. The mobile is notified only when notify_mobile is true (by default it does not notify). Assign by mobile or by provider (they are alternatives).

FieldTypeDescription
assign_vehiclestringMobile to assign (id or name). Resolves the driver's active work shift. Unresolved → hard fail.
assign_driverstringDriver to assign (id or name). Unresolved → hard fail.
assign_providerstringProvider to assign (id or name), as an alternative to a mobile. Unresolved → hard fail.
assign_templatestringCommunication template for the assignment. Defaults to the resource's template; a template that doesn't belong to the resource → warning + default is used.
notify_mobilebooleanNotify the mobile on assignment (default: no).

account fields

The requesting account is mandatory. If external_code doesn't match an existing account and name is provided, the account is auto-created with the task's origin address.

FieldTypeDescription
external_codestringResolves the account by external code. Max 200.
namestringAccount name (used on auto-create). Max 200.
update_if_existsbooleanIf true, updates non-empty fields of the existing account.
documentstringDocument number (search key).
phonestringPhone (search key).
mobilestringMobile (search key).
emailstringEmail (search key).
notesstringAccount notes. Max 2000.
addressobjectAccount address. Overrides the inherited origin address. Subset of origin: street, corner, door_number, country, department, city, lat, lng.

dynamic_fields (OAV)

Dynamic fields (OAV) are defined per product. Their requirement and type come from the product's OAV definition:

  • If the product has mandatory OAV fields, dynamic_fields must include them with a non-empty value, or the item fails with OAV_REQUIRED_MISSING.
  • Each value is validated against the field's type (number, true/false, date, list option). A wrong format → OAV_TYPE_MISMATCH; a value outside the allowed list → OAV_LIST_VALUE_INVALID.
  • A label that doesn't match any field on the product is ignored with a warning (it does not fail the item).
FieldTypeRequiredDescription
labelstringYesField label. Matched case-insensitively against the product's OAV field names.
valuestringNoValue, typed according to the field. Max 4000.

attachments fields

FieldTypeRequiredDescription
namestringNoDisplay file name. Max 300.
urlstringYesHTTPS URL saved as-is as an external link (opened from web/app; not downloaded). Max 2000.
notesstringNoAttachment notes. Max 2000.
A failed link doesn't fail the task

Each attachment is registered as an external link. If the link can't be registered, the task is still created and the attachment is reported in warnings[].

load (cargo data)

Cargo data for the task's shipment: weight, volume, package count, and special handling requirements. Every field is gated by the product's cargo profile — each product declares which cargo dimensions it handles.

FieldTypeDescription
weightKgnumberTotal weight in kilograms (≥ 0).
volumeM3numberTotal volume in cubic meters (≥ 0).
packagesintegerNumber of packages (≥ 0).
requiresColdbooleanNeeds refrigerated handling.
requiresFragilebooleanContains fragile items.
requiresHeavybooleanNeeds heavy-load handling.
Only the dimensions the product handles

If you send a load dimension the product doesn't handle, the item fails with LOAD_DIMENSION_NOT_SUPPORTED. Which dimensions a product handles is part of its configuration. On update, the product is read from the existing task (never from the body). Omit a dimension to leave it unchanged; send null to clear it.

Code Example

curl -s -X POST "https://$TENANT/apidev/v1/tasks" \
-H "Authorization: Bearer $TOKEN" \
-H "X-API-Key: $APIKEY" \
-H "tenant: $TENANT" \
-H "Content-Type: application/json" \
-d '{
"contact": "Maria Gomez",
"external_id": "CRM-90021",
"phone_mobile": "+59899123456",
"classification": {
"procedence": "Call Center",
"product": "Roadside Assistance"
},
"origin": {
"country": "Uruguay",
"department": "Montevideo",
"city": "Montevideo",
"street": "Av. 18 de Julio",
"door_number": "1234"
},
"account": {
"external_code": "ACC-5587",
"name": "Maria Gomez"
},
"dynamic_fields": [
{ "label": "Vehicle Plate", "value": "ABC1234" }
]
}'

Batch Example

Send { "items": [...] } with up to 50 tasks. The response keeps the same order via each item's index.

curl -s -X POST "https://$TENANT/apidev/v1/tasks" \
-H "Authorization: Bearer $TOKEN" \
-H "X-API-Key: $APIKEY" \
-H "tenant: $TENANT" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "contact": "Maria Gomez", "classification": { "motive": "Breakdown" },
"origin": { "country": "Uruguay", "department": "Montevideo", "street": "Av. 18 de Julio" },
"account": { "external_code": "ACC-5587", "name": "Maria Gomez" } },
{ "contact": "Juan Perez", "classification": { "procedence": "Call Center", "product": "Tow" },
"origin": { "country": "Uruguay", "department": "Canelones", "street": "Ruta 8 km 25" },
"account": { "external_code": "ACC-9912", "name": "Juan Perez" } }
]
}'

Example Response

A successful single create returns data as an array of one item. HTTP 200 when at least one item succeeds; meta.failed counts the rest.

{
"success": true,
"meta": { "created": 2, "failed": 1 },
"data": [
{
"index": 0,
"success": true,
"serid": "728193045120004001",
"service_number": "103878",
"assistance_number": "55012",
"status": "SA",
"warnings": []
},
{
"index": 1,
"success": true,
"serid": "728193045120004002",
"service_number": "103879",
"assistance_number": "55013",
"status": "SA",
"warnings": [
{
"index": 1,
"field": "origin.zone",
"code": "GEO_ZONE_IGNORED",
"message": "We couldn't find the zone you provided; the task was created without a zone.",
"hint": "Check the valid zones in the geographic catalogs."
}
]
},
{
"index": 2,
"success": false,
"errors": [
{
"index": 2,
"field": "classification.product",
"code": "PRODUCT_NOT_FOUND",
"message": "We couldn't find the product in the origin you provided.",
"hint": "Check GET /apidev/v1/catalogs/origins/{originId}/products."
}
]
}
]
}

Result item fields

FieldTypePresenceDescription
indexnumberAlways0-based position in the batch (0 for a single object).
successbooleanAlwaysWhether this item succeeded.
seridstringIf successInternal task id.
service_numberstringIf successService number.
assistance_numberstringIf successAssistance number.
statusstringIf successBehavior status. Create: SA (or ASI if assigned on creation).
warningsarrayIf successNon-blocking advisories. [] when none. See Issue shape.
errorsarrayIf !successPer-item errors. See Issue shape.

meta carries created + failed for create, updated + failed for update, and cancelled + failed for cancel.


Update Task

PUT/apidev/v1/tasks
PermissionAPICLI_TASKS_UPDATE
Rate Limit20 req/min (sliding window)
CacheNone

Applies a partial update: only the fields you send are changed; omitted fields keep their current value. Accepts a single object or { "items": [...] }. See Partial Updates for the general pattern.

Identifying a task

Send at least one of these. They are resolved in this order until one matches a task in your company:

FieldTypeDescription
seridstringPreferred identity.
service_numberstringSecond fallback.
external_idstringThird fallback (your own key).

If none resolves, the item fails with TASK_NOT_FOUND. A task already in state FIN or CAN fails with TASK_ALREADY_TERMINAL.

Request Body

All Create Task business fields are accepted (all optional). Notes specific to update:

  • Only the fields present in the body are applied.
  • For OAV, only the dynamic_fields you send are updated (matched by label); fields you don't mention are left as they are. The full set of mandatory OAV fields is not re-checked on update — only the types of the ones you send are validated.
  • service_number = 0 / auto-numbering is not accepted (the task already exists).
  • assignment_alert and no_notify_mobile apply on update.

Code Example

curl -s -X PUT "https://$TENANT/apidev/v1/tasks" \
-H "Authorization: Bearer $TOKEN" \
-H "X-API-Key: $APIKEY" \
-H "tenant: $TENANT" \
-H "Content-Type: application/json" \
-d '{
"external_id": "CRM-90021",
"phone_mobile": "+59899765432",
"detail": "Customer added a second contact number",
"dynamic_fields": [
{ "label": "Vehicle Plate", "value": "XYZ9876" }
]
}'

Example Response

{
"success": true,
"meta": { "updated": 1, "failed": 0 },
"data": [
{
"index": 0,
"success": true,
"serid": "728193045120004001",
"service_number": "103878",
"assistance_number": "55012",
"status": "SA",
"warnings": []
}
]
}

The result item shape is identical to create. On update, status reflects the task's current state after the change.


Cancel Task

DELETE/apidev/v1/tasks
PermissionAPICLI_TASKS_CANCEL
Rate Limit20 req/min (sliding window)
CacheNone

Cancels a task (state CAN) with a reason. If the task was assigned, the mobile is notified. Accepts a single object or { "items": [...] }.

Request Body

FieldTypeRequiredDescription
seridstringOne of threeIdentity (preferred).
service_numberstringOne of threeIdentity (second fallback).
external_idstringOne of threeIdentity (third fallback).
reasonstringYesCancellation reason. Must not be empty. Max 2000.

Identity is resolved in the order seridservice_numberexternal_id. A task already in state FIN or CAN fails with TASK_ALREADY_TERMINAL.

Code Example

curl -s -X DELETE "https://$TENANT/apidev/v1/tasks" \
-H "Authorization: Bearer $TOKEN" \
-H "X-API-Key: $APIKEY" \
-H "tenant: $TENANT" \
-H "Content-Type: application/json" \
-d '{
"external_id": "CRM-90021",
"reason": "Customer cancelled the request"
}'

Example Response

{
"success": true,
"meta": { "cancelled": 1, "failed": 0 },
"data": [
{
"index": 0,
"success": true,
"serid": "728193045120004001",
"service_number": "103878",
"assistance_number": "55012",
"status": "CAN"
}
]
}

The cancel result item carries index, success, the three identifiers, and status (CAN on success) or errors[] on failure.


Errors

Two validation layers

The API validates in two distinct moments. Don't confuse them:

LayerDetectsResponse
ShapeUnknown field, wrong type, missing required field, invalid length, empty batch, batch over 50.400 VALIDATION_ERROR with no data — the body is not processed and no item is created.
BusinessCatalog not resolved, OAV mandatory/type/list, coverage quota, resource to assign/reserve, identity not found.Per item in data[].errors. HTTP 200 with meta.failed; 400 only if all items fail (the failing data + meta are still included).

Issue shape

Each entry in errors[] and warnings[] has the same shape:

FieldTypeDescription
indexnumber0-based position in the batch.
fieldstringDot-path to the request field (e.g., classification.product, origin.country, dynamic_fields.<label>).
codestringStable error/warning code (see below).
messagestringHuman-readable explanation.
hintstringConcrete next step (which catalog to check / which field to fix).

Errors accumulate — a single item can return several at once.

Per-item error codes (hard fail — block the item)

CodeTypical fieldDescription
CONTACT_REQUIREDcontactMissing the requester's name.
ORIGIN_COUNTRY_REQUIREDorigin.countryMissing the origin country.
ORIGIN_DEPARTMENT_REQUIREDorigin.departmentMissing the origin department / province.
STREET_REQUIREDorigin.streetMissing the origin street.
MOTIVE_OR_CLASSIFICATION_REQUIREDclassificationMissing the motive, or the provision with its cause and subcause.
PROCEDENCE_NOT_FOUNDclassification.procedenceThe origin/source wasn't found.
PRODUCT_NOT_FOUNDclassification.productThe product wasn't found in the given origin.
COVERAGE_NOT_FOUNDclassification.coverageThe coverage wasn't found.
MOTIVE_NOT_FOUNDclassification.motiveThe motive wasn't found.
PROVISION_NOT_FOUNDclassification.provisionThe provision wasn't found.
CAUSE_NOT_FOUNDclassification.origin_cause / destination_causeThe cause wasn't found.
SUBCAUSE_NOT_FOUNDclassification.origin_subcause / destination_subcauseThe subcause wasn't found.
GEO_NOT_FOUNDorigin.city / destination.*The geographic location wasn't found.
VEHICLE_TYPE_INVALIDvehicle_typesOne of the requested mobile types doesn't exist.
OAV_REQUIRED_MISSINGdynamic_fields.<label>A mandatory dynamic field for this product is missing.
OAV_TYPE_MISMATCHdynamic_fields.<label>The dynamic field value doesn't have the expected format.
OAV_LIST_VALUE_INVALIDdynamic_fields.<label>The value isn't among the field's allowed options.
ACCOUNT_NOT_RESOLVEDaccount.external_codeThe account couldn't be resolved or created.
COVERAGE_QUOTA_EXCEEDEDclassification.coverageThe coverage ran out of service quota.
RESERVE_PROVIDER_INVALIDreserve.providerThe provider to reserve wasn't found.
RESERVE_MOBILE_INVALIDreserve.mobileThe mobile to reserve wasn't found.
RESERVE_USER_INVALIDreserve.user_email / telephonist_emailThe user wasn't found.
ASSIGN_VEHICLE_INVALIDassignment.assign_vehicleThe mobile to assign wasn't found.
ASSIGN_DRIVER_INVALIDassignment.assign_driverThe driver to assign wasn't found.
ASSIGN_PROVIDER_INVALIDassignment.assign_providerThe provider to assign wasn't found.
ASSIGN_TEMPLATE_INVALIDassignment.assign_templateThe communication template wasn't found.
TASK_NOT_FOUND(identity)No task matched serid / service_number / external_id.
TASK_ALREADY_TERMINAL(identity)The task is already finished or cancelled and can't be changed.
LOAD_DIMENSION_NOT_SUPPORTEDload.<dimension>The task's product doesn't handle this cargo dimension (weight/volume/packages/cold/fragile/heavy).
LOAD_VALUE_INVALIDload.<dimension>The cargo value has the wrong format (weight/volume must be numbers ≥ 0; packages a whole number ≥ 0).

Warning codes (non-blocking — go to warnings[])

CodeTypical fieldMeaning
GEO_ZONE_IGNOREDorigin.zoneThe zone wasn't found; the task was created without it.
SPECIAL_PLACE_IGNOREDorigin.special_placeThe special place wasn't found; ignored.
RESERVE_PERSONNEL_IGNOREDreserve.personnelThe personnel to reserve wasn't found; ignored.
COMM_MEDIUM_IGNOREDcommunication_mediumThe communication template wasn't found; ignored.
SHIFT_IGNOREDshiftThe shift wasn't found; ignored.
ATTACHMENT_LINK_FAILEDattachmentsThe attachment link couldn't be registered.
OAV_FIELD_UNKNOWN_IGNOREDdynamic_fields.<label>The label doesn't match a field on the product; ignored.
ASSIGN_TEMPLATE_IGNOREDassignment.assign_templateThe template doesn't belong to the resource; the resource default was used.

Transport / shape / auth errors (full-failure envelope)

HTTPCodeDescription
400VALIDATION_ERRORShape validation failed (unknown field, wrong type, missing required, length, batch empty or over 50). Detail in error.details[].
401UNAUTHORIZED / TOKEN_EXPIREDMissing, invalid, or expired tenant / Authorization / X-API-Key.
403FORBIDDENThe API key lacks APICLI_TASKS_CREATE / APICLI_TASKS_UPDATE / APICLI_TASKS_CANCEL.
404NOT_FOUNDThe task doesn't exist (single-object update/cancel).
429RATE_LIMITEDExceeded 20 req/min.
500INTERNAL_ERRORUnexpected server error.
POST always creates

There is no upsert on this rail. Re-sending a POST with the same external_id creates a second task. To change an existing task, use PUT.