SAT module guide — Technical assistance
Microservice: XDPeople.Soba.WebAPI (Core API) + Invoice API (issuing)
Authentication: Bearer token (JWT) and tenant context — see Combined Login
Management endpoints live under https://api.xdsoba.com/gateway/... and require Authorization: Bearer {token}.
Introduction
The SAT module (Technical Assistance Service) covers the full assistance cycle in Soba: catalogues, assistance contracts, customer equipment, service orders, technical interventions, close, invoicing and RMA (returns), plus dedicated reports.
Flow overview
| Step | What | Guide page |
|---|---|---|
| 1 | Prepare catalogues (once per tenant) | Catalogues |
| 1.5 | SAT module configuration | Configuration |
| 2 | Assistance contracts (optional) | Contracts |
| 3 | Register customer equipment | Equipment |
| 4 | Open, close and reopen the service order | Service order |
| 4.1 | Billable lines (details) | Service order |
| 5 | Register interventions | Interventions |
| 5.1 | Link interventions to the service order | Linking |
| 6 | Preview and issue invoice | Invoicing |
| — | Returns (parallel flow) | RMA |
| — | Link RMA to the service order | Linking |
Quick resource map
| Area | Typical prefix |
|---|---|
| Equipment | /gateway/equipment-type, equipment-brand, equipment-model, equipment |
| Order | /gateway/service-order-catalog, service-order-state, service-order, sat-config |
| Intervention | /gateway/intervention-config, intervention |
| Contract | /gateway/entity-contract-group, entity-contract-type, entity-contract |
| Invoicing | /gateway/service-order/invoice/preview, /gateway/intervention/invoice/preview, /gateway/invoice/invoices |
| RMA | /gateway/return-type, return-reason, rma |
Link interventions and RMA to the Service Order
The order must exist first: linking always uses the GUID returned by POST /gateway/service-order (or obtained from GET /gateway/service-order/{series}/{number}). You cannot create the order and its interventions in the same request — the order payload does not accept an interventions list.
Step 5.1 — Link interventions to the Service Order
Option A — link when creating the intervention
POST /gateway/intervention
Content-Type: application/json
Authorization: Bearer {token}
{
"type": "DIAG",
"status": "CURSO",
"description": "Initial PSU diagnosis",
"userId": 1,
"entityKeyId": "C0001",
"equipmentId": 123,
"serviceOrderGuid": "ORDER-GUID",
"concluded": true,
"discountTime": 1.5,
"discountTimeItemId": "MO-HORA",
"details": [
{
"itemKeyId": "FONTE-19V",
"itemDescription": "19V / 65W power supply",
"quantity": 1,
"retailPrice": 45.00
}
]
}
The API validates that the order exists and copies series and number from it, later returned as serviceOrderSeries and serviceOrderNumber. If the order does not exist, it returns 404 ServiceOrder.NotFound.
If serviceOrderGuid is empty or not a valid GUID, the field is silently ignored and the intervention stays without an order — there is no error. Always confirm with the order GET.
There is no inheritance from the order: entityKeyId, equipmentId and entityContractId must be sent on the intervention payload, even if the order already has them.
Option B — associate an existing intervention
POST /gateway/service-order/ORDER-GUID/interventions/46
Authorization: Bearer {token}
Response: 204 No Content, no body. To link several interventions to the same order, repeat the call — one per intervention; there is no batch endpoint:
POST /gateway/service-order/ORDER-GUID/interventions/46
Authorization: Bearer {token}
POST /gateway/service-order/ORDER-GUID/interventions/47
Authorization: Bearer {token}
POST /gateway/service-order/ORDER-GUID/interventions/48
Authorization: Bearer {token}
| Situation | Response |
|---|---|
| Linked successfully | 204 |
| Already linked to this same order | 204 (idempotent) |
| Already linked to another order | 409 Intervention.AlreadyLinked |
| Unknown order | 404 ServiceOrder.NotFound |
| Unknown intervention | 404 Intervention.NotFound |
List interventions on an order: GET /gateway/service-order/{guid}, property interventions[]. There is no GET /service-order/{guid}/interventions, and GET /gateway/intervention does not filter by order.
Remove an intervention from the order
DELETE /gateway/service-order/ORDER-GUID/interventions/46
Authorization: Bearer {token}
This endpoint does not unlink the intervention from the order: it deletes it (logical delete). There is no “unlink” that returns the intervention to a standalone state. If the intervention does not belong to that order, it returns 409 Intervention.NotLinkedToServiceOrder.
Edit after linking
Once linked, the intervention can only be edited “through” the order. PUT /gateway/intervention/{id} returns 409 Intervention.CannotEditLinkedToServiceOrder — unless the request body repeats the same serviceOrderGuid, which signals that the edit comes from the order context (the same exception applies to already invoiced interventions, which otherwise return 409 Intervention.CannotEditInvoiced).
serviceOrderGuid is ignored on update: it does not move the intervention to another order. To change the link, use the association endpoint, and only if the intervention is not already linked to another order.
RMA — link to a service order
Here too the order must exist first, because linking uses its GUID. There are two approaches, and the choice has consequences.
Option A — declare the order on the RMA itself
POST /gateway/rma
Content-Type: application/json
Authorization: Bearer {token}
{
"rmaId": "RMA-2026-001",
"rmaType": 1,
"equipmentId": 123,
"quantity": 1,
"returnType": "Warranty",
"returnReason": "Manufacturing defect",
"serviceOrderGuid": "ORDER-GUID"
}
The same works on PUT /gateway/rma/{guid}, so you can link an existing RMA afterwards.
Unlike interventions, the RMA serviceOrderGuid is not validated: a wrong GUID is accepted and the RMA becomes orphaned — it will not appear on the order detail and there is no error. Always confirm with GET /gateway/service-order/{guid}.
Option B — send RMAs in the order payload
PUT /gateway/service-order/ORDER-GUID
Content-Type: application/json
Authorization: Bearer {token}
{
"status": "RECEB",
"priority": "URG",
"assistanceTypeKeyId": "REP",
"rmaList": [
{ "rmaId": "RMA-2026-001", "rmaType": 1, "equipmentId": 123, "quantity": 1 },
{ "rmaId": "RMA-2026-002", "rmaType": 2, "componentKeyId": "PSU19V", "quantity": 1 }
]
}
The API fills serviceOrderGuid and serviceOrderDesignation on each RMA from the order, and generates a GUID for those that do not bring one.
On PUT, rmaList is a full destructive replacement: existing RMAs on the order are physically deleted from the database and recreated from the submitted list — with new GUIDs if you do not include them. Omitting the field (null) keeps current RMAs; sending [] deletes them all.
This path does not apply RMA resource validations: duplicate rmaId, existence of returnType/returnReason, and the requirement of equipmentId (Equipment type) or componentKeyId (Component type) are only checked on POST/PUT /gateway/rma. For integration payloads, prefer Option A.
If the order is closed, PUT /gateway/service-order/{guid} returns 409 ServiceOrder.CannotEditClosed. In that case, link or change the RMA via PUT /gateway/rma/{guid}.
Unlink an RMA from the order: PUT /gateway/rma/{guid} with an empty serviceOrderGuid, or remove it from the order rmaList (remember that this deletes and recreates the others).
List RMAs on an order: GET /gateway/service-order/{guid}, property rmaList[]. There is no GET /service-order/{guid}/rmas.
Linking summary
| Intervention → SO | RMA → SO | |
|---|---|---|
| Order must exist first | Yes | Yes |
| Link field | serviceOrderGuid (optional) | serviceOrderGuid (optional) |
| Order existence validated | Yes (404 if missing) | No (orphaned silently) |
| Dedicated endpoint | POST /gateway/service-order/{guid}/interventions/{id} | None |
| Via order payload | Not supported | rmaList (full replacement on PUT) |
| Change order on resource PUT | No (field ignored) | Yes |
| Query | GET /service-order/{guid} → interventions[] | GET /service-order/{guid} → rmaList[] |
| Undo the link | Only by deleting the intervention | Empty serviceOrderGuid on RMA PUT |
SAT reports
The module includes four dedicated reports (available in the product UI and through the Standard Reports API):
| Report | Contents | Identifier |
|---|---|---|
| Entity contracts | Contracts, hours ceiling, hours used and hours available (now calculated) | D3B0946B-409F-477C-855D-A05BC517B186 |
| Equipment | Equipment fleet by customer, brand, model and warranty | 367DD5A9-D7A4-4722-906F-3A88EDFC616E |
| Interventions | Technical work by period, technician, customer and contract | BE27808C-123D-4699-9107-666D255530DE |
| Service orders | Orders by status, priority, assistance type and equipment | B2D7C4E8-1A3F-4B9C-8D6E-5F2A7C3B1D9E |
Use GET /gateway/reports/{reportId}/info and GET /gateway/reports/{reportId}?jsonParameters=… as described in the Report API guide.
Common errors
| HTTP | Situation | How to fix |
|---|---|---|
400 | Required field missing (status, priority, assistanceTypeKeyId…) | The message indicates the first missing field |
400 | Catalogue keyId does not exist | Create the catalogue entry first (Step 1) |
400 | ExtraOnlyRequiresContract | ExtraOnly requires an intervention with a linked contract |
400 | Invoice.Details.OnlyComments | The document needs at least one valued line (details) |
400 | ServiceOrderInvoice.NothingToInvoice / InterventionInvoice.NothingToInvoice | Add details and/or valued hours/km |
400 | ServiceOrder.InvalidDetailItemKeyId / Intervention.InvalidDetailItemKeyId | Send itemKeyId on lines with quantity > 0 |
400 | ServiceOrder.ResponsibleUserRequired | Send responsibleUserId > 0 when isEmployeeFillObligatory is on |
400 | SatLineNotFromDeclaredOrigin | The submitted line does not belong to the service order/intervention declared on the header |
404 | Unknown GUID/id | Confirm with the list GET |
404 | ServiceOrder.NotFound / Intervention.NotFound | Confirm the order GUID or intervention id |
404 | ServiceOrder.ItemNotFound / Intervention.ItemNotFound | Create the item in the item catalogue first |
404 | ServiceOrderConfiguration.NotFound | Treat as defaults, or PUT /gateway/sat-config |
409 | Close with open interventions | Use close-preview and send concludeOpenInterventions: true |
409 | ServiceOrder.CannotRemoveInvoicedDetail | Do not drop invoiced lines from details on PUT |
409 | Intervention.AlreadyLinked | The intervention is already linked to another order |
409 | Intervention.CannotEditLinkedToServiceOrder | Repeat the same serviceOrderGuid on PUT (edit from order context) |
409 | Intervention.NotLinkedToServiceOrder | DELETE only removes interventions that belong to that order |
409 | ServiceOrder.CannotEditClosed | Reopen the order, or change the RMA via PUT /gateway/rma/{guid} |
409 | Duplicate keyId / rmaId | Choose another key or look up the existing one |