Overview
Mobile Field Report (MFR) is a field-service platform for planning, dispatching and documenting jobs (service requests), appointments, service objects (assets), customers, items, invoices and more. Everything you can do in the MFR portal is available through this API.
The API is an OData v3 service (JSON light). Every entity set supports the standard OData verbs (GET, POST, PUT, PATCH/MERGE, DELETE), OData query options and $links for relations, plus a few actions and a handful of plain REST endpoints for binary uploads/downloads.
| Base URL | https://portal.mobilefieldreport.com/odata (written as {{serverURL}}) |
| Host for non-OData endpoints | https://portal.mobilefieldreport.com (written as {{baseURL}}) |
| Metadata document | GET {{serverURL}}/$metadata |
| Protocol | OData v3, JSON light (application/json;odata=minimalmetadata) |
| Authentication | HTTP Basic (e-mail address / password of an API user) |
Conventions
Keys and numbers
- All keys are 64-bit integers. In URLs they must carry the
L suffix: {{serverURL}}/ServiceRequests(123L). - In JSON responses
Edm.Int64 and Edm.Decimal values are serialized as strings ("Id": "123", "Price": "12.50") – that is how OData v3 JSON light avoids precision loss. In request bodies you may send them as numbers or strings. - Dates are ISO 8601 in UTC (
2026-08-25T08:00:00Z). - Enumerations are transported as strings (e.g.
"State": "Released", "Type": "Material"). The allowed values are listed in each entity description.
Query options
| Option | Example | Notes |
|---|
$filter | $filter=State eq 'Released' and DateModified gt datetime'2026-01-01T00:00:00Z' | OData v3 filter syntax. Some sets have mandatory filters (Comments, Attachments) or special filters (QuickSearch, IsTemplate, ContactId). |
$expand | $expand=Customer,ServiceObjects/Location,Appointments/Contacts | Loads navigation properties in the same request. Max depth 5. Navigations are never included unless expanded. |
$select | $select=Id,Name,State | Restricts the returned properties (not available on Attachments, Comments, Steps, Items). |
$orderby | $orderby=DateModified desc | |
$top / $skip | $top=50&$skip=100 | $top is capped at 128. |
/$count | GET {{serverURL}}/ServiceRequests/$count?$filter=State eq 'Released' | Plain-text number. Supported on ServiceRequests, Appointments, Users, CustomerRequests, Offers and Orders. |
$inlinecount and $search are not supported.
Paging
Collections are paged server-side. When more data is available the response carries an odata.nextLink – follow it until it disappears:
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests",
"value": [ ... ],
"odata.nextLink": "https://portal.mobilefieldreport.com/odata/ServiceRequests?$skip=128"
}
Creating, updating, deleting
| Verb | Behaviour |
|---|
POST {Set} | Creates an entity, returns 201 with the created entity (including its Id). |
PUT {Set}(id) | Replaces the entity. Properties missing from the body are reset to their default – always GET the entity first, modify, and send the whole object back. Navigation collections (Tags, Contacts, Documents, …) are ignored by PUT; use $links. |
PATCH {Set}(id) / MERGE {Set}(id) | Partial update: only the properties present in the body are changed (404 if the entity does not exist). |
DELETE {Set}(id) | Returns 204. |
PUT and PATCH answer 204 No Content by default. Send the header Prefer: return-content to get 200 with the updated entity instead – the examples in this documentation assume that header, which is why they show a body.
Relations – $links
Many-to-many and reference relations are managed with the $links sub-resource:
POST {{serverURL}}/ServiceRequests(123L)/$links/Tags
Content-Type: application/json
{ "url": "{{serverURL}}/Tags(456L)" }
POST or PUT on {Set}(id)/$links/{Navigation} adds the relation. The body is { "url": "<entity URL>" }; a relative URL like /Tags(456L) is accepted too.DELETE {Set}(id)/$links/{Navigation}(relatedId) removes it. Alternatively send DELETE {Set}(id)/$links/{Navigation} with the same { "url": ... } body.
Creating related entities
Some children can be created directly under their parent, which sets the parent link for you:
POST {{serverURL}}/Companies(id)/ContactsPOST {{serverURL}}/Companies(id)/ServiceObjectsPOST {{serverURL}}/ServiceRequests(id)/AppointmentsPOST {{serverURL}}/Projects(id)/TasksPOST {{serverURL}}/Warehouses(id)/Inventory and .../StockMovements
Actions
Actions are invoked with POST {Set}(id)/{Action} and a JSON body holding the parameters ({} when there are none), e.g. POST {{serverURL}}/Invoices(123L)/Cancel. Collection-bound actions are called on the set: POST {{serverURL}}/ServiceRequests/Deep.
Batch requests
POST {{serverURL}}/$batch accepts a multipart/mixed body with several operations. Wrap writes in a changeset so they are executed atomically. See Step → Batch create Steps for a complete example.
Missing entities
By default GET {Set}(id) for an unknown id returns 500. Send the header ProperStatusCodes: true to receive a proper 404 instead – recommended for all integrations.
Errors
Errors are returned as OData error documents:
{
"odata.error": {
"code": "",
"message": { "lang": "en-US", "value": "The entity ServiceRequest with Key: 123 can not be found" }
}
}
| Status | Meaning |
|---|
| 400 | Validation or business-rule violation (message explains what is wrong). |
| 401 | Missing/invalid credentials or missing API permission. |
| 404 | Entity not found (with ProperStatusCodes, on PATCH, and on most write endpoints). |
| 405 | Operation not supported on this set (e.g. POST Warehouses(id)/Orders). |
| 429 | Login throttling – wait for Retry-After. |
| 500 | Unexpected error; also returned for unknown ids without ProperStatusCodes. |
Binary content (files)
Files are not part of the OData model. Use the REST endpoints under {{baseURL}}/mfr documented in the Document, Attachment and Report chapters (multipart uploads, PDF download).
Service Request 27 endpoints
A Service Request is a job (work order): what has to be done, for which customer, on which service object, by whom and when. It carries checklist steps, items (material/services), time recordings, appointments, documents, reports and comments.
Related sets Offers, Orders, CustomerRequests, Projects and invoice drafts are service requests with a different Type and are documented in their own chapters.
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: ServiceRequests(123L). |
| Name | string | Title of the job. Required on create. |
| ExternalId | string | Free identifier for your own system (ERP number, foreign key, …). |
| InvoiceId | string | Invoice number if the job has been invoiced. Read-only. |
| CreatedBy | Contact | Contact of the user who created the job. Navigation, read-only. |
| ClosedBy | User | User who closed the job. Navigation, read-only. |
| ReleasedBy | User | User who released the job. Navigation, read-only. |
| ClosedAt | datetime | When the job was closed. Read-only. |
| ReleasedAt | datetime | When the job was released. Read-only. |
| WorkDoneAt | datetime | When the technician reported the work as done. Read-only. |
| TargetTimeInMinutes | long | Planned duration in minutes. |
| DateModified | datetime | Date of the last modification (UTC). Read-only. |
| DateOfCreation | datetime | Date of creation (UTC). Read-only. |
| DueDateRangeStart | datetime | Start of the due-date window. |
| DueDateRangeEnd | datetime | End of the due-date window (deadline). |
| PortalLink | string | Customer-portal link (see the ResolveCustomerPortalLink action). Read-only. |
| CostCenterId | long | Id of the cost center / project the job belongs to. |
| CostCenter | CostCenter | Navigation property (CostCenter). Load it with $expand=CostCenter. |
| Description | string | Description of the work (may contain HTML). |
| State | string | Workflow state – see the table below. Serialized without the e prefix used internally (Released, not eReleased). |
| Destination | ServiceObject | The service object where the work takes place (root service object). Navigation. |
| Appointments | Appointment[] | Appointments (planned visits). Navigation – $expand=Appointments/Contacts includes the technicians. |
| Items | Item[] | Material / services booked on the job. Navigation. |
| CustomValues | CustomValue[] | Custom field values: [{ "Meta": "<field name>", "Value": "<value>" }]. |
| DocumentIds | long[] | Ids of linked documents. Read-only. |
| Documents | Document[] | Linked documents. Navigation. |
| Reports | Report[] | Generated reports and invoices. Navigation. |
| ContactIds | long[] | Ids of linked contacts. Read-only. |
| Contacts | Contact[] | Customer contacts linked to the job. Navigation. |
| ServiceObjectIds | long[] | Ids of linked service objects. Read-only. |
| StepListTemplates | StepListTemplate[] | Checklist templates applied to the job. Navigation. |
| ServiceObjects | ServiceObject[] | Service objects / products of this job. Navigation – $expand=ServiceObjects/Location includes addresses. |
| StepListTemplateIds | long[] | Ids of the applied checklist templates. Read-only. |
| TimeEvents | TimeEvent[] | Time recordings of the job. Navigation. |
| Comments | Comment[] | Comments. Navigation. |
| CurrentOwnerId | long | Id of the contact (office user) responsible for the job. |
| CurrentOwner | Contact | Responsible office user. Navigation. |
| CustomerId | long | Id of the customer company. |
| ParentServiceRequestId | long | Id of the parent job (follow-up jobs). |
| Customer | Company | Customer company. Navigation. |
| Location | Location | Location of the job (copied from the destination). Navigation. |
| Version | int | Row version, incremented on every update. Read-only. |
| TagIds | long[] | Ids of the assigned tags. Read-only – use $links/Tags. |
| Tags | Tag[] | Assigned tags. Navigation. |
| Steps | Step[] | Checklist steps. Navigation – $expand=Steps (use Steps/StepListTemplate or Steps/Attachments for more). |
| StockMovements | StockMovement[] | Stock movements booked on the job. Navigation. |
| IsTemplate | bool | true for service request templates. Filter IsTemplate eq true lists templates instead of jobs. |
| IsTemplateMobile | bool | Template is offered on the mobile app for ad-hoc jobs. |
| CreateFromServiceRequestTemplateId | long | Write-only on create: id of the template the new job is copied from (steps, items, documents). |
| Type | string | Kind of service request – see the table below. Read-only. |
| Qualifications | Qualification[] | Qualifications a technician needs for this job. Navigation. |
| Invoices | Invoice[] | Invoices generated from this job. Navigation. |
State values
| Value | Meaning |
|---|
| Created | Job created, not planned yet (Open). |
| ReadyForScheduling | Job is complete and waits for planning. |
| Scheduled | An appointment exists but the job is not released yet. |
| Released | Released to the technician(s); visible on the mobile app. |
| InProgress | A technician is working on the job. |
| IsWorkDone | Technician reported the work as done; waiting for office approval. |
| Closed | Approved and closed. |
| Invoiced | An invoice was generated for the job. |
| Rejected | Rejected / cancelled. |
| WaitingForResponse | Waiting for a response from the customer. |
| SubcontractorPendingConfirmation / SubcontractorConfirmed / SubcontractorRejected / SubcontractorAdditionalTasks | Subcontractor workflow states. |
| CollaborationWaitingConfirmation / CollaborationRejected / CollaborationMerged / CollaborationAdditionalTasks | Collaboration (multi-tenant) workflow states. |
| OfferIsSend / OfferIsConfirmed / OfferIsConfirmedAndCreateJob / OfferIsRejected / OfferIsExpired / OfferIsCancelled | Used by Offers only. |
| OrderPrinted / OrderCancelled | Used by Orders only. |
Type values
| Value | Meaning |
|---|
| IsServiceRequest | Regular job (default). |
| IsStandardTemplate | Service request template. |
| IsProjectSRTemplate | Template that belongs to a project. |
| IsRecurringJob | Job generated by a recurring event. |
| IsMaintenance | Maintenance job. |
| IsOffer | Offer – exposed through the Offers set. |
| IsOrder | Order – exposed through the Orders set. |
| IsCustomerRequest | Customer request – exposed through the CustomerRequests set. |
| IsInvoice | Invoice draft – used by CreateInvoiceDraft / POST Invoices. |
| IsProject | Project – exposed through the Projects set. |
| IsActivity / IsHoliday / IsAdditionalCosts / IsInventory | Internal types. |
Useful filters
| Filter | Effect |
|---|
$filter=IsTemplate eq true | Returns templates instead of jobs. |
$filter=State eq 'Released' | Jobs in a state. |
$filter=DateModified gt datetime'2026-08-01T00:00:00Z' | Delta sync. |
$filter=CustomerId eq 123L | Jobs of a customer. |
$filter=ExternalId eq 'ERP-4711' | Lookup by your own id. |
Endpoints
| Method | URL | Description |
|---|
| GET | {{serverURL}}/ServiceRequests?$top=50&$orderby=DateModified desc | Get Service Requests |
| GET | {{serverURL}}/ServiceRequests?$expand=Customer,ServiceObjects/Location,Appointments/Contacts,Tags,Steps&$select=Id,Name,State,Customer,ServiceObjects,Appointments,Tags,Steps&$top=20 | Get Service Requests with related data |
| GET | {{serverURL}}/ServiceRequests?$filter=DateModified gt datetime'2026-08-01T00:00:00Z' and State eq 'Closed'&$orderby=DateModified | Get Service Requests modified since (delta sync) |
| GET | {{serverURL}}/ServiceRequests?$filter=IsTemplate eq true&$expand=Steps,Items | Get Service Request Templates |
| GET | {{serverURL}}/ServiceRequests/$count?$filter=State eq 'Released' | Count Service Requests |
| GET | {{serverURL}}/ServiceRequests(1234567890L)?$expand=Customer,Destination,Contacts,Documents,Qualifications | Retrieve a Service Request |
| POST | {{serverURL}}/ServiceRequests | Create a Service Request |
| POST | {{serverURL}}/ServiceRequests | Create a Service Request from a Template |
| POST | {{serverURL}}/ServiceRequests/Deep | Create a Service Request with customer and service objects (Deep) |
| PUT | {{serverURL}}/ServiceRequests(1234567890L) | Update a Service Request (PUT) |
| PATCH | {{serverURL}}/ServiceRequests(1234567890L) | Update a Service Request partially (PATCH) |
| PATCH | {{serverURL}}/ServiceRequests(1234567890L) | Change the State of a Service Request |
| DELETE | {{serverURL}}/ServiceRequests(1234567890L) | Delete a Service Request |
| GET | {{serverURL}}/ServiceRequests(1234567890L)/Comments | Get Comments of a Service Request |
| POST | {{serverURL}}/ServiceRequests(1234567890L)/Appointments | Create an Appointment for a Service Request |
| POST | {{serverURL}}/ServiceRequests(1234567890L)/$links/ServiceObjects | Link a Service Object to a Service Request |
| DELETE | {{serverURL}}/ServiceRequests(1234567890L)/$links/ServiceObjects(4001L) | Unlink a Service Object from a Service Request |
| POST | {{serverURL}}/ServiceRequests(1234567890L)/$links/Tags | Link a Tag to a Service Request |
| DELETE | {{serverURL}}/ServiceRequests(1234567890L)/$links/Tags(6001L) | Unlink a Tag from a Service Request |
| POST | {{serverURL}}/ServiceRequests(1234567890L)/$links/Qualifications | Link a Qualification to a Service Request |
| DELETE | {{serverURL}}/ServiceRequests(1234567890L)/$links/Qualifications(9001L) | Unlink a Qualification from a Service Request |
| POST | {{serverURL}}/ServiceRequests(1234567890L)/$links/Contacts | Link a Contact to a Service Request |
| POST | {{serverURL}}/ServiceRequests(1234567890L)/$links/Documents | Link a Document to a Service Request |
| POST | {{serverURL}}/ServiceRequests(1234567890L)/$links/StepListTemplates | Link a Step List Template to a Service Request |
| POST | {{serverURL}}/ServiceRequests(1234567890L)/ResolveCustomerPortalLink | Action: Resolve Customer Portal Link |
| POST | {{serverURL}}/ServiceRequests(1234567890L)/CreateInvoiceDraft | Action: Create Invoice Draft |
| POST | {{serverURL}}/ServiceRequests(1234567890L)/BestTechnicianForJob | Action: Best Technician for Job |
GET Get Service Requests
GET {{serverURL}}/ServiceRequests?$top=50&$orderby=DateModified desc
Lists jobs (not templates), newest first. The response is paged – follow odata.nextLink to fetch the rest.
Combine with $filter, $select and $expand as needed; see the chapter description for common filters.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests",
"value": [
{
"Id": "1234567890",
"Name": "Repair heating pump",
"ExternalId": "ERP-4711",
"ReleasedAt": "2026-08-25T08:00:00Z",
"TargetTimeInMinutes": "120",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DueDateRangeStart": "2026-09-01T06:00:00Z",
"DueDateRangeEnd": "2026-09-05T16:00:00Z",
"Description": "<p>Pump makes noise, check bearing.</p>",
"State": "Released",
"CustomValues": [
{
"Meta": "OrderNumber",
"Value": "PO-2026-001"
}
],
"CurrentOwnerId": "3001",
"CustomerId": "2001",
"Version": 1,
"IsTemplate": false,
"IsTemplateMobile": false,
"Type": "IsServiceRequest"
}
],
"odata.nextLink": "https://portal.mobilefieldreport.com/odata/ServiceRequests?$top=50&$orderby=DateModified desc&$skip=50"
}
GET Get Service Requests with related data
GET {{serverURL}}/ServiceRequests?$expand=Customer,ServiceObjects/Location,Appointments/Contacts,Tags,Steps&$select=Id,Name,State,Customer,ServiceObjects,Appointments,Tags,Steps&$top=20
Uses $expand to load the customer, service objects with their address, appointments with the assigned technicians, tags and checklist steps in one round trip. $select keeps the payload small.
Nested expands supported on this set: ServiceObjects/Location, Destination, Steps/StepListTemplate, Steps/Attachments, Appointments/Contacts, Items/ItemType, TimeEvents/Contact.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests",
"value": [
{
"Id": "1234567890",
"Name": "Repair heating pump",
"State": "Released",
"Customer": {
"Id": "2001",
"Name": "ACME GmbH",
"ExternalId": "C-100"
},
"ServiceObjects": [
{
"Id": "4001",
"Name": "Heating pump 3",
"ExternalId": "HP-3",
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"Country": "DE",
"Latitude": 52.53,
"Longitude": 13.38
}
}
],
"Appointments": [
{
"Id": "5001",
"StartDateTime": "2026-09-02T07:00:00Z",
"EndDateTime": "2026-09-02T09:00:00Z",
"State": "NotVisited",
"AppointmentType": "Standard",
"Contacts": [
{
"Id": "3002",
"FirstName": "Max",
"LastName": "Mustermann"
}
]
}
],
"Tags": [
{
"Id": "6001",
"Name": "Repair",
"ColorDefinition": "#1491ad",
"Type": "ServiceRequest"
}
],
"Steps": [
{
"Id": "7001",
"Name": "Check bearing",
"Type": "Choice",
"IsDone": false,
"TrackingId": "CHK1",
"SortOrder": 0
}
]
}
]
}
GET Get Service Requests modified since (delta sync)
GET {{serverURL}}/ServiceRequests?$filter=DateModified gt datetime'2026-08-01T00:00:00Z' and State eq 'Closed'&$orderby=DateModified
Typical integration query: everything closed and changed since the last run. Store the highest DateModified you processed and use it as the next lower bound.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests",
"value": [
{
"Id": "1234567890",
"Name": "Repair heating pump",
"ExternalId": "ERP-4711",
"ReleasedAt": "2026-08-25T08:00:00Z",
"TargetTimeInMinutes": "120",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DueDateRangeStart": "2026-09-01T06:00:00Z",
"DueDateRangeEnd": "2026-09-05T16:00:00Z",
"Description": "<p>Pump makes noise, check bearing.</p>",
"State": "Closed",
"CustomValues": [
{
"Meta": "OrderNumber",
"Value": "PO-2026-001"
}
],
"CurrentOwnerId": "3001",
"CustomerId": "2001",
"Version": 1,
"IsTemplate": false,
"IsTemplateMobile": false,
"Type": "IsServiceRequest",
"ClosedAt": "2026-08-25T08:00:00Z"
}
]
}
GET Get Service Request Templates
GET {{serverURL}}/ServiceRequests?$filter=IsTemplate eq true&$expand=Steps,Items
The IsTemplate eq true filter switches the set to templates. Template ids can be used in CreateFromServiceRequestTemplateId when creating jobs, and for recurring events.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests",
"value": [
{
"Id": "1111",
"Name": "Standard maintenance",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"State": "Created",
"Items": [],
"Version": 1,
"Steps": [
{
"Id": "7101",
"Name": "Visual inspection",
"Type": "Choice",
"TrackingId": "VI"
}
],
"IsTemplate": true,
"IsTemplateMobile": false,
"Type": "IsStandardTemplate"
}
]
}
GET Count Service Requests
GET {{serverURL}}/ServiceRequests/$count?$filter=State eq 'Released'
Returns the number of matching jobs as plain text. Any $filter is honoured.
Responses
200 200 OK
42
GET Retrieve a Service Request
GET {{serverURL}}/ServiceRequests(1234567890L)?$expand=Customer,Destination,Contacts,Documents,Qualifications
Loads one job by id. Note the L suffix on the key.
The ProperStatusCodes: true header makes the service answer 404 for unknown ids instead of 500.
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests/@Element",
"Id": "1234567890",
"Name": "Repair heating pump",
"ExternalId": "ERP-4711",
"ReleasedAt": "2026-08-25T08:00:00Z",
"TargetTimeInMinutes": "120",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DueDateRangeStart": "2026-09-01T06:00:00Z",
"DueDateRangeEnd": "2026-09-05T16:00:00Z",
"Description": "<p>Pump makes noise, check bearing.</p>",
"State": "Released",
"CustomValues": [
{
"Meta": "OrderNumber",
"Value": "PO-2026-001"
}
],
"CurrentOwnerId": "3001",
"CustomerId": "2001",
"Version": 1,
"IsTemplate": false,
"IsTemplateMobile": false,
"Type": "IsServiceRequest",
"Customer": {
"Id": "2001",
"Name": "ACME GmbH"
},
"Destination": {
"Id": "4001",
"Name": "Heating pump 3"
},
"Contacts": [],
"Documents": [],
"Qualifications": []
}
404 404 Not Found (with ProperStatusCodes header)
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "The entity ServiceRequest with Key: 1234567890 can not be found"
}
}
}
POST Create a Service Request
POST {{serverURL}}/ServiceRequests
Creates a job in state Created.
| Body | Type | Description |
|---|
| Name | string | Required. |
| CustomerId | long | Customer company. Alternatively Customer: { "Id": ... }. |
| CurrentOwnerId | long | Responsible office contact. |
| Description, ExternalId, TargetTimeInMinutes, DueDateRangeStart/End, CostCenterId, CustomValues | | Optional. |
| CreateFromServiceRequestTemplateId | long | Copy steps, items and documents from a template (see next request). |
| State | string | Optional initial state, e.g. ReadyForScheduling. |
Link the service object afterwards with $links/ServiceObjects (or use Create a Service Request with customer and service objects (Deep) to do everything in one call).
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"Name": "Repair heating pump",
"ExternalId": "ERP-4711",
"Description": "<p>Pump makes noise, check bearing.</p>",
"CustomerId": 2001,
"CurrentOwnerId": 3001,
"TargetTimeInMinutes": 120,
"DueDateRangeStart": "2026-09-01T06:00:00Z",
"DueDateRangeEnd": "2026-09-05T16:00:00Z",
"CustomValues": [
{
"Meta": "OrderNumber",
"Value": "PO-2026-001"
}
]
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests/@Element",
"Id": "1234567891",
"Name": "Repair heating pump",
"ExternalId": "ERP-4711",
"TargetTimeInMinutes": "120",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DueDateRangeStart": "2026-09-01T06:00:00Z",
"DueDateRangeEnd": "2026-09-05T16:00:00Z",
"Description": "<p>Pump makes noise, check bearing.</p>",
"State": "Created",
"CustomValues": [
{
"Meta": "OrderNumber",
"Value": "PO-2026-001"
}
],
"CurrentOwnerId": "3001",
"CustomerId": "2001",
"Version": 1,
"IsTemplate": false,
"IsTemplateMobile": false,
"Type": "IsServiceRequest"
}
400 400 Bad Request
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "Name: The Name field is required."
}
}
}
POST Create a Service Request from a Template
POST {{serverURL}}/ServiceRequests
Same as Create a Service Request, but copies checklist steps, items and documents from the template given in CreateFromServiceRequestTemplateId (get template ids from Get Service Request Templates).
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"Name": "Yearly maintenance – ACME",
"CreateFromServiceRequestTemplateId": 1111,
"CustomerId": 2001,
"State": "ReadyForScheduling"
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests/@Element",
"Id": "1234567891",
"Name": "Yearly maintenance – ACME",
"ExternalId": "ERP-4711",
"TargetTimeInMinutes": "120",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DueDateRangeStart": "2026-09-01T06:00:00Z",
"DueDateRangeEnd": "2026-09-05T16:00:00Z",
"Description": "<p>Pump makes noise, check bearing.</p>",
"State": "ReadyForScheduling",
"CustomValues": [
{
"Meta": "OrderNumber",
"Value": "PO-2026-001"
}
],
"CurrentOwnerId": "3001",
"CustomerId": "2001",
"Version": 1,
"IsTemplate": false,
"IsTemplateMobile": false,
"Type": "IsServiceRequest"
}
POST Create a Service Request with customer and service objects (Deep)
POST {{serverURL}}/ServiceRequests/Deep
Collection action that creates (or reuses) the customer, the service objects with their contacts and the job in a single transaction – the typical "new order from ERP" call.
Customer.Id / ServiceObjects[].Id: pass an existing id to reuse the entity, null to create it. Existing entities are also matched by ExternalId.CreateGeoLocation: true geocodes the address so the object appears on the map / in route planning.State: optional initial job state (Created by default).CreateFromServiceRequestTemplateId: optional template to copy steps and items from.
Returns the created service request.
| Attribute | Type | Description |
|---|
| Name | string | Required. Job title. |
| Description | string | Job description. |
| Customer | Company | Customer to create or reuse (Id, Name, ExternalId, CreateGeoLocation, IsPhysicalPerson, Location). |
| ServiceObjects | ServiceObject[] | Service objects to create or reuse (Id, Name, ExternalId, CreateGeoLocation, Location, Contacts[]). |
| State | string | Initial state. |
| CreateFromServiceRequestTemplateId | long | Template to copy from. |
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"serviceRequest": {
"Name": "Install new boiler",
"Description": "Customer bought model X200",
"State": "ReadyForScheduling",
"CreateFromServiceRequestTemplateId": null,
"Customer": {
"Id": null,
"Name": "ACME GmbH",
"ExternalId": "C-100",
"CreateGeoLocation": true,
"IsPhysicalPerson": false,
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"Country": "DE"
}
},
"ServiceObjects": [
{
"Id": null,
"Name": "Boiler X200",
"ExternalId": "SN-998877",
"CreateGeoLocation": true,
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"Country": "DE"
},
"Contacts": [
{
"FirstName": "Erika",
"LastName": "Musterfrau",
"Telephone": "+49 30 1234",
"Mobile": "+49 170 1234",
"Email": "erika@example.com"
}
]
}
]
}
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests/@Element",
"Id": "1234567891",
"Name": "Install new boiler",
"ExternalId": "ERP-4711",
"TargetTimeInMinutes": "120",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DueDateRangeStart": "2026-09-01T06:00:00Z",
"DueDateRangeEnd": "2026-09-05T16:00:00Z",
"Description": "<p>Pump makes noise, check bearing.</p>",
"State": "ReadyForScheduling",
"CustomValues": [
{
"Meta": "OrderNumber",
"Value": "PO-2026-001"
}
],
"CurrentOwnerId": "3001",
"CustomerId": "2002",
"Version": 1,
"IsTemplate": false,
"IsTemplateMobile": false,
"Type": "IsServiceRequest"
}
PUT Update a Service Request (PUT)
PUT {{serverURL}}/ServiceRequests(1234567890L)
Replaces the job. Always GET first, change, and send everything back – properties missing from the body are reset.
Contacts, Documents, Tags and ServiceObjects in the body are ignored; the existing links are kept. Use $links to change them.- Changing
State runs the workflow: ReadyForScheduling marks the job ready for planning, Released releases it to the technicians, Closed closes and approves it; other values are set directly.
Returns 200 with the updated entity.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": "1234567890",
"Name": "Repair heating pump",
"ExternalId": "ERP-4711",
"ReleasedAt": "2026-08-25T08:00:00Z",
"TargetTimeInMinutes": 180,
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DueDateRangeStart": "2026-09-01T06:00:00Z",
"DueDateRangeEnd": "2026-09-05T16:00:00Z",
"Description": "<p>Pump makes noise, check bearing. Bring spare bearing 6204.</p>",
"State": "Released",
"CustomValues": [
{
"Meta": "OrderNumber",
"Value": "PO-2026-001"
}
],
"CurrentOwnerId": "3001",
"CustomerId": "2001",
"Version": 1,
"IsTemplate": false,
"IsTemplateMobile": false,
"Type": "IsServiceRequest"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests/@Element",
"Id": "1234567890",
"Name": "Repair heating pump",
"ExternalId": "ERP-4711",
"ReleasedAt": "2026-08-25T08:00:00Z",
"TargetTimeInMinutes": "180",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DueDateRangeStart": "2026-09-01T06:00:00Z",
"DueDateRangeEnd": "2026-09-05T16:00:00Z",
"Description": "<p>Pump makes noise, check bearing.</p>",
"State": "Released",
"CustomValues": [
{
"Meta": "OrderNumber",
"Value": "PO-2026-001"
}
],
"CurrentOwnerId": "3001",
"CustomerId": "2001",
"Version": 2,
"IsTemplate": false,
"IsTemplateMobile": false,
"Type": "IsServiceRequest"
}
PATCH Update a Service Request partially (PATCH)
PATCH {{serverURL}}/ServiceRequests(1234567890L)
Changes only the properties present in the body (MERGE is accepted as an alias). Safer than PUT for integrations that only own a few fields. Returns 200 with the entity, 404 if it does not exist.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"CurrentOwnerId": 3005,
"DueDateRangeEnd": "2026-09-10T16:00:00Z"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests/@Element",
"Id": "1234567890",
"Name": "Repair heating pump",
"ExternalId": "ERP-4711",
"ReleasedAt": "2026-08-25T08:00:00Z",
"TargetTimeInMinutes": "120",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DueDateRangeStart": "2026-09-01T06:00:00Z",
"DueDateRangeEnd": "2026-09-10T16:00:00Z",
"Description": "<p>Pump makes noise, check bearing.</p>",
"State": "Released",
"CustomValues": [
{
"Meta": "OrderNumber",
"Value": "PO-2026-001"
}
],
"CurrentOwnerId": "3005",
"CustomerId": "2001",
"Version": 2,
"IsTemplate": false,
"IsTemplateMobile": false,
"Type": "IsServiceRequest"
}
404 404 Not Found
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "The entity ServiceRequest with Key: 1234567890 can not be found"
}
}
}
PATCH Change the State of a Service Request
PATCH {{serverURL}}/ServiceRequests(1234567890L)
Shortcut for a state transition. Typical sequence: Created → ReadyForScheduling → (appointment created) → Released → technician works (InProgress, IsWorkDone) → Closed.
Releasing requires a planned appointment with a technician when your account is configured that way; a 400 explains the missing precondition.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"State": "Released"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests/@Element",
"Id": "1234567890",
"Name": "Repair heating pump",
"ExternalId": "ERP-4711",
"ReleasedAt": "2026-08-25T08:00:00Z",
"TargetTimeInMinutes": "120",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DueDateRangeStart": "2026-09-01T06:00:00Z",
"DueDateRangeEnd": "2026-09-05T16:00:00Z",
"Description": "<p>Pump makes noise, check bearing.</p>",
"State": "Released",
"CustomValues": [
{
"Meta": "OrderNumber",
"Value": "PO-2026-001"
}
],
"CurrentOwnerId": "3001",
"CustomerId": "2001",
"Version": 2,
"IsTemplate": false,
"IsTemplateMobile": false,
"Type": "IsServiceRequest"
}
DELETE Delete a Service Request
DELETE {{serverURL}}/ServiceRequests(1234567890L)
Deletes the job with its steps, items, appointments and time events. Returns 204.
Responses
204 204 No Content
No body.
POST Create an Appointment for a Service Request
POST {{serverURL}}/ServiceRequests(1234567890L)/Appointments
Creates a visit for the technician (ContactId = the technician's contact id) and links it to the job. The job is released automatically when it is ready. Equivalent to POST Appointments with ServiceRequestId set – see the Appointment chapter for the body.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"StartDateTime": "2026-09-02T07:00:00Z",
"EndDateTime": "2026-09-02T09:00:00Z",
"ContactId": 3002,
"AppointmentType": "Standard",
"Note": "Bring spare bearing"
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Appointments/@Element",
"Id": "5001",
"Version": 1,
"State": "NotVisited",
"Type": "Standard",
"AppointmentType": "Standard",
"CreatedAt": "2026-08-25T08:00:00Z",
"EndDateTime": "2026-09-02T09:00:00Z",
"StartDateTime": "2026-09-02T07:00:00Z",
"DrivingDistanceFrom": 0,
"DrivingDistanceTo": 0,
"WasReadOnClientSide": false,
"ContactIds": [
"3002"
],
"ServiceRequestId": "1234567890",
"ContactId": "3002",
"Note": "Bring spare bearing"
}
POST Link a Service Object to a Service Request
POST {{serverURL}}/ServiceRequests(1234567890L)/$links/ServiceObjects
Sets the root service object (destination) of the job. A job has one root service object – linking another one replaces it. PUT works the same way.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/ServiceObjects(4001L)"
}
Responses
204 204 No Content
No body.
DELETE Unlink a Service Object from a Service Request
DELETE {{serverURL}}/ServiceRequests(1234567890L)/$links/ServiceObjects(4001L)
Removes the service object from the job.
Responses
204 204 No Content
No body.
POST Link a Tag to a Service Request
POST {{serverURL}}/ServiceRequests(1234567890L)/$links/Tags
Adds a tag of type ServiceRequest (see Tags). Repeat for multiple tags.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/Tags(6001L)"
}
Responses
204 204 No Content
No body.
DELETE Unlink a Tag from a Service Request
DELETE {{serverURL}}/ServiceRequests(1234567890L)/$links/Tags(6001L)
Removes the tag. Alternative form: DELETE …/$links/Tags with body { "url": "…/Tags(6001L)" }.
Responses
204 204 No Content
No body.
POST Link a Qualification to a Service Request
POST {{serverURL}}/ServiceRequests(1234567890L)/$links/Qualifications
Requires the qualification for this job; only technicians with the qualification are proposed by the scheduler.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/Qualifications(9001L)"
}
Responses
204 204 No Content
No body.
DELETE Unlink a Qualification from a Service Request
DELETE {{serverURL}}/ServiceRequests(1234567890L)/$links/Qualifications(9001L)
Removes the qualification requirement.
Responses
204 204 No Content
No body.
POST Link a Contact to a Service Request
POST {{serverURL}}/ServiceRequests(1234567890L)/$links/Contacts
Adds a customer contact (on-site contact person) to the job. Contacts are shown to the technician on the mobile app.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/Contacts(3100L)"
}
Responses
204 204 No Content
No body.
POST Link a Document to a Service Request
POST {{serverURL}}/ServiceRequests(1234567890L)/$links/Documents
Attaches an existing document (upload it first with POST {{baseURL}}/mfr/Document/UploadAndCreate, see Document). To detach use DELETE {{baseURL}}/mfr/ServiceRequest/{id}/Document/{documentId}.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/Documents(10001L)"
}
Responses
204 204 No Content
No body.
POST Link a Step List Template to a Service Request
POST {{serverURL}}/ServiceRequests(1234567890L)/$links/StepListTemplates
Applies a released checklist template: its steps are copied into the job. Also works for templates (IsTemplate eq true).
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/StepListTemplates(12001L)"
}
Responses
204 204 No Content
No body.
POST Action: Resolve Customer Portal Link
POST {{serverURL}}/ServiceRequests(1234567890L)/ResolveCustomerPortalLink
Returns the public customer-portal URL of the job (the customer can follow the progress and download reports there).
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Edm.String",
"value": "https://portal.mobilefieldreport.com/CustomerPortal/ABCDEF123456"
}
POST Action: Create Invoice Draft
POST {{serverURL}}/ServiceRequests(1234567890L)/CreateInvoiceDraft
Creates an invoice draft (a service request of type IsInvoice) from the items and time recordings of the job and returns it. Pass its Id as InvoiceDraftId to POST Invoices to generate the invoice PDF (see Invoice).
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests/@Element",
"Id": "1234570000",
"Name": "Invoice – Repair heating pump",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"State": "Created",
"CustomerId": "2001",
"ParentServiceRequestId": "1234567890",
"Version": 1,
"IsTemplate": false,
"IsTemplateMobile": false,
"Type": "IsInvoice"
}
POST Action: Best Technician for Job
POST {{serverURL}}/ServiceRequests(1234567890L)/BestTechnicianForJob
Scheduling assistant: ranks technicians for the job in the given time window.
| Parameter | Type | Description |
|---|
| maxDistance | int | Maximum distance to the job location in km. |
| startDateTime / endDateTime | datetime | Time window to search in. |
Returns a collection ordered by Score (higher is better) with distance, driving time, the next free time block and the technician's contact data.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"maxDistance": 50,
"startDateTime": "2026-09-02T06:00:00Z",
"endDateTime": "2026-09-04T16:00:00Z"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Collection(MFR.Domain.Api.Documents.ODataBestTechnicianData)",
"value": [
{
"IsSecondAppointmentThisDay": false,
"HomeDistance": 30.2,
"HomeDrivingTime": 35,
"Distance": 12.4,
"DrivingTime": 18.5,
"SourceLongitude": "0",
"SourceLatitude": "0",
"DestinationLongitude": "0",
"DestinationLatitude": "0",
"Score": "87",
"Confidence": "90",
"IsSubcontractor": false,
"NumberOfCustomerVisits": "3",
"NumberOfServiceObjectVisits": 0,
"NextAppointment": "2026-09-02T10:00:00Z",
"PreviousFreeTimeBlock": {
"Start": "2026-09-02T06:00:00Z",
"End": "2026-09-02T10:00:00Z",
"Distance": 12.4,
"DrivingTime": 18.5,
"HasLocation": true,
"Latitude": 52.5,
"Longitude": 13.4,
"LatitudeTechnician": 52.4,
"LongitudeTechnician": 13.3,
"MinTargetTimeHours": 2
},
"Technician": {
"ExternalId": "T-12",
"Email": "max@example.com",
"FirstName": "Max",
"LastName": "Mustermann",
"JobTitle": "Technician",
"MobilePhone": "+49 170 1234",
"Telephone": null,
"StartWorkingTime": "07:00",
"EndWorkingTime": "16:00",
"Pause": "00:30",
"Vacation": "30"
}
}
]
}
Appointment 12 endpoints
An Appointment is a planned time slot of a technician: either a visit for a service request or an absence (vacation, illness, …). Creating a standard appointment on a job that is ready for scheduling releases the job automatically.
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Appointments(123L). |
| Version | int | Row version, incremented on every update. Read-only. |
| State | string | Progress of the visit – see State values. Read-only (set by the technician). |
| Type | string | Same as AppointmentType; kept for backwards compatibility. Use AppointmentType. |
| AppointmentType | string | Kind of appointment – see AppointmentType values. Default Standard. |
| CreatedAt | datetime | Date of creation (UTC). Read-only. |
| EndDateTime | datetime | Planned end (UTC). Required. |
| StartDateTime | datetime | Planned start (UTC). Required. |
| DrivingDistanceFrom | int | Driving distance to the site in km (calculated). |
| DrivingDistanceTo | int | Driving distance from the site in km (calculated). |
| WasReadOnClientSide | bool | The technician has seen the appointment on the mobile app. Read-only. |
| ContactIds | long[] | Ids of all assigned technicians (contacts). Read-only – set ContactId / Contacts. |
| ServiceRequestId | long | Job the visit belongs to. Required for Standard appointments, omitted for absences. |
| ServiceRequest | ServiceRequest | The job. Navigation. |
| Contacts | Contact[] | Assigned technicians. Navigation – $expand=Contacts. On create you may pass [{ "Id": … }] to assign several technicians. |
| Pipeline | Tag | Pipeline tag (project tasks only). Navigation. |
| ContactId | long | Id of the (first) assigned technician's contact (not the user id). |
| Contact | Contact | Assigned technician. Navigation. |
| Note | string | Free text shown to the technician. |
| ExternalId | string | Your own identifier. |
State values
| Value | Meaning |
|---|
| NotVisited | Planned, technician has not started yet. |
| InProgress | Technician is on site / working. |
| IsWorkDone | Technician finished the visit. |
| Rejected | Technician rejected the appointment. |
AppointmentType values
| Value | Meaning |
|---|
| Standard | Visit for a service request (requires ServiceRequestId). |
| Task | Project task (see Project → Tasks). |
| Vacation | Vacation of a technician (no service request). |
| Illness | Sick leave (no service request). |
| Other | Other absence with a time range. |
| OtherWithoutTime | Other all-day absence. |
| WorktimeCompensation | Compensation of overtime. |
| Repeating | Recurring appointment (created by the portal). |
Filters
| Filter | Notes |
|---|
StartDateTime ge datetime'…' and EndDateTime le datetime'…' | Time window. |
ContactId eq 3002L | Appointments of a technician (matches all assigned technicians, not only the first). |
Type eq 'Vacation' or AppointmentType eq 'Vacation' | By kind. |
ServiceRequestId eq 1234567890L | Appointments of a job. |
Endpoints
GET Get Appointments
GET {{serverURL}}/Appointments?$filter=StartDateTime ge datetime'2026-09-01T00:00:00Z' and EndDateTime le datetime'2026-09-30T23:59:59Z'&$expand=Contacts,ServiceRequest&$orderby=StartDateTime
Appointments in a time window with the assigned technicians and the job. Paged – follow odata.nextLink.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Appointments",
"value": [
{
"Id": "5001",
"Version": 1,
"State": "NotVisited",
"Type": "Standard",
"AppointmentType": "Standard",
"CreatedAt": "2026-08-25T08:00:00Z",
"EndDateTime": "2026-09-02T09:00:00Z",
"StartDateTime": "2026-09-02T07:00:00Z",
"DrivingDistanceFrom": 12,
"DrivingDistanceTo": 12,
"WasReadOnClientSide": false,
"ContactIds": [
"3002"
],
"ServiceRequestId": "1234567890",
"ContactId": "3002",
"Note": "Bring spare bearing",
"Contacts": [
{
"Id": "3002",
"FirstName": "Max",
"LastName": "Mustermann"
}
],
"ServiceRequest": {
"Id": "1234567890",
"Name": "Repair heating pump",
"State": "Released"
}
}
]
}
GET Get Appointments of a Technician
GET {{serverURL}}/Appointments?$filter=ContactId eq 3002L and StartDateTime ge datetime'2026-09-01T00:00:00Z'
ContactId is the technician's contact id (Users?$expand=Contact gives you the mapping). The filter matches every appointment the technician is assigned to, including team appointments.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Appointments",
"value": [
{
"Id": "5001",
"Version": 1,
"State": "NotVisited",
"Type": "Standard",
"AppointmentType": "Standard",
"CreatedAt": "2026-08-25T08:00:00Z",
"EndDateTime": "2026-09-02T09:00:00Z",
"StartDateTime": "2026-09-02T07:00:00Z",
"DrivingDistanceFrom": 12,
"DrivingDistanceTo": 12,
"WasReadOnClientSide": false,
"ContactIds": [
"3002"
],
"ServiceRequestId": "1234567890",
"ContactId": "3002",
"Note": "Bring spare bearing"
},
{
"Id": "5002",
"Version": 1,
"State": "NotVisited",
"Type": "Vacation",
"AppointmentType": "Vacation",
"CreatedAt": "2026-08-25T08:00:00Z",
"EndDateTime": "2026-09-18T23:59:59Z",
"StartDateTime": "2026-09-14T00:00:00Z",
"DrivingDistanceFrom": 0,
"DrivingDistanceTo": 0,
"WasReadOnClientSide": false,
"ContactIds": [
"3002"
],
"ContactId": "3002"
}
]
}
GET Get Absences (Vacation, Illness, …)
GET {{serverURL}}/Appointments?$filter=Type eq 'Vacation' or Type eq 'Illness'&$expand=Contact
Absences are appointments without a service request. Type eq '…' is translated to AppointmentType by the server.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Appointments",
"value": [
{
"Id": "5002",
"Version": 1,
"State": "NotVisited",
"Type": "Vacation",
"AppointmentType": "Vacation",
"CreatedAt": "2026-08-25T08:00:00Z",
"EndDateTime": "2026-09-18T23:59:59Z",
"StartDateTime": "2026-09-14T00:00:00Z",
"DrivingDistanceFrom": 0,
"DrivingDistanceTo": 0,
"WasReadOnClientSide": false,
"ContactIds": [
"3002"
],
"ContactId": "3002",
"Contact": {
"Id": "3002",
"FirstName": "Max",
"LastName": "Mustermann"
}
}
]
}
GET Count Appointments
GET {{serverURL}}/Appointments/$count?$filter=State eq 'NotVisited'
Number of matching appointments as plain text.
Responses
200 200 OK
17
GET Retrieve an Appointment
GET {{serverURL}}/Appointments(5001L)?$expand=Contacts,ServiceRequest
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Appointments/@Element",
"Id": "5001",
"Version": 1,
"State": "NotVisited",
"Type": "Standard",
"AppointmentType": "Standard",
"CreatedAt": "2026-08-25T08:00:00Z",
"EndDateTime": "2026-09-02T09:00:00Z",
"StartDateTime": "2026-09-02T07:00:00Z",
"DrivingDistanceFrom": 12,
"DrivingDistanceTo": 12,
"WasReadOnClientSide": false,
"ContactIds": [
"3002"
],
"ServiceRequestId": "1234567890",
"ContactId": "3002",
"Note": "Bring spare bearing",
"Contacts": [
{
"Id": "3002",
"FirstName": "Max",
"LastName": "Mustermann"
}
],
"ServiceRequest": {
"Id": "1234567890",
"Name": "Repair heating pump"
}
}
404 404 Not Found
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "The entity Appointment with Key: 5001 can not be found"
}
}
}
POST Create an Appointment
POST {{serverURL}}/Appointments
Plans a visit. The job is released automatically if it is in ReadyForScheduling.
| Body | Type | Description |
|---|
| ServiceRequestId | long | Required for Standard. |
| ContactId | long | Required. Technician's contact id. To assign a team pass Contacts: [{ "Id": 3002 }, { "Id": 3003 }] in addition. |
| StartDateTime / EndDateTime | datetime | Required, UTC. |
| AppointmentType | string | Default Standard. |
| Note, ExternalId | string | Optional. |
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"ServiceRequestId": 1234567890,
"ContactId": 3002,
"StartDateTime": "2026-09-02T07:00:00Z",
"EndDateTime": "2026-09-02T09:00:00Z",
"AppointmentType": "Standard",
"Note": "Bring spare bearing"
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Appointments/@Element",
"Id": "5001",
"Version": 1,
"State": "NotVisited",
"Type": "Standard",
"AppointmentType": "Standard",
"CreatedAt": "2026-08-25T08:00:00Z",
"EndDateTime": "2026-09-02T09:00:00Z",
"StartDateTime": "2026-09-02T07:00:00Z",
"DrivingDistanceFrom": 12,
"DrivingDistanceTo": 12,
"WasReadOnClientSide": false,
"ContactIds": [
"3002"
],
"ServiceRequestId": "1234567890",
"ContactId": "3002",
"Note": "Bring spare bearing"
}
400 400 Bad Request
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "StartDateTime: The StartDateTime field is required."
}
}
}
POST Create a Team Appointment
POST {{serverURL}}/Appointments
Assigns several technicians to the same visit. ContactId must be one of the Contacts.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"ServiceRequestId": 1234567890,
"ContactId": 3002,
"Contacts": [
{
"Id": 3002
},
{
"Id": 3003
}
],
"StartDateTime": "2026-09-02T07:00:00Z",
"EndDateTime": "2026-09-02T12:00:00Z",
"AppointmentType": "Standard"
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Appointments/@Element",
"Id": "5003",
"Version": 1,
"State": "NotVisited",
"Type": "Standard",
"AppointmentType": "Standard",
"CreatedAt": "2026-08-25T08:00:00Z",
"EndDateTime": "2026-09-02T12:00:00Z",
"StartDateTime": "2026-09-02T07:00:00Z",
"DrivingDistanceFrom": 12,
"DrivingDistanceTo": 12,
"WasReadOnClientSide": false,
"ContactIds": [
"3002",
"3003"
],
"ServiceRequestId": "1234567890",
"ContactId": "3002",
"Note": "Bring spare bearing"
}
POST Create a Vacation
POST {{serverURL}}/Appointments
Absences have no ServiceRequestId. Use AppointmentType Vacation, Illness, Other, OtherWithoutTime or WorktimeCompensation.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"ContactId": 3002,
"StartDateTime": "2026-09-14T00:00:00Z",
"EndDateTime": "2026-09-18T23:59:59Z",
"AppointmentType": "Vacation"
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Appointments/@Element",
"Id": "5002",
"Version": 1,
"State": "NotVisited",
"Type": "Vacation",
"AppointmentType": "Vacation",
"CreatedAt": "2026-08-25T08:00:00Z",
"EndDateTime": "2026-09-18T23:59:59Z",
"StartDateTime": "2026-09-14T00:00:00Z",
"DrivingDistanceFrom": 0,
"DrivingDistanceTo": 0,
"WasReadOnClientSide": false,
"ContactIds": [
"3002"
],
"ContactId": "3002"
}
POST Create an Illness
POST {{serverURL}}/Appointments
Same as Create a Vacation with AppointmentType: "Illness".
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"ContactId": 3002,
"StartDateTime": "2026-09-21T00:00:00Z",
"EndDateTime": "2026-09-21T23:59:59Z",
"AppointmentType": "Illness",
"Note": "Sick note received"
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Appointments/@Element",
"Id": "5004",
"Version": 1,
"State": "NotVisited",
"Type": "Illness",
"AppointmentType": "Illness",
"CreatedAt": "2026-08-25T08:00:00Z",
"EndDateTime": "2026-09-21T23:59:59Z",
"StartDateTime": "2026-09-21T00:00:00Z",
"DrivingDistanceFrom": 0,
"DrivingDistanceTo": 0,
"WasReadOnClientSide": false,
"ContactIds": [
"3002"
],
"ContactId": "3002",
"Note": "Sick note received"
}
PUT Update an Appointment (PUT)
PUT {{serverURL}}/Appointments(5001L)
Replaces the appointment (GET first, send everything back). Re-scheduling an appointment of a ready job releases the job automatically.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 5001,
"ServiceRequestId": 1234567890,
"ContactId": 3002,
"StartDateTime": "2026-09-03T07:00:00Z",
"EndDateTime": "2026-09-03T09:00:00Z",
"AppointmentType": "Standard",
"Note": "Moved to Thursday"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Appointments/@Element",
"Id": "5001",
"Version": 2,
"State": "NotVisited",
"Type": "Standard",
"AppointmentType": "Standard",
"CreatedAt": "2026-08-25T08:00:00Z",
"EndDateTime": "2026-09-03T09:00:00Z",
"StartDateTime": "2026-09-03T07:00:00Z",
"DrivingDistanceFrom": 12,
"DrivingDistanceTo": 12,
"WasReadOnClientSide": false,
"ContactIds": [
"3002"
],
"ServiceRequestId": "1234567890",
"ContactId": "3002",
"Note": "Moved to Thursday"
}
PATCH Reassign an Appointment (PATCH)
PATCH {{serverURL}}/Appointments(5001L)
Changes only the given properties – here the technician.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"ContactId": 3003
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Appointments/@Element",
"Id": "5001",
"Version": 2,
"State": "NotVisited",
"Type": "Standard",
"AppointmentType": "Standard",
"CreatedAt": "2026-08-25T08:00:00Z",
"EndDateTime": "2026-09-02T09:00:00Z",
"StartDateTime": "2026-09-02T07:00:00Z",
"DrivingDistanceFrom": 12,
"DrivingDistanceTo": 12,
"WasReadOnClientSide": false,
"ContactIds": [
"3003"
],
"ServiceRequestId": "1234567890",
"ContactId": "3003",
"Note": "Bring spare bearing"
}
DELETE Delete an Appointment
DELETE {{serverURL}}/Appointments(5001L)
Removes the appointment. The job stays in its current state.
Responses
204 204 No Content
No body.
Time Event 8 endpoints
Time Events are the time recordings of technicians (working, driving, pause, absences). They are the basis for time sheets and for invoicing labour.
The set is paged with 200 entries per page.
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: TimeEvents(123L). |
| Version | int | Row version, incremented on every update. Read-only. |
| State | string | Internal state of the recording (e.g. Closed). Read-only. |
| IsApproved | bool | Approved by the office (time sheet approval). |
| IsManual | bool | Entered manually (not tracked automatically on the device). |
| TimeEventType | string | Kind of time – see TimeEventType values. Required. |
| ExternalId | string | Free identifier for your own system (ERP number, foreign key, …). |
| DateModified | datetime | Date of the last modification (UTC). Read-only. |
| StartDateTime | datetime | Start (UTC). Required. |
| EndDateTime | datetime | End (UTC). Required. |
| ProposedDrivingDistance | int | Driving distance in km proposed by the system (driving events). |
| ContactId | long | Technician's contact id. Required. |
| Contact | Contact | Technician. Navigation. |
| ServiceRequestId | long | Job the time was booked on (working/driving events). |
| ServiceRequest | ServiceRequest | The job. Navigation. |
| Description | string | Free text. |
TimeEventType values
| Value | Meaning |
|---|
| eWorking | Working time on a job. |
| eDriving | Driving time. |
| ePause | Break. |
| eCustomTimeEvent | Company time / custom time type. |
| eVacation | Vacation. |
| eIllness | Illness. |
| eOther | Other (global) time. |
| eWorktimeCompensation | Overtime compensation. |
| eNotWorking | Idle. |
Endpoints
GET Get Time Events
GET {{serverURL}}/TimeEvents?$filter=StartDateTime ge datetime'2026-09-01T00:00:00Z'&$expand=Contact&$orderby=StartDateTime
Time recordings from a date on, with the technician. 200 per page – follow odata.nextLink.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#TimeEvents",
"value": [
{
"Id": "13001",
"Version": 1,
"State": "Closed",
"IsApproved": false,
"IsManual": false,
"TimeEventType": "eWorking",
"DateModified": "2026-08-25T08:00:00Z",
"StartDateTime": "2026-09-02T07:15:00Z",
"EndDateTime": "2026-09-02T09:05:00Z",
"ProposedDrivingDistance": 0,
"ContactId": "3002",
"ServiceRequestId": "1234567890",
"Description": "Bearing replaced",
"Contact": {
"Id": "3002",
"FirstName": "Max",
"LastName": "Mustermann"
}
}
],
"odata.nextLink": "https://portal.mobilefieldreport.com/odata/TimeEvents?$filter=StartDateTime ge datetime'2026-09-01T00:00:00Z'&$expand=Contact&$orderby=StartDateTime&$skip=200"
}
GET Get Time Events of a Service Request
GET {{serverURL}}/TimeEvents?$filter=ServiceRequestId eq 1234567890L
All recordings booked on a job (alternative: ServiceRequests(id)?$expand=TimeEvents).
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#TimeEvents",
"value": [
{
"Id": "13001",
"Version": 1,
"State": "Closed",
"IsApproved": false,
"IsManual": false,
"TimeEventType": "eWorking",
"DateModified": "2026-08-25T08:00:00Z",
"StartDateTime": "2026-09-02T07:15:00Z",
"EndDateTime": "2026-09-02T09:05:00Z",
"ProposedDrivingDistance": 0,
"ContactId": "3002",
"ServiceRequestId": "1234567890",
"Description": "Bearing replaced"
},
{
"Id": "13002",
"Version": 1,
"State": "Closed",
"IsApproved": false,
"IsManual": false,
"TimeEventType": "eDriving",
"DateModified": "2026-08-25T08:00:00Z",
"StartDateTime": "2026-09-02T06:40:00Z",
"EndDateTime": "2026-09-02T07:15:00Z",
"ProposedDrivingDistance": 12,
"ContactId": "3002",
"ServiceRequestId": "1234567890",
"Description": null
}
]
}
GET Get Time Events of a Technician
GET {{serverURL}}/TimeEvents?$filter=ContactId eq 3002L and StartDateTime ge datetime'2026-09-01T00:00:00Z' and StartDateTime lt datetime'2026-10-01T00:00:00Z'
Monthly time sheet of one technician.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#TimeEvents",
"value": [
{
"Id": "13001",
"Version": 1,
"State": "Closed",
"IsApproved": false,
"IsManual": false,
"TimeEventType": "eWorking",
"DateModified": "2026-08-25T08:00:00Z",
"StartDateTime": "2026-09-02T07:15:00Z",
"EndDateTime": "2026-09-02T09:05:00Z",
"ProposedDrivingDistance": 0,
"ContactId": "3002",
"ServiceRequestId": "1234567890",
"Description": "Bearing replaced"
}
]
}
GET Retrieve a Time Event
GET {{serverURL}}/TimeEvents(13001L)
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#TimeEvents/@Element",
"Id": "13001",
"Version": 1,
"State": "Closed",
"IsApproved": false,
"IsManual": false,
"TimeEventType": "eWorking",
"DateModified": "2026-08-25T08:00:00Z",
"StartDateTime": "2026-09-02T07:15:00Z",
"EndDateTime": "2026-09-02T09:05:00Z",
"ProposedDrivingDistance": 0,
"ContactId": "3002",
"ServiceRequestId": "1234567890",
"Description": "Bearing replaced"
}
POST Create a Time Event
POST {{serverURL}}/TimeEvents
Books time for a technician.
| Body | Type | Description |
|---|
| TimeEventType | string | Required. |
| ContactId | long | Required. Technician's contact id. |
| StartDateTime / EndDateTime | datetime | Required, UTC. |
| ServiceRequestId | long | Required for eWorking / eDriving. |
| IsManual, IsApproved, Description, ExternalId | | Optional. |
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"TimeEventType": "eWorking",
"ContactId": 3002,
"ServiceRequestId": 1234567890,
"StartDateTime": "2026-09-02T07:15:00Z",
"EndDateTime": "2026-09-02T09:05:00Z",
"IsManual": true,
"Description": "Bearing replaced"
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#TimeEvents/@Element",
"Id": "13001",
"Version": 1,
"State": "Closed",
"IsApproved": false,
"IsManual": true,
"TimeEventType": "eWorking",
"DateModified": "2026-08-25T08:00:00Z",
"StartDateTime": "2026-09-02T07:15:00Z",
"EndDateTime": "2026-09-02T09:05:00Z",
"ProposedDrivingDistance": 0,
"ContactId": "3002",
"ServiceRequestId": "1234567890",
"Description": "Bearing replaced"
}
PUT Update a Time Event (PUT)
PUT {{serverURL}}/TimeEvents(13001L)
Replaces the recording – e.g. to correct times or approve it (IsApproved). GET first and send the full object.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 13001,
"TimeEventType": "eWorking",
"ContactId": 3002,
"ServiceRequestId": 1234567890,
"StartDateTime": "2026-09-02T07:00:00Z",
"EndDateTime": "2026-09-02T09:00:00Z",
"IsApproved": true,
"IsManual": true,
"Description": "Bearing replaced"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#TimeEvents/@Element",
"Id": "13001",
"Version": 2,
"State": "Closed",
"IsApproved": true,
"IsManual": true,
"TimeEventType": "eWorking",
"DateModified": "2026-08-25T08:00:00Z",
"StartDateTime": "2026-09-02T07:00:00Z",
"EndDateTime": "2026-09-02T09:00:00Z",
"ProposedDrivingDistance": 0,
"ContactId": "3002",
"ServiceRequestId": "1234567890",
"Description": "Bearing replaced"
}
PATCH Approve a Time Event (PATCH)
PATCH {{serverURL}}/TimeEvents(13001L)
Partial update – only IsApproved is changed.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"IsApproved": true
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#TimeEvents/@Element",
"Id": "13001",
"Version": 2,
"State": "Closed",
"IsApproved": true,
"IsManual": false,
"TimeEventType": "eWorking",
"DateModified": "2026-08-25T08:00:00Z",
"StartDateTime": "2026-09-02T07:15:00Z",
"EndDateTime": "2026-09-02T09:05:00Z",
"ProposedDrivingDistance": 0,
"ContactId": "3002",
"ServiceRequestId": "1234567890",
"Description": "Bearing replaced"
}
DELETE Delete a Time Event
DELETE {{serverURL}}/TimeEvents(13001L)
Responses
204 204 No Content
No body.
Step 10 endpoints
Steps are the checklist items of a service request (or of a step list template). The technician works through them on the mobile app; results (choice, value, text, photo, signature) end up in Data and Attachments.
GET Steps without a key is not supported – load steps through the job: ServiceRequests(id)?$expand=Steps (add Steps/Attachments or Steps/StepListTemplate when needed). $select is not available on steps.
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Steps(123L). |
| MobileId | long | Id used by the mobile app while offline. Read-only. |
| Version | int | Row version, incremented on every update. Read-only. |
| Name | string | Title shown to the technician. Required. |
| IsDone | bool | Step completed. |
| IsVisible | bool | Step visible on the mobile app (hidden steps hold data only). |
| HasError | bool | Technician marked a defect / the chosen option is flagged as error. |
| TrackingId | string | Your stable identifier for the step (used to find the same step across jobs and in report definitions). |
| Type | string | Step type – see Type values. Required. |
| SortOrder | int | Position within the checklist / group. |
| Data | string | JSON string with the step definition and the captured value (see Data format). |
| DateModifiedOffline | datetime | Last change on the device. Read-only. |
| ServiceRequestId | long | Job the step belongs to. Required on create (unless the step belongs to a template). |
| Description | string | Instruction text (HTML allowed). |
| Comment | string | Comment entered by the technician. |
| InternalComment | string | Internal comment (office). |
| ServiceObjectId | long | Service object the step refers to (custom-value steps). |
| ServiceRequest | ServiceRequest | The job. Navigation. |
| ServiceObject | ServiceObject | Service object. Navigation. |
| StepListTemplateId | long | Template the step was created from. |
| StepListTemplate | StepListTemplate | Template. Navigation. |
| ParentId | long | Id of the parent Group step. |
| Parent | Step | Parent step. Navigation. |
| Attachments | Attachment[] | Photos / signatures. Navigation – $expand=Attachments. |
Type values
| Value | Meaning |
|---|
| Choice | Single choice from a list of options (Data.fields[0].enumeration). |
| EnterValue | Numeric value (meter reading, measurement). |
| EnterText | Free text. |
| Picture | Photo(s) – stored as attachments. |
| SignDocument | Signature. |
| Material | Material / items used. |
| Group | Container for child steps (ParentId). |
| CustomStep | Custom form defined by Data. |
| Action | Triggers an action (e.g. open a report). |
Data format
Data is a JSON string. For a Choice step:
{
"fields": [{
"isRequired": true,
"name": "Result",
"type": "choice",
"enumeration": "OK;Defect;Not checked",
"errorlist": "false;true;false"
}],
"custom": null
}
enumeration – options separated by ;.errorlist – for each option whether choosing it sets HasError.- After the technician answered, the chosen value is stored in the same JSON (
"value"). For EnterValue / EnterText steps the value is in fields[0].value; SignDocument uses { "isRequired": 1 }.
Endpoints
GET Get Steps of a Service Request
GET {{serverURL}}/ServiceRequests(1234567890L)?$expand=Steps/Attachments&$select=Id,Name,Steps
Steps are loaded through the job (the plain Steps collection is not queryable). Steps/Attachments includes photos and signatures.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests/@Element",
"Id": "1234567890",
"Name": "Repair heating pump",
"Steps": [
{
"Id": "7001",
"Version": 1,
"Name": "Check bearing",
"IsDone": false,
"IsVisible": true,
"HasError": false,
"TrackingId": "CHK1",
"Type": "Choice",
"SortOrder": 0,
"Data": "{\"fields\":[{\"isRequired\":true,\"name\":\"Result\",\"type\":\"choice\",\"enumeration\":\"OK;Defect;Not checked\",\"errorlist\":\"false;true;false\"}],\"custom\":null}",
"DateModifiedOffline": "2026-08-25T08:00:00Z",
"ServiceRequestId": "1234567890",
"Description": "<p>Listen for grinding noise.</p>",
"Attachments": []
},
{
"Id": "7002",
"Version": 1,
"Name": "Photo after repair",
"IsDone": true,
"IsVisible": true,
"HasError": false,
"TrackingId": "PHOTO",
"Type": "Picture",
"SortOrder": 1,
"DateModifiedOffline": "2026-08-25T08:00:00Z",
"ServiceRequestId": "1234567890",
"Attachments": [
{
"Id": "14001",
"FileName": "IMG_0042.jpg",
"ContentType": "image/jpeg",
"URI": "https://portal.mobilefieldreport.com/mfr/Attachment/14001/Content",
"StepId": "7002",
"UploadDate": "2026-08-25T08:00:00Z"
}
]
}
]
}
GET Retrieve a Step
GET {{serverURL}}/Steps(7001L)?$expand=Attachments,StepListTemplate
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Steps/@Element",
"Id": "7001",
"Version": 1,
"Name": "Check bearing",
"IsDone": false,
"IsVisible": true,
"HasError": false,
"TrackingId": "CHK1",
"Type": "Choice",
"SortOrder": 0,
"Data": "{\"fields\":[{\"isRequired\":true,\"name\":\"Result\",\"type\":\"choice\",\"enumeration\":\"OK;Defect;Not checked\",\"errorlist\":\"false;true;false\"}],\"custom\":null}",
"DateModifiedOffline": "2026-08-25T08:00:00Z",
"ServiceRequestId": "1234567890",
"Description": "<p>Listen for grinding noise.</p>",
"Attachments": []
}
404 404 Not Found
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "The entity Step with Key: 7001 can not be found"
}
}
}
GET Get Attachments of a Step
GET {{serverURL}}/Steps(7001L)/Attachments
Photos / signatures captured on the step. See the Attachment chapter for uploads.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Attachments",
"value": [
{
"Id": "14001",
"Version": 1,
"FileName": "IMG_0042.jpg",
"ContentType": "image/jpeg",
"URI": "https://portal.mobilefieldreport.com/mfr/Attachment/14001/Content",
"StepId": "7001",
"UploadDate": "2026-08-25T08:00:00Z"
}
]
}
POST Create a Step in a Service Request
POST {{serverURL}}/Steps
Adds a checklist step to a job.
| Body | Type | Description |
|---|
| ServiceRequestId | long | Required. |
| Name | string | Required. |
| Type | string | Required – see Type values. |
| TrackingId | string | Recommended: stable id for reporting. |
| SortOrder | int | Position. |
| ParentId | long | Put the step inside a Group step. |
| Data | string | Step definition JSON (required for Choice). |
| Description, Comment, IsVisible | | Optional. |
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"ServiceRequestId": 1234567890,
"Name": "Pressure (bar)",
"Type": "EnterValue",
"TrackingId": "PRESS",
"SortOrder": 1,
"Description": "<p>Read the manometer.</p>"
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Steps/@Element",
"Id": "7003",
"Version": 1,
"Name": "Pressure (bar)",
"IsDone": false,
"IsVisible": true,
"HasError": false,
"TrackingId": "PRESS",
"Type": "EnterValue",
"SortOrder": 1,
"DateModifiedOffline": "2026-08-25T08:00:00Z",
"ServiceRequestId": "1234567890",
"Description": "<p>Read the manometer.</p>"
}
POST Create a Choice Step
POST {{serverURL}}/Steps
A Choice step needs the options in Data (JSON string, see Data format).
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"ServiceRequestId": 1234567890,
"Name": "Check bearing",
"Type": "Choice",
"TrackingId": "CHK1",
"SortOrder": 0,
"Data": "{\"fields\":[{\"isRequired\":true,\"name\":\"Result\",\"type\":\"choice\",\"enumeration\":\"OK;Defect;Not checked\",\"errorlist\":\"false;true;false\"}],\"custom\":null}"
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Steps/@Element",
"Id": "7001",
"Version": 1,
"Name": "Check bearing",
"IsDone": false,
"IsVisible": true,
"HasError": false,
"TrackingId": "CHK1",
"Type": "Choice",
"SortOrder": 0,
"Data": "{\"fields\":[{\"isRequired\":true,\"name\":\"Result\",\"type\":\"choice\",\"enumeration\":\"OK;Defect;Not checked\",\"errorlist\":\"false;true;false\"}],\"custom\":null}",
"DateModifiedOffline": "2026-08-25T08:00:00Z",
"ServiceRequestId": "1234567890",
"Description": "<p>Listen for grinding noise.</p>"
}
POST Create a Step inside a Group
POST {{serverURL}}/Steps
Same as Create a Step, plus ParentId pointing to an existing Group step of the same job.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"ServiceRequestId": 1234567890,
"ParentId": 7010,
"Name": "Oil level",
"Type": "Choice",
"TrackingId": "OIL",
"SortOrder": 0,
"Data": "{\"fields\":[{\"isRequired\":true,\"name\":\"Oil level\",\"type\":\"choice\",\"enumeration\":\"OK;Low\",\"errorlist\":\"false;true\"}],\"custom\":null}"
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Steps/@Element",
"Id": "7011",
"Version": 1,
"Name": "Oil level",
"IsDone": false,
"IsVisible": true,
"HasError": false,
"TrackingId": "OIL",
"Type": "Choice",
"SortOrder": 0,
"DateModifiedOffline": "2026-08-25T08:00:00Z",
"ServiceRequestId": "1234567890",
"ParentId": "7010"
}
POST Batch create Steps
POST {{serverURL}}/$batch
Creates several steps in one HTTP request. An OData batch is a multipart/mixed body; operations inside a changeset are executed atomically (all or nothing). Every part is a full HTTP request (POST {{serverURL}}/Steps HTTP/1.1 plus headers and JSON body). Use Content-ID to correlate the responses, which come back as a multipart/mixed document with one part per operation.
Batches count as a single write for rate limiting, which makes them the preferred way to push whole checklists.
Headers
| Header | Value |
|---|
| Content-Type | multipart/mixed; boundary=batch_36522ad7-fc75-4b56-8c71-56071383e77b |
| Accept | multipart/mixed |
Request body
--batch_36522ad7-fc75-4b56-8c71-56071383e77b
Content-Type: multipart/mixed; boundary=changeset_77162fcd-b8da-41ac-a9f8-9357efbbd621
--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd621
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1
POST {{serverURL}}/Steps HTTP/1.1
Content-Type: application/json
{ "Type": "Group", "Name": "Inspection", "TrackingId": "GRP1", "SortOrder": 0, "ServiceRequestId": 1234567890 }
--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd621
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 2
POST {{serverURL}}/Steps HTTP/1.1
Content-Type: application/json
{ "Type": "EnterValue", "Name": "Pressure (bar)", "TrackingId": "PRESS", "SortOrder": 1, "ServiceRequestId": 1234567890 }
--changeset_77162fcd-b8da-41ac-a9f8-9357efbbd621--
--batch_36522ad7-fc75-4b56-8c71-56071383e77b--
Responses
202 202 Accepted
--batchresponse_9a1f...
Content-Type: multipart/mixed; boundary=changesetresponse_2b7c...
--changesetresponse_2b7c...
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1
HTTP/1.1 201 Created
Content-Type: application/json;odata=minimalmetadata
{"odata.metadata":"https://portal.mobilefieldreport.com/odata/$metadata#Steps/@Element","Id":"7020","Name":"Inspection","Type":"Group", ...}
--changesetresponse_2b7c...
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 2
HTTP/1.1 201 Created
Content-Type: application/json;odata=minimalmetadata
{"odata.metadata":"https://portal.mobilefieldreport.com/odata/$metadata#Steps/@Element","Id":"7021","Name":"Pressure (bar)","Type":"EnterValue", ...}
--changesetresponse_2b7c...--
--batchresponse_9a1f...--
PUT Update a Step (PUT)
PUT {{serverURL}}/Steps(7001L)
Replaces the step. GET the step first and send the complete object back – otherwise Data and other values are lost.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 7001,
"Version": 1,
"Name": "Check bearing",
"IsDone": true,
"IsVisible": true,
"HasError": false,
"TrackingId": "CHK1",
"Type": "Choice",
"SortOrder": 0,
"Data": "{\"fields\":[{\"isRequired\":true,\"name\":\"Result\",\"type\":\"choice\",\"enumeration\":\"OK;Defect;Not checked\",\"errorlist\":\"false;true;false\",\"value\":\"OK\"}],\"custom\":null}",
"DateModifiedOffline": "2026-08-25T08:00:00Z",
"ServiceRequestId": "1234567890",
"Description": "<p>Listen for grinding noise.</p>",
"Comment": "Bearing replaced"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Steps/@Element",
"Id": "7001",
"Version": 2,
"Name": "Check bearing",
"IsDone": true,
"IsVisible": true,
"HasError": false,
"TrackingId": "CHK1",
"Type": "Choice",
"SortOrder": 0,
"Data": "{\"fields\":[{\"isRequired\":true,\"name\":\"Result\",\"type\":\"choice\",\"enumeration\":\"OK;Defect;Not checked\",\"errorlist\":\"false;true;false\"}],\"custom\":null}",
"DateModifiedOffline": "2026-08-25T08:00:00Z",
"ServiceRequestId": "1234567890",
"Description": "<p>Listen for grinding noise.</p>",
"Comment": "Bearing replaced"
}
PATCH Complete a Step (PATCH)
PATCH {{serverURL}}/Steps(7001L)
Partial update – marks the step done without touching Data.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"IsDone": true,
"Comment": "Bearing replaced"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Steps/@Element",
"Id": "7001",
"Version": 2,
"Name": "Check bearing",
"IsDone": true,
"IsVisible": true,
"HasError": false,
"TrackingId": "CHK1",
"Type": "Choice",
"SortOrder": 0,
"Data": "{\"fields\":[{\"isRequired\":true,\"name\":\"Result\",\"type\":\"choice\",\"enumeration\":\"OK;Defect;Not checked\",\"errorlist\":\"false;true;false\"}],\"custom\":null}",
"DateModifiedOffline": "2026-08-25T08:00:00Z",
"ServiceRequestId": "1234567890",
"Description": "<p>Listen for grinding noise.</p>",
"Comment": "Bearing replaced"
}
DELETE Delete a Step
DELETE {{serverURL}}/Steps(7001L)
Deletes the step (and, for a group, its children).
Responses
204 204 No Content
No body.
Item 8 endpoints
Items are the material and service positions booked on a service request (and on offers, orders and invoice drafts). They are the basis of reports and invoices.
GET Items without a key is not supported – load items through the job: ServiceRequests(id)?$expand=Items/ItemType. $select is not available on items.
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Items(123L). |
| Version | int | Row version, incremented on every update. Read-only. |
| QuantityHours | decimal | Quantity used (pieces, hours, metres – depends on the unit). |
| DateModified | datetime | Date of the last modification (UTC). Read-only. |
| PlannedQuantityHours | decimal | Planned quantity (from the offer / planning). |
| ItemTypeId | long | Article the item is based on (copies name, price, VAT when given). |
| ItemNumber | string | Article number. |
| TrackingId | string | Your stable identifier (e.g. offer position). |
| Manufacture | string | Manufacturer. |
| Price | decimal | Selling price per unit (net). |
| Costs | decimal | Purchase price per unit. |
| NameOrNumber | string | Name shown on the job / invoice. Required if no ItemTypeId. |
| CustomValues | CustomValue[] | Custom field values: [{ "Meta": "<field name>", "Value": "<value>" }]. |
| Note | string | Free text / description line. |
| ExternalId | string | Free identifier for your own system (ERP number, foreign key, …). |
| Discount | decimal | Discount in percent. |
| VAT | decimal | VAT rate in percent. 0 is treated as not set (falls back to the article/account rate) unless the header X-TreatZeroVatAsValid: true is sent. |
| IsManual | bool | Entered manually by the technician (not from the article master). |
| SortOrder | int | Position on the item list. |
| ItemType | ItemType | Article. Navigation. |
| Type | string | Kind – see Item Type → Type values. |
| ServiceRequestId | long | Job. Required. |
| ParentId | long | Parent item for set components. |
| ServiceRequest | ServiceRequest | The job. Navigation. |
| ServiceObjectId | long | Service object the material was used on. Set automatically from the job. |
| ServiceObject | ServiceObject | Service object. Navigation. |
| CreatorId | long | Contact who booked the item. Defaults to the API user. |
| Creator | Contact | Creator. Navigation. |
| UnitId | long | Unit. |
| UnitString | string | Unit name. Read-only. |
| Unit | ItemUnit | Unit. Navigation. |
Endpoints
GET Get Items of a Service Request
GET {{serverURL}}/ServiceRequests(1234567890L)?$expand=Items/ItemType&$select=Id,Name,Items
Items are loaded through the job. Include Items/ItemType for the article master data, Items/Unit for units.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests/@Element",
"Id": "1234567890",
"Name": "Repair heating pump",
"Items": [
{
"Id": "17001",
"Version": 1,
"QuantityHours": "2",
"DateModified": "2026-08-25T08:00:00Z",
"PlannedQuantityHours": "2",
"ItemTypeId": "15001",
"ItemNumber": "BB-6204",
"Price": "8.90",
"Costs": "3.10",
"NameOrNumber": "Ball bearing 6204",
"CustomValues": [],
"ExternalId": "BB-6204",
"Discount": "0",
"VAT": "19",
"IsManual": false,
"SortOrder": 0,
"Type": "Material",
"ServiceRequestId": "1234567890",
"ServiceObjectId": "4001",
"CreatorId": "3002",
"UnitId": "16001",
"UnitString": "pcs",
"ItemType": {
"Id": "15001",
"NameOrNumber": "Ball bearing 6204",
"ExternalId": "BB-6204",
"Type": "Material"
}
},
{
"Id": "17002",
"Version": 1,
"QuantityHours": "1.5",
"DateModified": "2026-08-25T08:00:00Z",
"PlannedQuantityHours": "0",
"Price": "65.00",
"Costs": "0",
"NameOrNumber": "Labour",
"CustomValues": [],
"Discount": "0",
"VAT": "19",
"IsManual": true,
"SortOrder": 1,
"Type": "Service",
"ServiceRequestId": "1234567890",
"CreatorId": "3002",
"UnitString": "h"
}
]
}
GET Retrieve an Item
GET {{serverURL}}/Items(17001L)?$expand=ItemType,Unit
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Items/@Element",
"Id": "17001",
"Version": 1,
"QuantityHours": "2",
"DateModified": "2026-08-25T08:00:00Z",
"PlannedQuantityHours": "2",
"ItemTypeId": "15001",
"ItemNumber": "BB-6204",
"Price": "8.90",
"Costs": "3.10",
"NameOrNumber": "Ball bearing 6204",
"CustomValues": [],
"ExternalId": "BB-6204",
"Discount": "0",
"VAT": "19",
"IsManual": false,
"SortOrder": 0,
"Type": "Material",
"ServiceRequestId": "1234567890",
"ServiceObjectId": "4001",
"CreatorId": "3002",
"UnitId": "16001",
"UnitString": "pcs"
}
404 404 Not Found
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "The entity Item with Key: 17001 can not be found"
}
}
}
POST Create an Item from an Item Type
POST {{serverURL}}/Items
Books an article on a job. Name, price, VAT and unit are copied from the article when not given.
| Body | Type | Description |
|---|
| ServiceRequestId | long | Required. |
| ItemTypeId | long | Article to copy from. |
| QuantityHours | decimal | Quantity used. Default 0. |
| PlannedQuantityHours | decimal | Planned quantity. |
| NameOrNumber, Price, Costs, VAT, Discount, UnitId, Note, ExternalId, TrackingId, SortOrder | | Override the article values. |
VAT 0: a VAT of 0 is interpreted as "not specified" and replaced by the article / account rate. Send the header X-TreatZeroVatAsValid: true if the position really is VAT-free.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"ServiceRequestId": 1234567890,
"ItemTypeId": 15001,
"QuantityHours": 2,
"PlannedQuantityHours": 2
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Items/@Element",
"Id": "17001",
"Version": 1,
"QuantityHours": "2",
"DateModified": "2026-08-25T08:00:00Z",
"PlannedQuantityHours": "2",
"ItemTypeId": "15001",
"ItemNumber": "BB-6204",
"Price": "8.90",
"Costs": "3.10",
"NameOrNumber": "Ball bearing 6204",
"CustomValues": [],
"ExternalId": "BB-6204",
"Discount": "0",
"VAT": "19",
"IsManual": false,
"SortOrder": 0,
"Type": "Material",
"ServiceRequestId": "1234567890",
"ServiceObjectId": "4001",
"CreatorId": "3002",
"UnitId": "16001",
"UnitString": "pcs"
}
POST Create a manual Item (no Item Type)
POST {{serverURL}}/Items
A free position without an article. Here X-TreatZeroVatAsValid keeps the 0 % VAT.
Headers
| Header | Value |
|---|
| X-TreatZeroVatAsValid | true |
| Content-Type | application/json |
Request body
{
"ServiceRequestId": 1234567890,
"NameOrNumber": "Disposal fee",
"Type": "Service",
"QuantityHours": 1,
"Price": 25,
"VAT": 0,
"Note": "Old bearing disposal"
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Items/@Element",
"Id": "17003",
"Version": 1,
"QuantityHours": "1",
"DateModified": "2026-08-25T08:00:00Z",
"PlannedQuantityHours": "0",
"Price": "25.00",
"Costs": "0",
"NameOrNumber": "Disposal fee",
"CustomValues": [],
"Note": "Old bearing disposal",
"Discount": "0",
"VAT": "0",
"IsManual": true,
"SortOrder": 2,
"Type": "Service",
"ServiceRequestId": "1234567890",
"CreatorId": "3001"
}
PUT Update an Item (PUT)
PUT {{serverURL}}/Items(17001L)
Replaces the item. Id and ServiceRequestId must be present; GET first and send the complete object.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 17001,
"Version": 1,
"QuantityHours": 3,
"DateModified": "2026-08-25T08:00:00Z",
"PlannedQuantityHours": "2",
"ItemTypeId": "15001",
"ItemNumber": "BB-6204",
"Price": "8.90",
"Costs": "3.10",
"NameOrNumber": "Ball bearing 6204",
"CustomValues": [],
"ExternalId": "BB-6204",
"Discount": "0",
"VAT": "19",
"IsManual": false,
"SortOrder": 0,
"Type": "Material",
"ServiceRequestId": "1234567890",
"ServiceObjectId": "4001",
"CreatorId": "3002",
"UnitId": "16001",
"UnitString": "pcs"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Items/@Element",
"Id": "17001",
"Version": 2,
"QuantityHours": "3",
"DateModified": "2026-08-25T08:00:00Z",
"PlannedQuantityHours": "2",
"ItemTypeId": "15001",
"ItemNumber": "BB-6204",
"Price": "8.90",
"Costs": "3.10",
"NameOrNumber": "Ball bearing 6204",
"CustomValues": [],
"ExternalId": "BB-6204",
"Discount": "0",
"VAT": "19",
"IsManual": false,
"SortOrder": 0,
"Type": "Material",
"ServiceRequestId": "1234567890",
"ServiceObjectId": "4001",
"CreatorId": "3002",
"UnitId": "16001",
"UnitString": "pcs"
}
PATCH Update Quantity (PATCH)
PATCH {{serverURL}}/Items(17001L)
Partial update of an item.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"QuantityHours": 3
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Items/@Element",
"Id": "17001",
"Version": 2,
"QuantityHours": "3",
"DateModified": "2026-08-25T08:00:00Z",
"PlannedQuantityHours": "2",
"ItemTypeId": "15001",
"ItemNumber": "BB-6204",
"Price": "8.90",
"Costs": "3.10",
"NameOrNumber": "Ball bearing 6204",
"CustomValues": [],
"ExternalId": "BB-6204",
"Discount": "0",
"VAT": "19",
"IsManual": false,
"SortOrder": 0,
"Type": "Material",
"ServiceRequestId": "1234567890",
"ServiceObjectId": "4001",
"CreatorId": "3002",
"UnitId": "16001",
"UnitString": "pcs"
}
DELETE Delete an Item
DELETE {{serverURL}}/Items(17001L)
Removes the position from the job.
Responses
204 204 No Content
No body.
POST Action: Apply Price List
POST {{serverURL}}/Items/ApplyPriceList
Collection action: re-prices the given items with the customer's price list (customer-specific prices / discounts). Returns the number of updated items.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"itemIds": [
17001,
17002
]
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Edm.Int32",
"value": 2
}
Document 11 endpoints
Documents are files (PDF, images, manuals, …) or links attached to service requests and service objects. The technician sees them on the mobile app.
Binary content does not travel through OData. Workflow:
- Upload the file with
POST {{baseURL}}/mfr/Document/UploadAndCreate (multipart, field Filedata) → returns the document with its Id. - Attach it:
POST ServiceRequests(id)/$links/Documents, PUT {{baseURL}}/mfr/ServiceRequest/{id}/Document/{documentId} or PUT {{baseURL}}/mfr/ServiceObject/{id}/Document/{documentId}. - Download it later through the
URI property (authenticated).
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Documents(123L). |
| CustomValues | CustomValue[] | Custom field values: [{ "Meta": "<field name>", "Value": "<value>" }]. |
| Version | int | Row version, incremented on every update. Read-only. |
| State | string | Internal state. Read-only. |
| ExternalId | string | Free identifier for your own system (ERP number, foreign key, …). |
| URI | string | Download URL of the file (or the target URL if IsLink). Read-only for uploads. |
| IsGlobal | bool | Global document (available on every job, e.g. safety instructions). |
| StartDateTime | datetime | Validity start (global documents). |
| EndDateTime | datetime | Validity end (global documents). |
| FileName | string | File name shown to the user. |
| DateModified | datetime | Date of the last modification (UTC). Read-only. |
| UploadDate | datetime | Upload timestamp. Read-only. |
| IsLink | bool | true if the document is a link to an external URL instead of an uploaded file. |
| ContentType | string | MIME type. |
| HTMLCode | string | Embedded HTML (link documents). |
| ServiceRequestId | long | Job the document is attached to (documents may also be linked to several jobs via $links). |
| ServiceRequest | ServiceRequest | The job. Navigation. |
| Note | string | Description. |
Endpoints
GET Get Documents
GET {{serverURL}}/Documents?$filter=DateModified gt datetime'2026-08-01T00:00:00Z'&$orderby=DateModified desc
Lists documents (paged). Documents of one job: ServiceRequests(id)?$expand=Documents.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Documents",
"value": [
{
"Id": "10001",
"CustomValues": [],
"Version": 1,
"URI": "https://portal.mobilefieldreport.com/mfr/Document/10001/Content",
"IsGlobal": false,
"FileName": "manual-x200.pdf",
"DateModified": "2026-08-25T08:00:00Z",
"UploadDate": "2026-08-25T08:00:00Z",
"IsLink": false,
"ContentType": "application/pdf",
"Note": "Installation manual"
}
]
}
GET Get Global Documents
GET {{serverURL}}/Documents?$filter=IsGlobal eq true
Documents that are available on every job.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Documents",
"value": [
{
"Id": "10002",
"CustomValues": [],
"Version": 1,
"URI": "https://portal.mobilefieldreport.com/mfr/Document/10001/Content",
"IsGlobal": true,
"FileName": "safety-instructions.pdf",
"DateModified": "2026-08-25T08:00:00Z",
"UploadDate": "2026-08-25T08:00:00Z",
"IsLink": false,
"ContentType": "application/pdf",
"Note": "Safety instructions"
}
]
}
GET Retrieve a Document
GET {{serverURL}}/Documents(10001L)
Metadata of one document. Download the content from URI with the same credentials.
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Documents/@Element",
"Id": "10001",
"CustomValues": [],
"Version": 1,
"URI": "https://portal.mobilefieldreport.com/mfr/Document/10001/Content",
"IsGlobal": false,
"FileName": "manual-x200.pdf",
"DateModified": "2026-08-25T08:00:00Z",
"UploadDate": "2026-08-25T08:00:00Z",
"IsLink": false,
"ContentType": "application/pdf",
"Note": "Installation manual"
}
POST Upload a Document (REST)
POST {{baseURL}}/mfr/Document/UploadAndCreate
Uploads a file and creates the document record. Send multipart/form-data with one file part (field name Filedata); the part's file name and content type become FileName / ContentType of the document.
Limits: 10 parallel uploads per user. Returns the created document as JSON (same shape as the OData entity, without the odata.metadata property). Then link it to a job or service object and set Note / ExternalId with PATCH Documents(id) if needed.
Request body (multipart/form-data)
| Field | Type | Value |
|---|
| Filedata | file | (file) |
Responses
200 200 OK
{
"Id": "10003",
"CustomValues": [],
"Version": 1,
"URI": "https://portal.mobilefieldreport.com/mfr/Document/10001/Content",
"IsGlobal": false,
"FileName": "manual-x200.pdf",
"DateModified": "2026-08-25T08:00:00Z",
"UploadDate": "2026-08-25T08:00:00Z",
"IsLink": false,
"ContentType": "application/pdf",
"Note": "Installation manual",
"Tags": [],
"IsBlobUri": true,
"FileSize": 482113
}
POST Create a Link Document
POST {{serverURL}}/Documents
Creates a document that points to an external URL (no upload). ServiceRequestId attaches it to a job directly.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"FileName": "Manufacturer portal",
"URI": "https://manufacturer.example.com/x200",
"IsLink": true,
"Note": "Spare part catalogue",
"ServiceRequestId": 1234567890
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Documents/@Element",
"Id": "10004",
"CustomValues": [],
"Version": 1,
"URI": "https://manufacturer.example.com/x200",
"IsGlobal": false,
"FileName": "Manufacturer portal",
"DateModified": "2026-08-25T08:00:00Z",
"UploadDate": "2026-08-25T08:00:00Z",
"IsLink": true,
"ServiceRequestId": "1234567890",
"Note": "Spare part catalogue"
}
PUT Update a Document (PUT)
PUT {{serverURL}}/Documents(10001L)
Updates the metadata (name, note, external id, validity). The file itself cannot be replaced – upload a new document.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": "10001",
"CustomValues": [],
"Version": 1,
"URI": "https://portal.mobilefieldreport.com/mfr/Document/10001/Content",
"IsGlobal": false,
"FileName": "manual-x200.pdf",
"DateModified": "2026-08-25T08:00:00Z",
"UploadDate": "2026-08-25T08:00:00Z",
"IsLink": false,
"ContentType": "application/pdf",
"Note": "Installation manual (rev. B)",
"ExternalId": "DMS-4711"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Documents/@Element",
"Id": "10001",
"CustomValues": [],
"Version": 2,
"URI": "https://portal.mobilefieldreport.com/mfr/Document/10001/Content",
"IsGlobal": false,
"FileName": "manual-x200.pdf",
"DateModified": "2026-08-25T08:00:00Z",
"UploadDate": "2026-08-25T08:00:00Z",
"IsLink": false,
"ContentType": "application/pdf",
"Note": "Installation manual (rev. B)",
"ExternalId": "DMS-4711"
}
DELETE Delete a Document
DELETE {{serverURL}}/Documents(10001L)
Deletes the document and its file. To only detach it from a job use the REST unlink below.
Responses
204 204 No Content
No body.
PUT Attach a Document to a Service Request (REST)
PUT {{baseURL}}/mfr/ServiceRequest/1234567890/Document/10001
Links an existing document to a job. Equivalent to POST ServiceRequests(id)/$links/Documents.
Responses
200 200 OK
No body.
DELETE Detach a Document from a Service Request (REST)
DELETE {{baseURL}}/mfr/ServiceRequest/1234567890/Document/10001
Removes the link between job and document; the document itself is kept.
Responses
200 200 OK
No body.
PUT Attach a Document to a Service Object (REST)
PUT {{baseURL}}/mfr/ServiceObject/4001/Document/10001
Links an existing document to a service object (documents of the asset are visible on every job at that object).
Responses
200 200 OK
No body.
DELETE Detach a Document from a Service Object (REST)
DELETE {{baseURL}}/mfr/ServiceObject/4001/Document/10001
Removes the link between service object and document.
Responses
200 200 OK
No body.
Company 12 endpoints
A Company is a customer (or supplier). It owns contacts and service objects and is referenced by jobs (ServiceRequest.CustomerId), offers, orders and invoices.
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Companys(123L). |
| Version | int | Row version, incremented on every update. Read-only. |
| IsPhysicalPerson | bool | Private customer (person) instead of a company. |
| IsOwner | bool | The own company (account owner). Read-only. |
| IsEmailInvoicingActive | bool | Invoices are sent by e-mail. |
| IsSupplier | bool | Supplier (used for orders and purchase invoices). |
| MappingId | string | Additional mapping key for integrations. |
| ExternalId | string | Free identifier for your own system (ERP number, foreign key, …). |
| Name | string | Company name. Required. |
| Note | string | Free text. |
| BillingAddress | string | Billing address as text (when it differs from Location). |
| SupportTelephone | string | Central phone number. |
| SupportFax | string | Fax. |
| SupportMail | string | Central e-mail address. |
| QuickSearch | string | Write-only filter helper: $filter=QuickSearch eq 'text' searches name, external id, address and contacts. |
| DateOfCreation | datetime | Date of creation (UTC). Read-only. |
| DateModified | datetime | Date of the last modification (UTC). Read-only. |
| CustomValues | CustomValue[] | Custom field values: [{ "Meta": "<field name>", "Value": "<value>" }]. |
| Location | Location | Address – see Location attributes. Pass CreateGeoLocation inside Location to geocode it. |
| ContactIds | long[] | Ids of the contacts. Read-only. |
| MainContactId | long | Main contact person. |
| MainContact | Contact | Main contact. Navigation. |
| TagIds | long[] | Ids of the tags. Read-only. |
| Tags | Tag[] | Tags of type Company. Navigation (managed in the portal). |
| Contacts | Contact[] | Contact persons. Navigation – $expand=Contacts. |
| ServiceObjectIds | long[] | Ids of the service objects. Read-only. |
| ServiceObjects | ServiceObject[] | Service objects (assets) of the customer. Navigation. |
Location attributes
| Attribute | Type | Description |
|---|
| AddressString | string | Street and house number. |
| Postal | string | Postal code. |
| City | string | City. |
| State | string | State / region. |
| Country | string | Country (ISO code or name). |
| Longitude | double | Longitude (set by geocoding or by you). |
| Latitude | double | Latitude. |
| IsValidLocation | bool | Geocoding succeeded. Read-only. |
| IsMoveable | bool | Location can be changed by the technician (mobile objects). |
Filters
| Filter | Notes |
|---|
$filter=QuickSearch eq 'acme' | Full-text quick search (name, external id, address, contacts). Cannot be combined with other filters. |
$filter=ExternalId eq 'C-100' | Lookup by your id. |
$filter=IsSupplier eq true | Suppliers. |
$filter=DateModified gt datetime'…' | Delta sync. |
Endpoints
GET Get Companies
GET {{serverURL}}/Companies?$expand=Location,MainContact&$orderby=Name&$top=50
Customers with address and main contact (paged).
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Companies",
"value": [
{
"Id": "2001",
"Version": 1,
"IsPhysicalPerson": false,
"IsOwner": false,
"IsEmailInvoicingActive": true,
"IsSupplier": false,
"ExternalId": "C-100",
"Name": "ACME GmbH",
"SupportTelephone": "+49 30 1234",
"SupportMail": "office@acme.example.com",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"CustomValues": [
{
"Meta": "DebtorNumber",
"Value": "10045"
}
],
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"State": "Berlin",
"Country": "DE",
"Longitude": 13.3889,
"Latitude": 52.5323,
"IsValidLocation": true,
"IsMoveable": false
},
"MainContactId": "3100",
"MainContact": {
"Id": "3100",
"FirstName": "Erika",
"LastName": "Musterfrau",
"Email": "erika@example.com"
}
}
]
}
GET Quick Search Companies
GET {{serverURL}}/Companies?$filter=QuickSearch eq 'acme'&$expand=Location
Full-text search over name, external id, address and contact names – the same search as in the portal. Use it alone (no other filter terms).
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Companies",
"value": [
{
"Id": "2001",
"Version": 1,
"IsPhysicalPerson": false,
"IsOwner": false,
"IsEmailInvoicingActive": true,
"IsSupplier": false,
"ExternalId": "C-100",
"Name": "ACME GmbH",
"SupportTelephone": "+49 30 1234",
"SupportMail": "office@acme.example.com",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"CustomValues": [
{
"Meta": "DebtorNumber",
"Value": "10045"
}
],
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"State": "Berlin",
"Country": "DE",
"Longitude": 13.3889,
"Latitude": 52.5323,
"IsValidLocation": true,
"IsMoveable": false
},
"MainContactId": "3100"
}
]
}
GET Find a Company by External Id
GET {{serverURL}}/Companies?$filter=ExternalId eq 'C-100'
Lookup by your customer number.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Companies",
"value": [
{
"Id": "2001",
"Version": 1,
"IsPhysicalPerson": false,
"IsOwner": false,
"IsEmailInvoicingActive": true,
"IsSupplier": false,
"ExternalId": "C-100",
"Name": "ACME GmbH",
"SupportTelephone": "+49 30 1234",
"SupportMail": "office@acme.example.com",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"CustomValues": [
{
"Meta": "DebtorNumber",
"Value": "10045"
}
],
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"State": "Berlin",
"Country": "DE",
"Longitude": 13.3889,
"Latitude": 52.5323,
"IsValidLocation": true,
"IsMoveable": false
},
"MainContactId": "3100"
}
]
}
GET Retrieve a Company
GET {{serverURL}}/Companies(2001L)?$expand=Location,Contacts,ServiceObjects/Location,Tags
Customer with contacts, service objects and tags.
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Companies/@Element",
"Id": "2001",
"Version": 1,
"IsPhysicalPerson": false,
"IsOwner": false,
"IsEmailInvoicingActive": true,
"IsSupplier": false,
"ExternalId": "C-100",
"Name": "ACME GmbH",
"SupportTelephone": "+49 30 1234",
"SupportMail": "office@acme.example.com",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"CustomValues": [
{
"Meta": "DebtorNumber",
"Value": "10045"
}
],
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"State": "Berlin",
"Country": "DE",
"Longitude": 13.3889,
"Latitude": 52.5323,
"IsValidLocation": true,
"IsMoveable": false
},
"MainContactId": "3100",
"Contacts": [
{
"Id": "3100",
"FirstName": "Erika",
"LastName": "Musterfrau",
"Email": "erika@example.com",
"CompanyId": "2001"
}
],
"ServiceObjects": [
{
"Id": "4001",
"Name": "Heating pump 3",
"ExternalId": "HP-3",
"CompanyId": "2001",
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"State": "Berlin",
"Country": "DE",
"Longitude": 13.3889,
"Latitude": 52.5323,
"IsValidLocation": true,
"IsMoveable": false
}
}
],
"Tags": []
}
404 404 Not Found
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "The entity Company with Key: 2001 can not be found"
}
}
}
POST Create a Company
POST {{serverURL}}/Companies
Creates a customer.
| Body | Type | Description |
|---|
| Name | string | Required. |
| ExternalId | string | Recommended – your customer number. If a company with the same ExternalId already exists it is returned instead of creating a duplicate. |
| Location | object | Address. CreateGeoLocation: true geocodes it. |
| IsPhysicalPerson, IsSupplier, SupportTelephone, SupportMail, Note, BillingAddress, CustomValues | | Optional. |
Add contacts with POST Companies(id)/Contacts and assets with POST Companies(id)/ServiceObjects.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"Name": "ACME GmbH",
"ExternalId": "C-100",
"IsPhysicalPerson": false,
"SupportTelephone": "+49 30 1234",
"SupportMail": "office@acme.example.com",
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"Country": "DE",
"CreateGeoLocation": true
},
"CustomValues": [
{
"Meta": "DebtorNumber",
"Value": "10045"
}
]
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Companies/@Element",
"Id": "2001",
"Version": 1,
"IsPhysicalPerson": false,
"IsOwner": false,
"IsEmailInvoicingActive": true,
"IsSupplier": false,
"ExternalId": "C-100",
"Name": "ACME GmbH",
"SupportTelephone": "+49 30 1234",
"SupportMail": "office@acme.example.com",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"CustomValues": [
{
"Meta": "DebtorNumber",
"Value": "10045"
}
],
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"State": "Berlin",
"Country": "DE",
"Longitude": 13.3889,
"Latitude": 52.5323,
"IsValidLocation": true,
"IsMoveable": false
},
"MainContactId": "3100"
}
POST Create a Contact for a Company
POST {{serverURL}}/Companies(2001L)/Contacts
Creates a contact person and links it to the company (no CompanyId needed). Same body as Contact → Create a Contact.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"FirstName": "Erika",
"LastName": "Musterfrau",
"Email": "erika@example.com",
"JobTitle": "Facility manager",
"MobilePhone": "+49 170 1234",
"Gender": "Female"
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Contacts/@Element",
"Id": "3100",
"CustomValues": [],
"FirstName": "Erika",
"LastName": "Musterfrau",
"Email": "erika@example.com",
"JobTitle": "Facility manager",
"MobilePhone": "+49 170 1234",
"DateModified": "2026-08-25T08:00:00Z",
"Version": 1,
"CompanyId": "2001",
"IsUser": false,
"Gender": "Female",
"CostsPerHour": "0"
}
POST Create a Service Object for a Company
POST {{serverURL}}/Companies(2001L)/ServiceObjects
Creates an asset for the customer (no CompanyId needed). Same body as Service Object → Create a Service Object.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"Name": "Heating pump 3",
"ExternalId": "HP-3",
"Note": "Basement, room 0.12",
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"Country": "DE"
}
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceObjects/@Element",
"Id": "4001",
"Name": "Heating pump 3",
"Note": "Basement, room 0.12",
"CustomValues": [],
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"ExternalId": "HP-3",
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"State": "Berlin",
"Country": "DE",
"Longitude": 13.3889,
"Latitude": 52.5323,
"IsValidLocation": true,
"IsMoveable": false
},
"Version": 1,
"CreateGeoLocation": false,
"IsWarehouse": false,
"CompanyId": "2001",
"IsProduct": false
}
PUT Update a Company (PUT)
PUT {{serverURL}}/Companies(2001L)
Replaces the customer (GET first, send everything back). Tags, Contacts and ServiceObjects in the body are ignored.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 2001,
"Name": "ACME GmbH",
"ExternalId": "C-100",
"IsPhysicalPerson": false,
"IsSupplier": false,
"IsEmailInvoicingActive": true,
"SupportTelephone": "+49 30 5678",
"SupportMail": "office@acme.example.com",
"MainContactId": 3100,
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"Country": "DE"
},
"CustomValues": [
{
"Meta": "DebtorNumber",
"Value": "10045"
}
]
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Companies/@Element",
"Id": "2001",
"Version": 2,
"IsPhysicalPerson": false,
"IsOwner": false,
"IsEmailInvoicingActive": true,
"IsSupplier": false,
"ExternalId": "C-100",
"Name": "ACME GmbH",
"SupportTelephone": "+49 30 5678",
"SupportMail": "office@acme.example.com",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"CustomValues": [
{
"Meta": "DebtorNumber",
"Value": "10045"
}
],
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"State": "Berlin",
"Country": "DE",
"Longitude": 13.3889,
"Latitude": 52.5323,
"IsValidLocation": true,
"IsMoveable": false
},
"MainContactId": "3100"
}
PATCH Update a Company partially (PATCH)
PATCH {{serverURL}}/Companies(2001L)
Changes only the given properties.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"SupportMail": "service@acme.example.com",
"IsEmailInvoicingActive": false
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Companies/@Element",
"Id": "2001",
"Version": 2,
"IsPhysicalPerson": false,
"IsOwner": false,
"IsEmailInvoicingActive": false,
"IsSupplier": false,
"ExternalId": "C-100",
"Name": "ACME GmbH",
"SupportTelephone": "+49 30 1234",
"SupportMail": "service@acme.example.com",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"CustomValues": [
{
"Meta": "DebtorNumber",
"Value": "10045"
}
],
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"State": "Berlin",
"Country": "DE",
"Longitude": 13.3889,
"Latitude": 52.5323,
"IsValidLocation": true,
"IsMoveable": false
},
"MainContactId": "3100"
}
DELETE Delete a Company
DELETE {{serverURL}}/Companies(2001L)
Deletes the customer with its contacts and service objects. Use with care – jobs of the customer lose their customer reference.
Responses
204 204 No Content
No body.
POST Link an existing Contact to a Company
POST {{serverURL}}/Companies(2001L)/$links/Contacts
Moves / assigns an existing contact to this company.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/Contacts(3100L)"
}
Responses
204 204 No Content
No body.
DELETE Unlink a Contact from a Company
DELETE {{serverURL}}/Companies(2001L)/$links/Contacts(3100L)
Removes the contact from the company (the contact is kept). Alternative: DELETE …/$links/Contacts with { "url": "…/Contacts(3100L)" }.
Responses
204 204 No Content
No body.
Service Object 14 endpoints
A Service Object is an asset at the customer: a machine, a building, a device – the place where work is done. Jobs reference the object as Destination / ServiceObjects. Objects can form a hierarchy (ParentServiceObjectId) and can be instances of a Product.
Warehouses are special service objects – use the Warehouse set for them.
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: ServiceObjects(123L). |
| Name | string | Name of the asset. Required. |
| Note | string | Free text (location hints, access, …). |
| CustomValues | CustomValue[] | Custom field values: [{ "Meta": "<field name>", "Value": "<value>" }]. |
| DateOfCreation | datetime | Date of creation (UTC). Read-only. |
| DateModified | datetime | Date of the last modification (UTC). Read-only. |
| ExternalId | string | Free identifier for your own system (ERP number, foreign key, …). |
| MappingId | string | Additional mapping key for integrations. |
| QuickSearch | string | Write-only filter helper: $filter=QuickSearch eq 'text' searches name, external id, address and customer. |
| Location | Location | Address / coordinates. See Company → Location attributes. |
| Version | int | Row version, incremented on every update. Read-only. |
| CreateGeoLocation | bool | Write-only: geocode Location on create/update (set automatically on create). |
| IsWarehouse | bool | The object is a warehouse (see Warehouse). Read-only here. |
| WarehouseManager | Contact | Warehouse manager contact (warehouses only). Navigation. |
| ParentServiceObjectId | long | Parent object for hierarchies (building → floor → device). |
| ParentServiceObject | ServiceObject | Parent object. Navigation. |
| CustomValueSteps | Step[] | Steps of a durable checklist that store custom values of the object. Navigation. |
| CompanyId | long | Owning customer. Required on create. |
| Company | Company | Customer. Navigation. |
| IsProduct | bool | The object is an instance of a Product. |
| ProductId | long | Product the object is an instance of. |
| Product | Product | Product. Navigation. |
| ContactIds | long[] | Ids of the linked contacts. Read-only. |
| TagIds | long[] | Ids of the tags. Read-only – use $links/Tags. |
| Tags | Tag[] | Tags of type ServiceObject. Navigation. |
| ChildServiceObject | ServiceObject[] | Child objects. Navigation – or GET ServiceObjects(id)/ChildServiceObject. |
| Contacts | Contact[] | Contact persons responsible for the object. Navigation. |
| Items | Item[] | Items (spare parts) attached to the object. Navigation. |
Filters
| Filter | Notes |
|---|
$filter=QuickSearch eq 'pump' | Full-text quick search. Use it alone. |
$filter=CompanyId eq 2001L | Objects of a customer. |
$filter=ExternalId eq 'HP-3' | Lookup by your id (serial number). |
$filter=ParentServiceObjectId eq 4000L | Not supported – use ServiceObjects(4000L)/ChildServiceObject. |
Endpoints
GET Get Service Objects
GET {{serverURL}}/ServiceObjects?$expand=Location,Company&$orderby=Name&$top=50
Assets with address and customer (paged).
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceObjects",
"value": [
{
"Id": "4001",
"Name": "Heating pump 3",
"Note": "Basement, room 0.12",
"CustomValues": [
{
"Meta": "SerialNumber",
"Value": "SN-998877"
}
],
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"ExternalId": "HP-3",
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"State": "Berlin",
"Country": "DE",
"Longitude": 13.3889,
"Latitude": 52.5323,
"IsValidLocation": true,
"IsMoveable": false
},
"Version": 1,
"CreateGeoLocation": false,
"IsWarehouse": false,
"ParentServiceObjectId": "4000",
"CompanyId": "2001",
"IsProduct": false,
"Company": {
"Id": "2001",
"Name": "ACME GmbH"
}
}
]
}
GET Quick Search Service Objects
GET {{serverURL}}/ServiceObjects?$filter=QuickSearch eq 'pump'&$expand=Location
Full-text search (name, external id, address, customer). Use it without other filter terms.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceObjects",
"value": [
{
"Id": "4001",
"Name": "Heating pump 3",
"Note": "Basement, room 0.12",
"CustomValues": [
{
"Meta": "SerialNumber",
"Value": "SN-998877"
}
],
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"ExternalId": "HP-3",
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"State": "Berlin",
"Country": "DE",
"Longitude": 13.3889,
"Latitude": 52.5323,
"IsValidLocation": true,
"IsMoveable": false
},
"Version": 1,
"CreateGeoLocation": false,
"IsWarehouse": false,
"ParentServiceObjectId": "4000",
"CompanyId": "2001",
"IsProduct": false
}
]
}
GET Get Service Objects of a Company
GET {{serverURL}}/ServiceObjects?$filter=CompanyId eq 2001L&$expand=Location
All assets of one customer.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceObjects",
"value": [
{
"Id": "4001",
"Name": "Heating pump 3",
"Note": "Basement, room 0.12",
"CustomValues": [
{
"Meta": "SerialNumber",
"Value": "SN-998877"
}
],
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"ExternalId": "HP-3",
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"State": "Berlin",
"Country": "DE",
"Longitude": 13.3889,
"Latitude": 52.5323,
"IsValidLocation": true,
"IsMoveable": false
},
"Version": 1,
"CreateGeoLocation": false,
"IsWarehouse": false,
"ParentServiceObjectId": "4000",
"CompanyId": "2001",
"IsProduct": false
}
]
}
GET Retrieve a Service Object
GET {{serverURL}}/ServiceObjects(4001L)?$expand=Location,Company,Contacts,Tags,Product
Loads one asset with its relations.
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceObjects/@Element",
"Id": "4001",
"Name": "Heating pump 3",
"Note": "Basement, room 0.12",
"CustomValues": [
{
"Meta": "SerialNumber",
"Value": "SN-998877"
}
],
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"ExternalId": "HP-3",
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"State": "Berlin",
"Country": "DE",
"Longitude": 13.3889,
"Latitude": 52.5323,
"IsValidLocation": true,
"IsMoveable": false
},
"Version": 1,
"CreateGeoLocation": false,
"IsWarehouse": false,
"ParentServiceObjectId": "4000",
"CompanyId": "2001",
"IsProduct": false,
"Company": {
"Id": "2001",
"Name": "ACME GmbH"
},
"Contacts": [],
"Tags": []
}
404 404 Not Found
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "The entity ServiceObject with Key: 4001 can not be found"
}
}
}
GET Get Child Service Objects
GET {{serverURL}}/ServiceObjects(4000L)/ChildServiceObject?$expand=Location
Children of an object in the hierarchy. ($filter=ParentServiceObjectId eq … is rejected with 400 – use this navigation instead.)
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceObjects",
"value": [
{
"Id": "4001",
"Name": "Heating pump 3",
"Note": "Basement, room 0.12",
"CustomValues": [
{
"Meta": "SerialNumber",
"Value": "SN-998877"
}
],
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"ExternalId": "HP-3",
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"State": "Berlin",
"Country": "DE",
"Longitude": 13.3889,
"Latitude": 52.5323,
"IsValidLocation": true,
"IsMoveable": false
},
"Version": 1,
"CreateGeoLocation": false,
"IsWarehouse": false,
"ParentServiceObjectId": "4000",
"CompanyId": "2001",
"IsProduct": false
}
]
}
POST Create a Service Object
POST {{serverURL}}/ServiceObjects
Creates an asset. The address is geocoded automatically.
| Body | Type | Description |
|---|
| Name | string | Required. |
| CompanyId | long | Required. Owning customer. |
| ExternalId | string | Recommended – serial number / your id. |
| Location | object | Address; omit to reuse the customer's address in the portal. |
| ParentServiceObjectId | long | Attach as child of another object. |
| ProductId | long | Make it an instance of a product (custom-value checklist is applied). |
| Note, MappingId, CustomValues | | Optional. |
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"Name": "Heating pump 3",
"ExternalId": "HP-3",
"CompanyId": 2001,
"Note": "Basement, room 0.12",
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"Country": "DE"
},
"CustomValues": [
{
"Meta": "SerialNumber",
"Value": "SN-998877"
}
]
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceObjects/@Element",
"Id": "4001",
"Name": "Heating pump 3",
"Note": "Basement, room 0.12",
"CustomValues": [
{
"Meta": "SerialNumber",
"Value": "SN-998877"
}
],
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"ExternalId": "HP-3",
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"State": "Berlin",
"Country": "DE",
"Longitude": 13.3889,
"Latitude": 52.5323,
"IsValidLocation": true,
"IsMoveable": false
},
"Version": 1,
"CreateGeoLocation": false,
"IsWarehouse": false,
"CompanyId": "2001",
"IsProduct": false
}
POST Create a Child Service Object
POST {{serverURL}}/ServiceObjects
Same as Create a Service Object with ParentServiceObjectId – builds the asset hierarchy.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"Name": "Circulation pump",
"ExternalId": "HP-3-CP",
"CompanyId": 2001,
"ParentServiceObjectId": 4001
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceObjects/@Element",
"Id": "4002",
"Name": "Circulation pump",
"CustomValues": [],
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"ExternalId": "HP-3-CP",
"Version": 1,
"CreateGeoLocation": false,
"IsWarehouse": false,
"ParentServiceObjectId": "4001",
"CompanyId": "2001",
"IsProduct": false
}
PUT Update a Service Object (PUT)
PUT {{serverURL}}/ServiceObjects(4001L)
Replaces the asset (GET first, send everything back). Set CreateGeoLocation: true to re-geocode a changed address. Tags/Contacts in the body are ignored – use $links.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 4001,
"Name": "Heating pump 3",
"ExternalId": "HP-3",
"CompanyId": 2001,
"Note": "Basement, room 0.12 – key at reception",
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"Country": "DE"
},
"CreateGeoLocation": true,
"CustomValues": [
{
"Meta": "SerialNumber",
"Value": "SN-998877"
}
]
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceObjects/@Element",
"Id": "4001",
"Name": "Heating pump 3",
"Note": "Basement, room 0.12 – key at reception",
"CustomValues": [
{
"Meta": "SerialNumber",
"Value": "SN-998877"
}
],
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"ExternalId": "HP-3",
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"State": "Berlin",
"Country": "DE",
"Longitude": 13.3889,
"Latitude": 52.5323,
"IsValidLocation": true,
"IsMoveable": false
},
"Version": 2,
"CreateGeoLocation": false,
"IsWarehouse": false,
"ParentServiceObjectId": "4000",
"CompanyId": "2001",
"IsProduct": false
}
PATCH Update a Service Object partially (PATCH)
PATCH {{serverURL}}/ServiceObjects(4001L)
Changes only the given properties.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Note": "Key at reception",
"CustomValues": [
{
"Meta": "SerialNumber",
"Value": "SN-998877"
},
{
"Meta": "YearBuilt",
"Value": "2019"
}
]
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceObjects/@Element",
"Id": "4001",
"Name": "Heating pump 3",
"Note": "Key at reception",
"CustomValues": [
{
"Meta": "SerialNumber",
"Value": "SN-998877"
}
],
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"ExternalId": "HP-3",
"Location": {
"AddressString": "Hauptstraße 1",
"Postal": "10115",
"City": "Berlin",
"State": "Berlin",
"Country": "DE",
"Longitude": 13.3889,
"Latitude": 52.5323,
"IsValidLocation": true,
"IsMoveable": false
},
"Version": 2,
"CreateGeoLocation": false,
"IsWarehouse": false,
"ParentServiceObjectId": "4000",
"CompanyId": "2001",
"IsProduct": false
}
DELETE Delete a Service Object
DELETE {{serverURL}}/ServiceObjects(4001L)
Deletes the asset (and its child objects).
Responses
204 204 No Content
No body.
POST Link a Contact to a Service Object
POST {{serverURL}}/ServiceObjects(4001L)/$links/Contacts
Makes the contact the responsible person for the asset (shown to technicians on jobs at this object).
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/Contacts(3100L)"
}
Responses
204 204 No Content
No body.
DELETE Unlink a Contact from a Service Object
DELETE {{serverURL}}/ServiceObjects(4001L)/$links/Contacts(3100L)
Removes the responsibility link. Alternative: DELETE …/$links/Contacts with { "url": "…/Contacts(3100L)" }.
Responses
204 204 No Content
No body.
POST Link a Tag to a Service Object
POST {{serverURL}}/ServiceObjects(4001L)/$links/Tags
Adds a tag of type ServiceObject.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/Tags(6101L)"
}
Responses
204 204 No Content
No body.
DELETE Unlink a Tag from a Service Object
DELETE {{serverURL}}/ServiceObjects(4001L)/$links/Tags(6101L)
Responses
204 204 No Content
No body.
User 7 endpoints
Users are the people who log in to MFR: technicians (mobile) and office users. Every user has a Contact that carries name and phone numbers; appointments and time events reference that contact id, not the user id.
Passwords cannot be set through the API – a newly created user receives the invitation / password-reset flow of the portal.
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Users(123L). |
| Version | int | Row version, incremented on every update. Read-only. |
| UserName | string | Login name (e-mail address). Required on create. |
| IsSystem | bool | System account (integration user). Read-only. |
| CreationDate | datetime | Date of creation (UTC). Read-only. |
| IsApproved | bool | Account approved. Read-only. |
| ContactId | long | Contact record of the user. Required on create – create the contact first. |
| Contact | Contact | The contact (name, phone, group). Navigation. |
| PreferedLanguage | string | UI language, e.g. de-DE, en-US, fr-FR, it-IT. |
| EmailChannelEnabled | bool | Receives e-mail notifications. |
| HasFullScreenPreference | bool | UI preference. Read-only. |
| TimeZone | int | Time-zone offset preference. |
| PreferedCulture | string | Number/date formatting culture, e.g. de-DE. |
| IsActive | bool | Account enabled. Set false to deactivate a user (frees the licence). |
| IsMobile | bool | May use the mobile app (technician licence). |
| LastLoginDate | datetime | Last login. Read-only. |
| UserGuideProgress | string | Onboarding state. Read-only. |
| DashboardSettings | string | Dashboard configuration JSON. Read-only. |
Endpoints
GET Get Users
GET {{serverURL}}/Users?$expand=Contact&$filter=IsActive eq true
Active users with their contact. Map Contact.Id → ContactId for scheduling calls.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Users",
"value": [
{
"Id": "1002",
"Version": 1,
"UserName": "max@example.com",
"IsSystem": false,
"CreationDate": "2026-08-25T08:00:00Z",
"IsApproved": true,
"ContactId": "3002",
"PreferedLanguage": "de-DE",
"EmailChannelEnabled": true,
"HasFullScreenPreference": false,
"TimeZone": 0,
"PreferedCulture": "de-DE",
"IsActive": true,
"IsMobile": true,
"LastLoginDate": "2026-08-25T08:00:00Z",
"Contact": {
"Id": "3002",
"FirstName": "Max",
"LastName": "Mustermann",
"Email": "max@example.com",
"GroupId": "1500"
}
}
]
}
GET Count Users
GET {{serverURL}}/Users/$count?$filter=IsActive eq true and IsMobile eq true
Number of (e.g. active mobile) users – handy for licence checks.
Responses
200 200 OK
12
GET Retrieve a User
GET {{serverURL}}/Users(1002L)?$expand=Contact
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Users/@Element",
"Id": "1002",
"Version": 1,
"UserName": "max@example.com",
"IsSystem": false,
"CreationDate": "2026-08-25T08:00:00Z",
"IsApproved": true,
"ContactId": "3002",
"PreferedLanguage": "de-DE",
"EmailChannelEnabled": true,
"HasFullScreenPreference": false,
"TimeZone": 0,
"PreferedCulture": "de-DE",
"IsActive": true,
"IsMobile": true,
"LastLoginDate": "2026-08-25T08:00:00Z",
"Contact": {
"Id": "3002",
"FirstName": "Max",
"LastName": "Mustermann"
}
}
404 404 Not Found
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "The entity User with Key: 1002 can not be found"
}
}
}
POST Create a User
POST {{serverURL}}/Users
Creates a login for an existing contact.
| Body | Type | Description |
|---|
| UserName | string | Required. E-mail address used to log in. |
| ContactId | long | Required. Existing contact (create it with POST Contacts first). |
| IsMobile | bool | true for technicians (mobile licence), false for office users. |
| IsActive | bool | Default true. |
| PreferedLanguage / PreferedCulture | string | Optional. |
Validation problems are reported with 400 – e.g. the user name already exists, the e-mail address is malformed, or the maximum number of licences of the account is reached.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"UserName": "new.technician@example.com",
"ContactId": 3200,
"PreferedLanguage": "de-DE",
"PreferedCulture": "de-DE",
"IsActive": true,
"IsMobile": true,
"EmailChannelEnabled": true
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Users/@Element",
"Id": "1003",
"Version": 1,
"UserName": "new.technician@example.com",
"IsSystem": false,
"CreationDate": "2026-08-25T08:00:00Z",
"IsApproved": false,
"ContactId": "3200",
"PreferedLanguage": "de-DE",
"EmailChannelEnabled": true,
"HasFullScreenPreference": false,
"TimeZone": 0,
"PreferedCulture": "de-DE",
"IsActive": true,
"IsMobile": true
}
PUT Update a User (PUT)
PUT {{serverURL}}/Users(1002L)
Replaces the user settings. ContactId must be given (the user's own contact).
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 1002,
"UserName": "max@example.com",
"ContactId": 3002,
"PreferedLanguage": "en-US",
"PreferedCulture": "de-DE",
"IsActive": true,
"IsMobile": true,
"EmailChannelEnabled": false
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Users/@Element",
"Id": "1002",
"Version": 2,
"UserName": "max@example.com",
"IsSystem": false,
"CreationDate": "2026-08-25T08:00:00Z",
"IsApproved": true,
"ContactId": "3002",
"PreferedLanguage": "en-US",
"EmailChannelEnabled": false,
"HasFullScreenPreference": false,
"TimeZone": 0,
"PreferedCulture": "de-DE",
"IsActive": true,
"IsMobile": true,
"LastLoginDate": "2026-08-25T08:00:00Z"
}
PATCH Deactivate / Activate a User (PATCH)
PATCH {{serverURL}}/Users(1002L)
Toggles the account. Deactivated users cannot log in and do not consume a licence.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"IsActive": false
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Users/@Element",
"Id": "1002",
"Version": 2,
"UserName": "max@example.com",
"IsSystem": false,
"CreationDate": "2026-08-25T08:00:00Z",
"IsApproved": true,
"ContactId": "3002",
"PreferedLanguage": "de-DE",
"EmailChannelEnabled": true,
"HasFullScreenPreference": false,
"TimeZone": 0,
"PreferedCulture": "de-DE",
"IsActive": false,
"IsMobile": true,
"LastLoginDate": "2026-08-25T08:00:00Z"
}
DELETE Delete a User
DELETE {{serverURL}}/Users(1002L)
Deletes the user (the contact is kept). Prefer deactivation to keep the history intact.
Responses
204 204 No Content
No body.
Item Type 7 endpoints
Item Types are the article master data (materials, services, equipment) that technicians pick from when booking Items on a job.
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: ItemTypes(123L). |
| CustomValues | CustomValue[] | Custom field values: [{ "Meta": "<field name>", "Value": "<value>" }]. |
| Version | int | Row version, incremented on every update. Read-only. |
| Costs | decimal | Purchase price (net). |
| Description | string | Long description. |
| ListPrice | decimal | List price before discount. |
| Manufacture | string | Manufacturer / manufacturer part number. |
| ExternalId | string | Free identifier for your own system (ERP number, foreign key, …). |
| ItemNumber | string | Article number (same meaning as ExternalId). |
| NameOrNumber | string | Name of the article. Required. |
| GlobalTradeItemNr | string | EAN / GTIN. |
| Type | string | Kind of article – see Type values. Default Material. |
| Price | decimal | Selling price per unit (net). |
| VAT | decimal | VAT rate in percent (e.g. 19). |
| IsPortalOnly | bool | Not offered on the mobile app. |
| Discount | decimal | Default discount in percent. |
| DateModified | datetime | Date of the last modification (UTC). Read-only. |
| IsDiscontinued | bool | No longer orderable (hidden from pick lists). |
| IsWarehouse | bool | Stock-managed article. |
| UnitId | long | Unit (see Item Unit). |
| UnitString | string | Unit name. Read-only. |
| Unit | ItemUnit | Unit. Navigation. |
Type values
| Value | Meaning |
|---|
| Material | Material / spare part. |
| Service | Service / labour position. |
| Equipment | Equipment / tool. |
| ExchangePart | Exchange part of a product (requires ItemNumber). |
| Set | Set of items (bill of material); HiddenSet hides the components. |
| Text | Text line on the item list (no price). |
| Title | Heading line. |
| Subtotal | Subtotal line. |
| PageBreak | Page break in reports. |
| PartialInvoice | Partial-invoice position. |
| QuickFilter | Quick-filter entry (portal only). |
| WageAndMaterial | Combined wage & material (GAEB). |
Endpoints
GET Get Item Types
GET {{serverURL}}/ItemTypes?$expand=Unit&$filter=IsDiscontinued eq false&$orderby=NameOrNumber
Article master (paged). Filter by Type, ExternalId, DateModified as needed.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ItemTypes",
"value": [
{
"Id": "15001",
"CustomValues": [],
"Version": 1,
"Costs": "3.10",
"ListPrice": "8.90",
"Manufacture": "SKF",
"ExternalId": "BB-6204",
"ItemNumber": "BB-6204",
"NameOrNumber": "Ball bearing 6204",
"GlobalTradeItemNr": "4012345678901",
"Type": "Material",
"Price": "8.90",
"VAT": "19",
"IsPortalOnly": false,
"Discount": "0",
"DateModified": "2026-08-25T08:00:00Z",
"IsDiscontinued": false,
"IsWarehouse": true,
"UnitId": "16001",
"UnitString": "pcs",
"Unit": {
"Id": "16001",
"Version": 1,
"Name": "pcs"
}
}
]
}
GET Find an Item Type by External Id
GET {{serverURL}}/ItemTypes?$filter=ExternalId eq 'BB-6204'
Lookup by your ERP article number – use the returned Id as ItemTypeId when booking items.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ItemTypes",
"value": [
{
"Id": "15001",
"CustomValues": [],
"Version": 1,
"Costs": "3.10",
"ListPrice": "8.90",
"Manufacture": "SKF",
"ExternalId": "BB-6204",
"ItemNumber": "BB-6204",
"NameOrNumber": "Ball bearing 6204",
"GlobalTradeItemNr": "4012345678901",
"Type": "Material",
"Price": "8.90",
"VAT": "19",
"IsPortalOnly": false,
"Discount": "0",
"DateModified": "2026-08-25T08:00:00Z",
"IsDiscontinued": false,
"IsWarehouse": true,
"UnitId": "16001",
"UnitString": "pcs"
}
]
}
GET Retrieve an Item Type
GET {{serverURL}}/ItemTypes(15001L)?$expand=Unit
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ItemTypes/@Element",
"Id": "15001",
"CustomValues": [],
"Version": 1,
"Costs": "3.10",
"ListPrice": "8.90",
"Manufacture": "SKF",
"ExternalId": "BB-6204",
"ItemNumber": "BB-6204",
"NameOrNumber": "Ball bearing 6204",
"GlobalTradeItemNr": "4012345678901",
"Type": "Material",
"Price": "8.90",
"VAT": "19",
"IsPortalOnly": false,
"Discount": "0",
"DateModified": "2026-08-25T08:00:00Z",
"IsDiscontinued": false,
"IsWarehouse": true,
"UnitId": "16001",
"UnitString": "pcs"
}
POST Create an Item Type
POST {{serverURL}}/ItemTypes
Creates an article.
| Body | Type | Description |
|---|
| NameOrNumber | string | Required. |
| Type | string | Default Material. |
| ExternalId | string | Recommended – your article number. |
| Price, Costs, VAT, Discount | decimal | Default 0. |
| UnitId | long | Existing item unit. |
| Manufacture, GlobalTradeItemNr, Description, IsWarehouse, IsDiscontinued, CustomValues | | Optional. |
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"NameOrNumber": "Ball bearing 6204",
"ExternalId": "BB-6204",
"Type": "Material",
"Manufacture": "SKF",
"Costs": 3.1,
"Price": 8.9,
"VAT": 19,
"UnitId": 16001,
"GlobalTradeItemNr": "4012345678901",
"Description": "Deep groove ball bearing",
"IsWarehouse": true
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ItemTypes/@Element",
"Id": "15001",
"CustomValues": [],
"Version": 1,
"Costs": "3.10",
"ListPrice": "8.90",
"Manufacture": "SKF",
"ExternalId": "BB-6204",
"ItemNumber": "BB-6204",
"NameOrNumber": "Ball bearing 6204",
"GlobalTradeItemNr": "4012345678901",
"Type": "Material",
"Price": "8.90",
"VAT": "19",
"IsPortalOnly": false,
"Discount": "0",
"DateModified": "2026-08-25T08:00:00Z",
"IsDiscontinued": false,
"IsWarehouse": true,
"UnitId": "16001",
"UnitString": "pcs"
}
PUT Update an Item Type (PUT)
PUT {{serverURL}}/ItemTypes(15001L)
Replaces the article – GET first, send everything back (missing properties are reset).
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 15001,
"CustomValues": [],
"Version": 1,
"Costs": 3.3,
"ListPrice": "8.90",
"Manufacture": "SKF",
"ExternalId": "BB-6204",
"ItemNumber": "BB-6204",
"NameOrNumber": "Ball bearing 6204",
"GlobalTradeItemNr": "4012345678901",
"Type": "Material",
"Price": 9.4,
"VAT": "19",
"IsPortalOnly": false,
"Discount": "0",
"DateModified": "2026-08-25T08:00:00Z",
"IsDiscontinued": false,
"IsWarehouse": true,
"UnitId": "16001",
"UnitString": "pcs"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ItemTypes/@Element",
"Id": "15001",
"CustomValues": [],
"Version": 2,
"Costs": "3.30",
"ListPrice": "8.90",
"Manufacture": "SKF",
"ExternalId": "BB-6204",
"ItemNumber": "BB-6204",
"NameOrNumber": "Ball bearing 6204",
"GlobalTradeItemNr": "4012345678901",
"Type": "Material",
"Price": "9.40",
"VAT": "19",
"IsPortalOnly": false,
"Discount": "0",
"DateModified": "2026-08-25T08:00:00Z",
"IsDiscontinued": false,
"IsWarehouse": true,
"UnitId": "16001",
"UnitString": "pcs"
}
PATCH Update Prices (PATCH)
PATCH {{serverURL}}/ItemTypes(15001L)
Partial update – ideal for nightly price synchronisation.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Price": 9.4,
"Costs": 3.3
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ItemTypes/@Element",
"Id": "15001",
"CustomValues": [],
"Version": 2,
"Costs": "3.30",
"ListPrice": "8.90",
"Manufacture": "SKF",
"ExternalId": "BB-6204",
"ItemNumber": "BB-6204",
"NameOrNumber": "Ball bearing 6204",
"GlobalTradeItemNr": "4012345678901",
"Type": "Material",
"Price": "9.40",
"VAT": "19",
"IsPortalOnly": false,
"Discount": "0",
"DateModified": "2026-08-25T08:00:00Z",
"IsDiscontinued": false,
"IsWarehouse": true,
"UnitId": "16001",
"UnitString": "pcs"
}
DELETE Delete an Item Type
DELETE {{serverURL}}/ItemTypes(15001L)
Deletes the article. Prefer IsDiscontinued: true if it was already used on jobs.
Responses
204 204 No Content
No body.
Step List Template 5 endpoints
Step List Templates are reusable checklists. Apply one to a job with POST ServiceRequests(id)/$links/StepListTemplates or by creating a Step List Template Instance – the template's steps are copied into the job.
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: StepListTemplates(123L). |
| Version | int | Row version, incremented on every update. Read-only. |
| Name | string | Template name. Required. |
| MappingId | string | Your own identifier for the template. |
| DateModified | datetime | Date of the last modification (UTC). Read-only. |
| IsReleased | bool | Only released templates can be applied to jobs. Unreleased templates return an empty Steps list. |
| IsDurable | bool | Durable checklists keep their values across jobs of the same service object (custom values). |
| Steps | Step[] | Steps of the template. Navigation – $expand=Steps. On create you may pass the steps inline. |
Endpoints
GET Get Step List Templates
GET {{serverURL}}/StepListTemplates?$expand=Steps&$filter=IsReleased eq true
Released templates with their steps.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#StepListTemplates",
"value": [
{
"Id": "12001",
"Version": 1,
"Name": "Heating pump inspection",
"MappingId": "HP-INSP",
"DateModified": "2026-08-25T08:00:00Z",
"IsReleased": true,
"IsDurable": false,
"Steps": [
{
"Id": "7501",
"Name": "Visual inspection",
"Type": "Choice",
"TrackingId": "VI",
"SortOrder": 0,
"IsVisible": true,
"StepListTemplateId": "12001",
"Data": "{\"fields\":[{\"isRequired\":true,\"name\":\"Result\",\"type\":\"choice\",\"enumeration\":\"OK;Defect\",\"errorlist\":\"false;true\"}],\"custom\":null}"
},
{
"Id": "7502",
"Name": "Pressure (bar)",
"Type": "EnterValue",
"TrackingId": "PRESS",
"SortOrder": 1,
"IsVisible": true,
"StepListTemplateId": "12001"
}
]
}
]
}
GET Retrieve a Step List Template
GET {{serverURL}}/StepListTemplates(12001L)?$expand=Steps
Loads one template. Steps is empty while the template is not released.
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#StepListTemplates/@Element",
"Id": "12001",
"Version": 1,
"Name": "Heating pump inspection",
"MappingId": "HP-INSP",
"DateModified": "2026-08-25T08:00:00Z",
"IsReleased": true,
"IsDurable": false,
"Steps": [
{
"Id": "7501",
"Name": "Visual inspection",
"Type": "Choice",
"TrackingId": "VI",
"SortOrder": 0,
"IsVisible": true,
"StepListTemplateId": "12001",
"Data": "{\"fields\":[{\"isRequired\":true,\"name\":\"Result\",\"type\":\"choice\",\"enumeration\":\"OK;Defect\",\"errorlist\":\"false;true\"}],\"custom\":null}"
},
{
"Id": "7502",
"Name": "Pressure (bar)",
"Type": "EnterValue",
"TrackingId": "PRESS",
"SortOrder": 1,
"IsVisible": true,
"StepListTemplateId": "12001"
}
]
}
POST Create a Step List Template
POST {{serverURL}}/StepListTemplates
Creates a template, optionally with its steps inline (same fields as Step, without ServiceRequestId). Set IsReleased: true to make it usable immediately.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"Name": "Heating pump inspection",
"MappingId": "HP-INSP",
"IsReleased": true,
"Steps": [
{
"Name": "Visual inspection",
"Type": "Choice",
"TrackingId": "VI",
"SortOrder": 0,
"Data": "{\"fields\":[{\"isRequired\":true,\"name\":\"Result\",\"type\":\"choice\",\"enumeration\":\"OK;Defect\",\"errorlist\":\"false;true\"}],\"custom\":null}"
},
{
"Name": "Pressure (bar)",
"Type": "EnterValue",
"TrackingId": "PRESS",
"SortOrder": 1
}
]
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#StepListTemplates/@Element",
"Id": "12001",
"Version": 1,
"Name": "Heating pump inspection",
"MappingId": "HP-INSP",
"DateModified": "2026-08-25T08:00:00Z",
"IsReleased": true,
"IsDurable": false
}
PUT Update a Step List Template
PUT {{serverURL}}/StepListTemplates(12001L)
Updates name / flags. Steps of a template are managed through the Step endpoints (StepListTemplateId).
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 12001,
"Name": "Heating pump inspection v2",
"MappingId": "HP-INSP",
"IsReleased": true,
"IsDurable": false
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#StepListTemplates/@Element",
"Id": "12001",
"Version": 2,
"Name": "Heating pump inspection v2",
"MappingId": "HP-INSP",
"DateModified": "2026-08-25T08:00:00Z",
"IsReleased": true,
"IsDurable": false
}
DELETE Delete a Step List Template
DELETE {{serverURL}}/StepListTemplates(12001L)
Deletes the template. Steps already copied into jobs are not affected.
Responses
204 204 No Content
No body.
Offers 17 endpoints
Offers (quotes) are service requests of type IsOffer. They carry positions (Items), can be sent to the customer through the customer portal and – once confirmed – produce a job.
Filtering on Type is rejected (the set already fixes the type).
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Offers(123L). |
| Name | string | Title. Required. |
| ExternalId | string | Free identifier for your own system (ERP number, foreign key, …). |
| CreatedBy | Contact | Creator. Navigation, read-only. |
| ClosedBy | User | User who closed it. Navigation. |
| ReleasedBy | User | User who sent it. Navigation. |
| ClosedAt | datetime | Closing date. |
| ReleasedAt | datetime | Sent date. |
| WorkDoneAt | datetime | Not used for offers. |
| TargetTimeInMinutes | long | Planned duration of the resulting job. |
| DateModified | datetime | Date of the last modification (UTC). Read-only. |
| DateOfCreation | datetime | Date of creation (UTC). Read-only. |
| DueDateRangeStart | datetime | Validity start. |
| DueDateRangeEnd | datetime | Validity end (offer expires). |
| PortalLink | string | Customer-portal link where the customer can accept the offer. Read-only. |
| CostCenterId | long | Cost center / project. |
| CostCenter | CostCenter | Cost center. Navigation. |
| Description | string | Offer text (HTML). |
| State | string | See State values. |
| Items | Item[] | Offer positions – create them with POST Items using the offer id as ServiceRequestId. Navigation. |
| CustomValues | CustomValue[] | Custom field values: [{ "Meta": "<field name>", "Value": "<value>" }]. |
| Destination | ServiceObject | Service object the offer is for. Navigation – set via $links/Destination. |
| Qualifications | Qualification[] | Required qualifications. Navigation. |
| DocumentIds | long[] | Ids of linked documents. Read-only. |
| Documents | Document[] | Documents. Navigation. |
| Reports | Report[] | Generated offer PDFs. Navigation. |
| ContactIds | long[] | Ids of linked contacts. Read-only. |
| Contacts | Contact[] | Customer contacts. Navigation. |
| Comments | Comment[] | Comments. Navigation. |
| CurrentOwnerId | long | Responsible office contact. |
| CurrentOwner | Contact | Responsible office user. Navigation. |
| CustomerId | long | Customer. Required. |
| Customer | Company | Customer. Navigation. |
| Version | int | Row version, incremented on every update. Read-only. |
| TagIds | long[] | Ids of the tags. Read-only. |
| Tags | Tag[] | Tags. Navigation. |
| IsTemplate | bool | Offer template. |
| CreateFromServiceRequestTemplateId | long | Write-only: template to copy positions from. |
| Invoices | Invoice[] | Invoices created from the offer. Navigation. |
State values
| Value | Meaning |
|---|
| Created | Draft. |
| OfferIsSend | Sent to the customer. |
| OfferIsConfirmed | Accepted by the customer. |
| OfferIsConfirmedAndCreateJob | Accepted – a follow-up job is created from the offer. |
| OfferIsRejected | Declined. |
| OfferIsExpired | Validity expired. |
| OfferIsCancelled | Withdrawn. |
Endpoints
GET Get Offers
GET {{serverURL}}/Offers?$expand=Customer,Destination&$orderby=DateModified desc
All offers (paged) with customer and destination.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Offers",
"value": [
{
"Id": "1300001",
"Name": "Offer – Boiler replacement",
"ExternalId": "Q-2026-042",
"TargetTimeInMinutes": "480",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-30T22:00:00Z",
"Description": "<p>Replacement of the existing boiler by model X200.</p>",
"State": "Created",
"CustomValues": [],
"CurrentOwnerId": "3001",
"CustomerId": "2001",
"Version": 1,
"IsTemplate": false,
"Customer": {
"Id": "2001",
"Name": "ACME GmbH"
}
}
]
}
GET Get Offers in a State
GET {{serverURL}}/Offers?$filter=State eq 'OfferIsSend'&$expand=Items
e.g. all offers waiting for the customer's decision, with positions.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Offers",
"value": [
{
"Id": "1300001",
"Name": "Offer – Boiler replacement",
"ExternalId": "Q-2026-042",
"TargetTimeInMinutes": "480",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-30T22:00:00Z",
"Description": "<p>Replacement of the existing boiler by model X200.</p>",
"State": "OfferIsSend",
"CustomValues": [],
"CurrentOwnerId": "3001",
"CustomerId": "2001",
"Version": 1,
"IsTemplate": false,
"Items": [
{
"Id": "17101",
"NameOrNumber": "Boiler X200",
"QuantityHours": "1",
"Price": "2450.00",
"VAT": "19",
"Type": "Material",
"ServiceRequestId": "1300001"
}
]
}
]
}
GET Count Offers
GET {{serverURL}}/Offers/$count?$filter=State eq 'OfferIsSend'
Number of matching offers.
Responses
200 200 OK
5
GET Retrieve an Offer
GET {{serverURL}}/Offers(1300001L)?$expand=Items,Contacts,Documents,Qualifications,Destination,Tags
Loads one offer with all relations.
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Offers/@Element",
"Id": "1300001",
"Name": "Offer – Boiler replacement",
"ExternalId": "Q-2026-042",
"TargetTimeInMinutes": "480",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-30T22:00:00Z",
"Description": "<p>Replacement of the existing boiler by model X200.</p>",
"State": "Created",
"CustomValues": [],
"CurrentOwnerId": "3001",
"CustomerId": "2001",
"Version": 1,
"IsTemplate": false,
"Items": [],
"Contacts": [],
"Documents": [],
"Qualifications": [],
"Tags": []
}
404 404 Not Found
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "The entity Offer with Key: 1300001 can not be found"
}
}
}
POST Create an Offer
POST {{serverURL}}/Offers
Creates an offer in state Created (Type is set to IsOffer). Add positions with POST Items { ServiceRequestId: <offerId>, … }, then generate the PDF with GenerateReportHash using an offer report definition.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"Name": "Offer – Boiler replacement",
"ExternalId": "Q-2026-042",
"CustomerId": 2001,
"CurrentOwnerId": 3001,
"Description": "<p>Replacement of the existing boiler by model X200.</p>",
"DueDateRangeEnd": "2026-09-30T22:00:00Z",
"TargetTimeInMinutes": 480
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Offers/@Element",
"Id": "1300001",
"Name": "Offer – Boiler replacement",
"ExternalId": "Q-2026-042",
"TargetTimeInMinutes": "480",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-30T22:00:00Z",
"Description": "<p>Replacement of the existing boiler by model X200.</p>",
"State": "Created",
"CustomValues": [],
"CurrentOwnerId": "3001",
"CustomerId": "2001",
"Version": 1,
"IsTemplate": false
}
PUT Update an Offer (PUT)
PUT {{serverURL}}/Offers(1300001L)
Replaces the offer (GET first). Returns 400 if the id does not belong to an offer.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 1300001,
"Name": "Offer – Boiler replacement",
"ExternalId": "Q-2026-042",
"TargetTimeInMinutes": "480",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-30T22:00:00Z",
"Description": "<p>Replacement of the existing boiler by model X200 incl. disposal.</p>",
"State": "Created",
"CustomValues": [],
"CurrentOwnerId": "3001",
"CustomerId": "2001",
"Version": 1,
"IsTemplate": false
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Offers/@Element",
"Id": "1300001",
"Name": "Offer – Boiler replacement",
"ExternalId": "Q-2026-042",
"TargetTimeInMinutes": "480",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-30T22:00:00Z",
"Description": "<p>Replacement of the existing boiler by model X200 incl. disposal.</p>",
"State": "Created",
"CustomValues": [],
"CurrentOwnerId": "3001",
"CustomerId": "2001",
"Version": 2,
"IsTemplate": false
}
400 400 Bad Request
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "The specified entity is not an offer"
}
}
}
PATCH Change Offer State (PATCH)
PATCH {{serverURL}}/Offers(1300001L)
Sets the state. OfferIsConfirmed / OfferIsConfirmedAndCreateJob confirm the offer; the latter creates the follow-up job (ReadyForScheduling) with the offer positions.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"State": "OfferIsConfirmedAndCreateJob"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Offers/@Element",
"Id": "1300001",
"Name": "Offer – Boiler replacement",
"ExternalId": "Q-2026-042",
"TargetTimeInMinutes": "480",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-30T22:00:00Z",
"Description": "<p>Replacement of the existing boiler by model X200.</p>",
"State": "OfferIsConfirmedAndCreateJob",
"CustomValues": [],
"CurrentOwnerId": "3001",
"CustomerId": "2001",
"Version": 2,
"IsTemplate": false
}
DELETE Delete an Offer
DELETE {{serverURL}}/Offers(1300001L)
Deletes the offer. Returns 400 if the entity is not an offer.
Responses
204 204 No Content
No body.
400 400 Bad Request
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "The specified entity is not an offer"
}
}
}
POST Link a Tag to Offer
POST {{serverURL}}/Offers(1300001L)/$links/Tags
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/Tags(6001L)"
}
Responses
204 204 No Content
No body.
DELETE Unlink a Tag from Offer
DELETE {{serverURL}}/Offers(1300001L)/$links/Tags(6001L)
Removes the tag. Alternative: DELETE …/$links/Tags with { "url": "…/Tags(6001L)" }.
Responses
204 204 No Content
No body.
POST Link a Contact to Offer
POST {{serverURL}}/Offers(1300001L)/$links/Contacts
Adds a contact (Contacts).
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/Contacts(3100L)"
}
Responses
204 204 No Content
No body.
DELETE Unlink a Contact from Offer
DELETE {{serverURL}}/Offers(1300001L)/$links/Contacts(3100L)
Removes the contact. Alternative: DELETE …/$links/Contacts with { "url": "…/Contacts(3100L)" }.
Responses
204 204 No Content
No body.
POST Link a Qualification to Offer
POST {{serverURL}}/Offers(1300001L)/$links/Qualifications
Adds a qualification (Qualifications).
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/Qualifications(9001L)"
}
Responses
204 204 No Content
No body.
DELETE Unlink a Qualification from Offer
DELETE {{serverURL}}/Offers(1300001L)/$links/Qualifications(9001L)
Removes the qualification. Alternative: DELETE …/$links/Qualifications with { "url": "…/Qualifications(9001L)" }.
Responses
204 204 No Content
No body.
POST Link a Document to Offer
POST {{serverURL}}/Offers(1300001L)/$links/Documents
Attaches an uploaded document to the offer.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/Documents(10001L)"
}
Responses
204 204 No Content
No body.
POST Set the Destination of an Offer
POST {{serverURL}}/Offers(1300001L)/$links/Destination
Sets the service object the offer is for.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/ServiceObjects(4001L)"
}
Responses
204 204 No Content
No body.
DELETE Remove the Destination of an Offer
DELETE {{serverURL}}/Offers(1300001L)/$links/Destination
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/ServiceObjects(4001L)"
}
Responses
204 204 No Content
No body.
Customer Request 13 endpoints
Customer Requests are incoming requests from customers (customer portal, e-mail, API). The office confirms a request, which turns it into a service request, or rejects it.
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: CustomerRequests(123L). |
| Version | int | Row version, incremented on every update. Read-only. |
| Name | string | Subject. Required. |
| ExternalId | string | Free identifier for your own system (ERP number, foreign key, …). |
| Description | string | Request text. |
| State | string | See State values. Setting Closed confirms the request and creates a job; Rejected declines it. |
| DateOfCreation | datetime | Date of creation (UTC). Read-only. |
| DateModified | datetime | Date of the last modification (UTC). Read-only. |
| DueDateRangeStart | datetime | Requested start. |
| DueDateRangeEnd | datetime | Requested end. |
| IsTemplate | bool | Not used. |
| CreateFromServiceRequestTemplateId | long | Template for the job created on confirmation. |
| CustomerId | long | Customer. Required. |
| Customer | Company | Customer. Navigation. |
| Destination | ServiceObject | Service object. Navigation – set via $links/Destination. |
| Comments | Comment[] | Comments. Navigation. |
| Documents | Document[] | Documents. Navigation. |
| Tags | Tag[] | Tags. Navigation. |
| CreatedBy | Contact | Creator contact (customer-portal user or API user). Navigation. |
| CurrentOwner | Contact | Responsible office user. Navigation. |
State values
| Value | Meaning |
|---|
| Created | New request in the inbox. |
| InProgress | Being handled by the office. |
| Closed | Confirmed – setting this state creates the follow-up job. |
| Rejected | Declined. |
Endpoints
GET Get Customer Requests
GET {{serverURL}}/CustomerRequests?$filter=State eq 'Created'&$expand=Customer,Destination
Open requests in the inbox.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#CustomerRequests",
"value": [
{
"Id": "1400001",
"Version": 1,
"Name": "Heating not working",
"ExternalId": "TICKET-8812",
"Description": "No hot water since Monday.",
"State": "Created",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-03T16:00:00Z",
"IsTemplate": false,
"CustomerId": "2001",
"Customer": {
"Id": "2001",
"Name": "ACME GmbH"
}
}
]
}
GET Count Customer Requests
GET {{serverURL}}/CustomerRequests/$count?$filter=State eq 'Created'
Number of matching requests.
Responses
200 200 OK
3
GET Retrieve a Customer Request
GET {{serverURL}}/CustomerRequests(1400001L)?$expand=Customer,Destination,Documents,Tags
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#CustomerRequests/@Element",
"Id": "1400001",
"Version": 1,
"Name": "Heating not working",
"ExternalId": "TICKET-8812",
"Description": "No hot water since Monday.",
"State": "Created",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-03T16:00:00Z",
"IsTemplate": false,
"CustomerId": "2001",
"Documents": [],
"Tags": []
}
POST Create a Customer Request
POST {{serverURL}}/CustomerRequests
Creates a request in state Created (e.g. from a ticket system). Name and CustomerId are required.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"Name": "Heating not working",
"ExternalId": "TICKET-8812",
"Description": "No hot water since Monday.",
"CustomerId": 2001,
"DueDateRangeEnd": "2026-09-03T16:00:00Z"
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#CustomerRequests/@Element",
"Id": "1400001",
"Version": 1,
"Name": "Heating not working",
"ExternalId": "TICKET-8812",
"Description": "No hot water since Monday.",
"State": "Created",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-03T16:00:00Z",
"IsTemplate": false,
"CustomerId": "2001"
}
PATCH Confirm a Customer Request (creates a job)
PATCH {{serverURL}}/CustomerRequests(1400001L)
State: "Closed" confirms the request; a service request is created (optionally from CreateFromServiceRequestTemplateId) and linked as follow-up.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"State": "Closed",
"CreateFromServiceRequestTemplateId": 1111
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#CustomerRequests/@Element",
"Id": "1400001",
"Version": 2,
"Name": "Heating not working",
"ExternalId": "TICKET-8812",
"Description": "No hot water since Monday.",
"State": "Closed",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-03T16:00:00Z",
"IsTemplate": false,
"CustomerId": "2001"
}
PATCH Reject a Customer Request
PATCH {{serverURL}}/CustomerRequests(1400001L)
Declines the request; the customer is informed via the portal.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"State": "Rejected"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#CustomerRequests/@Element",
"Id": "1400001",
"Version": 2,
"Name": "Heating not working",
"ExternalId": "TICKET-8812",
"Description": "No hot water since Monday.",
"State": "Rejected",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-03T16:00:00Z",
"IsTemplate": false,
"CustomerId": "2001"
}
PUT Update a Customer Request (PUT)
PUT {{serverURL}}/CustomerRequests(1400001L)
Replaces the request (GET first).
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 1400001,
"Version": 1,
"Name": "Heating not working",
"ExternalId": "TICKET-8812",
"Description": "No hot water since Monday. Error code E12 on display.",
"State": "Created",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-03T16:00:00Z",
"IsTemplate": false,
"CustomerId": "2001"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#CustomerRequests/@Element",
"Id": "1400001",
"Version": 2,
"Name": "Heating not working",
"ExternalId": "TICKET-8812",
"Description": "No hot water since Monday. Error code E12 on display.",
"State": "Created",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-03T16:00:00Z",
"IsTemplate": false,
"CustomerId": "2001"
}
DELETE Delete a Customer Request
DELETE {{serverURL}}/CustomerRequests(1400001L)
Responses
204 204 No Content
No body.
POST Link a Tag to CustomerRequest
POST {{serverURL}}/CustomerRequests(1400001L)/$links/Tags
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/Tags(6001L)"
}
Responses
204 204 No Content
No body.
DELETE Unlink a Tag from CustomerRequest
DELETE {{serverURL}}/CustomerRequests(1400001L)/$links/Tags(6001L)
Removes the tag. Alternative: DELETE …/$links/Tags with { "url": "…/Tags(6001L)" }.
Responses
204 204 No Content
No body.
POST Set the Destination of a Customer Request
POST {{serverURL}}/CustomerRequests(1400001L)/$links/Destination
Sets the service object the request refers to.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/ServiceObjects(4001L)"
}
Responses
204 204 No Content
No body.
DELETE Remove the Destination of a Customer Request
DELETE {{serverURL}}/CustomerRequests(1400001L)/$links/Destination
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/ServiceObjects(4001L)"
}
Responses
204 204 No Content
No body.
Invoice 11 endpoints
Invoices are the issued bills. An invoice is generated from an invoice draft – a service request of type IsInvoice that holds the billable items – typically created with ServiceRequests(id)/CreateInvoiceDraft.
Typical flow: job closed → POST ServiceRequests(id)/CreateInvoiceDraft → adjust the draft's items → POST Invoices { InvoiceDraftId } → download the PDF from URI → PATCH to eIsSent / eIsPaid.
Invoices cannot be deleted; cancel them with the Cancel action (creates a cancellation invoice).
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Invoices(123L). |
| Version | int | Row version, incremented on every update. Read-only. |
| URI | string | Download URL of the invoice PDF. Read-only. |
| DocumentName | string | File name. Read-only. |
| ReportDefinitionCode | string | Invoice layout used. Read-only. |
| InvoiceDraftId | long | Id of the invoice draft (service request of type IsInvoice) the invoice was generated from. Required on create. |
| ReportDefinitionId | long | Invoice report definition to render with. Optional on create (account default). |
| SourceServiceRequest | ServiceRequest | Job the invoice was created for. Navigation. |
| Author | Contact | User who created it. Navigation. |
| Customer | Company | Billed customer. Navigation. |
| CostCenter | CostCenter | Cost center. Navigation. |
| ServiceObject | ServiceObject | Service object. Navigation. |
| FileType | string | PdfInvoice, PdfPartialInvoice, PdfCancelInvoice. Read-only. |
| InvoiceBalance | decimal | Gross total. |
| InvoiceBalanceNetto | decimal | Net total. |
| WageBalanceNet | decimal | Net labour share (for §35a statements). |
| DatePayed | datetime | Payment date. |
| InvoiceId | string | Invoice number. Read-only. |
| DueDate | datetime | Payment due date. |
| WithoutVAT | bool | Reverse charge / no VAT. |
| Skonto | decimal | Cash discount in percent. |
| PartialPayment | decimal | Amount already paid. |
| DateOfCreation | datetime | Date of creation (UTC). Read-only. |
| PerformanceDate | datetime | Date of service. |
| InvoiceDate | datetime | Invoice date. |
| InvoiceState | string | See InvoiceState values. Only simple transitions (eIsSent, eIsPaid, eIsWrittenOff, eIsDraft) may be set through PUT/PATCH; use the Cancel, Dun and Reopen actions for the others. |
| Note | string | Internal note (editable). |
| Dunnings | Report[] | Dunning letters generated for the invoice. Navigation. |
| TagIds | long[] | Ids of the tags. Read-only. |
| Tags | Tag[] | Tags. Navigation. |
| GobdBrokenDate | datetime | Set when the invoice was modified after issuing (GoBD audit flag). Read-only. |
| DetailedPriceInformation | string | JSON with the price breakdown (VAT groups, discounts). Read-only. |
InvoiceState values
| Value | Meaning |
|---|
| eIsDraft | Draft (not yet numbered). |
| eIsOpen | Issued, unpaid. |
| eIsSent | Sent to the customer. |
| eIsPaid | Paid. |
| eIsDunned | Reminder sent (via the Dun action). |
| eIsCancelled | Cancelled (via the Cancel action). |
| eIsWrittenOff | Written off (bad debt). |
Endpoints
GET Get Invoices
GET {{serverURL}}/Invoices?$filter=InvoiceState eq 'eIsOpen'&$expand=Customer&$orderby=InvoiceDate desc
Open invoices with the customer. Filter on InvoiceDate, DueDate, InvoiceState, DateOfCreation for exports to accounting.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Invoices",
"value": [
{
"Id": "1600001",
"Version": 1,
"URI": "https://portal.mobilefieldreport.com/mfr/Report/1600001/Content",
"DocumentName": "Invoice 2026-00042.pdf",
"ReportDefinitionCode": "INVOICE",
"InvoiceDraftId": "1234570000",
"ReportDefinitionId": "23002",
"FileType": "PdfInvoice",
"InvoiceBalance": "1190.00",
"InvoiceBalanceNetto": "1000.00",
"WageBalanceNet": "300.00",
"InvoiceId": "2026-00042",
"DueDate": "2026-09-08T00:00:00Z",
"WithoutVAT": false,
"Skonto": "0",
"PartialPayment": "0",
"DateOfCreation": "2026-08-25T08:00:00Z",
"PerformanceDate": "2026-09-02T00:00:00Z",
"InvoiceDate": "2026-08-25T00:00:00Z",
"InvoiceState": "eIsOpen",
"Customer": {
"Id": "2001",
"Name": "ACME GmbH",
"ExternalId": "C-100"
}
}
]
}
GET Retrieve an Invoice
GET {{serverURL}}/Invoices(1600001L)?$expand=Customer,SourceServiceRequest,Tags,Dunnings
Loads one invoice with the job it bills.
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Invoices/@Element",
"Id": "1600001",
"Version": 1,
"URI": "https://portal.mobilefieldreport.com/mfr/Report/1600001/Content",
"DocumentName": "Invoice 2026-00042.pdf",
"ReportDefinitionCode": "INVOICE",
"InvoiceDraftId": "1234570000",
"ReportDefinitionId": "23002",
"FileType": "PdfInvoice",
"InvoiceBalance": "1190.00",
"InvoiceBalanceNetto": "1000.00",
"WageBalanceNet": "300.00",
"InvoiceId": "2026-00042",
"DueDate": "2026-09-08T00:00:00Z",
"WithoutVAT": false,
"Skonto": "0",
"PartialPayment": "0",
"DateOfCreation": "2026-08-25T08:00:00Z",
"PerformanceDate": "2026-09-02T00:00:00Z",
"InvoiceDate": "2026-08-25T00:00:00Z",
"InvoiceState": "eIsOpen",
"SourceServiceRequest": {
"Id": "1234567890",
"Name": "Repair heating pump",
"State": "Invoiced"
},
"Tags": [],
"Dunnings": []
}
404 404 Not Found
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "The entity Invoice with Key: 1600001 can not be found"
}
}
}
POST Create an Invoice from a Draft
POST {{serverURL}}/Invoices
Generates the invoice (number + PDF) from an invoice draft.
| Body | Type | Description |
|---|
| InvoiceDraftId | long | Required. Service request of type IsInvoice (from CreateInvoiceDraft). |
| ReportDefinitionId | long | Invoice layout; account default when omitted. |
Returns 201 with the invoice; download the PDF from URI.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"InvoiceDraftId": 1234570000,
"ReportDefinitionId": 23002
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Invoices/@Element",
"Id": "1600001",
"Version": 1,
"URI": "https://portal.mobilefieldreport.com/mfr/Report/1600001/Content",
"DocumentName": "Invoice 2026-00042.pdf",
"ReportDefinitionCode": "INVOICE",
"InvoiceDraftId": "1234570000",
"ReportDefinitionId": "23002",
"FileType": "PdfInvoice",
"InvoiceBalance": "1190.00",
"InvoiceBalanceNetto": "1000.00",
"WageBalanceNet": "300.00",
"InvoiceId": "2026-00042",
"DueDate": "2026-09-08T00:00:00Z",
"WithoutVAT": false,
"Skonto": "0",
"PartialPayment": "0",
"DateOfCreation": "2026-08-25T08:00:00Z",
"PerformanceDate": "2026-09-02T00:00:00Z",
"InvoiceDate": "2026-08-25T00:00:00Z",
"InvoiceState": "eIsOpen"
}
400 400 Bad Request
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "InvoiceDraftId is required to generate an invoice from a draft."
}
}
}
PATCH Mark an Invoice as Paid (PATCH)
PATCH {{serverURL}}/Invoices(1600001L)
Only InvoiceState (simple transitions) and Note are writable; other properties in the body are ignored. eIsCancelled, eIsDunned and eIsOpen are rejected – use the actions.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"InvoiceState": "eIsPaid",
"Note": "Paid by bank transfer"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Invoices/@Element",
"Id": "1600001",
"Version": 2,
"URI": "https://portal.mobilefieldreport.com/mfr/Report/1600001/Content",
"DocumentName": "Invoice 2026-00042.pdf",
"ReportDefinitionCode": "INVOICE",
"InvoiceDraftId": "1234570000",
"ReportDefinitionId": "23002",
"FileType": "PdfInvoice",
"InvoiceBalance": "1190.00",
"InvoiceBalanceNetto": "1000.00",
"WageBalanceNet": "300.00",
"InvoiceId": "2026-00042",
"DueDate": "2026-09-08T00:00:00Z",
"WithoutVAT": false,
"Skonto": "0",
"PartialPayment": "0",
"DateOfCreation": "2026-08-25T08:00:00Z",
"PerformanceDate": "2026-09-02T00:00:00Z",
"InvoiceDate": "2026-08-25T00:00:00Z",
"InvoiceState": "eIsPaid",
"Note": "Paid by bank transfer"
}
400 400 Bad Request
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "Invoice state 'eIsCancelled' cannot be set through an update. Use the Cancel, Dun or Reopen action instead."
}
}
}
PUT Update an Invoice (PUT)
PUT {{serverURL}}/Invoices(1600001L)
Only InvoiceState (simple transitions) and Note are updated; all other properties are immutable once issued.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 1600001,
"Version": 1,
"URI": "https://portal.mobilefieldreport.com/mfr/Report/1600001/Content",
"DocumentName": "Invoice 2026-00042.pdf",
"ReportDefinitionCode": "INVOICE",
"InvoiceDraftId": "1234570000",
"ReportDefinitionId": "23002",
"FileType": "PdfInvoice",
"InvoiceBalance": "1190.00",
"InvoiceBalanceNetto": "1000.00",
"WageBalanceNet": "300.00",
"InvoiceId": "2026-00042",
"DueDate": "2026-09-08T00:00:00Z",
"WithoutVAT": false,
"Skonto": "0",
"PartialPayment": "0",
"DateOfCreation": "2026-08-25T08:00:00Z",
"PerformanceDate": "2026-09-02T00:00:00Z",
"InvoiceDate": "2026-08-25T00:00:00Z",
"InvoiceState": "eIsSent",
"Note": "Sent by e-mail"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Invoices/@Element",
"Id": "1600001",
"Version": 2,
"URI": "https://portal.mobilefieldreport.com/mfr/Report/1600001/Content",
"DocumentName": "Invoice 2026-00042.pdf",
"ReportDefinitionCode": "INVOICE",
"InvoiceDraftId": "1234570000",
"ReportDefinitionId": "23002",
"FileType": "PdfInvoice",
"InvoiceBalance": "1190.00",
"InvoiceBalanceNetto": "1000.00",
"WageBalanceNet": "300.00",
"InvoiceId": "2026-00042",
"DueDate": "2026-09-08T00:00:00Z",
"WithoutVAT": false,
"Skonto": "0",
"PartialPayment": "0",
"DateOfCreation": "2026-08-25T08:00:00Z",
"PerformanceDate": "2026-09-02T00:00:00Z",
"InvoiceDate": "2026-08-25T00:00:00Z",
"InvoiceState": "eIsSent",
"Note": "Sent by e-mail"
}
POST Action: Cancel an Invoice
POST {{serverURL}}/Invoices(1600001L)/Cancel
Cancels the invoice and creates a cancellation invoice (credit note) which is returned. The original gets eIsCancelled.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Invoices/@Element",
"Id": "1600002",
"Version": 1,
"URI": "https://portal.mobilefieldreport.com/mfr/Report/1600001/Content",
"DocumentName": "Cancellation 2026-00043.pdf",
"ReportDefinitionCode": "INVOICE",
"InvoiceDraftId": "1234570000",
"ReportDefinitionId": "23002",
"FileType": "PdfCancelInvoice",
"InvoiceBalance": "-1190.00",
"InvoiceBalanceNetto": "-1000.00",
"WageBalanceNet": "-300.00",
"InvoiceId": "2026-00043",
"DueDate": "2026-09-08T00:00:00Z",
"WithoutVAT": false,
"Skonto": "0",
"PartialPayment": "0",
"DateOfCreation": "2026-08-25T08:00:00Z",
"PerformanceDate": "2026-09-02T00:00:00Z",
"InvoiceDate": "2026-08-25T00:00:00Z",
"InvoiceState": "eIsOpen"
}
POST Action: Dun an Invoice
POST {{serverURL}}/Invoices(1600001L)/Dun
Generates a dunning letter (returned as a Report) and sets the invoice to eIsDunned.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Reports/@Element",
"Id": "22010",
"Version": 1,
"DateOfCreation": "2026-08-25T08:00:00Z",
"URI": "https://portal.mobilefieldreport.com/mfr/Report/22010/Content",
"DocumentName": "Reminder 2026-00042.pdf",
"FileTypeString": "PdfDunning",
"ReportDefinitionCode": "DUNNING",
"CanBeDeleted": false,
"InvoiceBalance": "0",
"InvoiceBalanceNetto": "0",
"WageBalanceNet": "0",
"WithoutVAT": false,
"InvoiceId": "2026-00042",
"DueDate": "2026-09-22T00:00:00Z",
"IsPayed": false,
"IsInvoice": false,
"IsCanceled": false,
"CustomValues": []
}
POST Action: Reopen an Invoice
POST {{serverURL}}/Invoices(1600001L)/Reopen
Reopens a cancelled invoice for correction: returns a new invoice draft (service request of type IsInvoice) with the original items. Edit it and create a new invoice from it.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests/@Element",
"Id": "1234570001",
"Name": "Invoice – Repair heating pump",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"State": "Created",
"CustomerId": "2001",
"ParentServiceRequestId": "1234567890",
"Version": 1,
"IsTemplate": false,
"IsTemplateMobile": false,
"Type": "IsInvoice"
}
POST Action: Clone an Invoice
POST {{serverURL}}/Invoices(1600001L)/Clone
Copies the invoice into a new invoice draft (e.g. for recurring billing) and returns the draft.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests/@Element",
"Id": "1234570002",
"Name": "Invoice – Repair heating pump (copy)",
"DateModified": "2026-08-25T08:00:00Z",
"DateOfCreation": "2026-08-25T08:00:00Z",
"State": "Created",
"CustomerId": "2001",
"Version": 1,
"IsTemplate": false,
"IsTemplateMobile": false,
"Type": "IsInvoice"
}
POST Link a Tag to Invoice
POST {{serverURL}}/Invoices(1600001L)/$links/Tags
Adds a tag (type ServiceRequest).
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/Tags(6001L)"
}
Responses
204 204 No Content
No body.
DELETE Unlink a Tag from Invoice
DELETE {{serverURL}}/Invoices(1600001L)/$links/Tags(6001L)
Removes the tag. Alternative: DELETE …/$links/Tags with { "url": "…/Tags(6001L)" }.
Responses
204 204 No Content
No body.
Purchase Invoice 7 endpoints
Purchase Invoices (inbound invoices / receipts) are supplier invoices uploaded in the portal or by e-mail and booked on jobs and cost centers. Through the API they can be read, approved / paid and tagged; upload and deletion happen in the portal.
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: PurchaseInvoices(123L). |
| Version | int | Row version, incremented on every update. Read-only. |
| Note | string | Note. |
| Name | string | Title / description. |
| DateModified | datetime | Date of the last modification (UTC). Read-only. |
| IsPaid | bool | Paid. |
| DateOfPayment | datetime | Payment date. |
| DateOfUpload | datetime | Upload date. Read-only. |
| DateCreated | datetime | Date of creation (UTC). Read-only. |
| Author | Contact | Uploader. Navigation. |
| Supplier | Company | Supplier company. Navigation. |
| State | string | See State values. |
| Costs | decimal | Gross amount. |
| CostCenter | CostCenter | Cost center. Navigation. |
| ExternalId | string | Free identifier for your own system (ERP number, foreign key, …). |
| ReceiptNumber | string | Supplier's invoice number. |
| ServiceRequest | ServiceRequest | Job the costs are booked on. Navigation. |
| URI | string | Download URL of the receipt. Read-only. |
| ExtractedItemsUri | string | URL of the extracted positions (OCR). Read-only. |
| IsBlobUri | bool | File stored in blob storage. Read-only. |
| IsLink | bool | External link instead of upload. |
| FileName | string | File name. |
| TagIds | long[] | Ids of the tags. Read-only. |
| Tags | Tag[] | Tags. Navigation. |
State values
| Value | Meaning |
|---|
| eInInbox | Uploaded, not yet assigned. |
| eIsToBeConfirmed | Assigned to a job / cost center, awaiting approval. |
| eIsConfirmed | Approved, to be paid. |
| eIsRejected | Rejected. |
| eIsPaid | Paid. |
Endpoints
GET Get Purchase Invoices
GET {{serverURL}}/PurchaseInvoices?$filter=State eq 'eIsToBeConfirmed'&$expand=Supplier,ServiceRequest,CostCenter
Receipts awaiting approval with supplier, job and cost center.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#PurchaseInvoices",
"value": [
{
"Id": "1700001",
"Version": 1,
"Name": "Bearings Ltd – 88123",
"DateModified": "2026-08-25T08:00:00Z",
"IsPaid": false,
"DateOfUpload": "2026-08-25T08:00:00Z",
"DateCreated": "2026-08-25T08:00:00Z",
"State": "eIsToBeConfirmed",
"Costs": "74.40",
"ReceiptNumber": "88123",
"URI": "https://portal.mobilefieldreport.com/mfr/PurchaseInvoice/1700001/Content",
"IsBlobUri": true,
"IsLink": false,
"FileName": "88123.pdf",
"Supplier": {
"Id": "2100",
"Name": "Bearings Ltd",
"IsSupplier": true
},
"ServiceRequest": {
"Id": "1234567890",
"Name": "Repair heating pump"
}
}
]
}
GET Retrieve a Purchase Invoice
GET {{serverURL}}/PurchaseInvoices(1700001L)?$expand=Supplier,Tags
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#PurchaseInvoices/@Element",
"Id": "1700001",
"Version": 1,
"Name": "Bearings Ltd – 88123",
"DateModified": "2026-08-25T08:00:00Z",
"IsPaid": false,
"DateOfUpload": "2026-08-25T08:00:00Z",
"DateCreated": "2026-08-25T08:00:00Z",
"State": "eIsToBeConfirmed",
"Costs": "74.40",
"ReceiptNumber": "88123",
"URI": "https://portal.mobilefieldreport.com/mfr/PurchaseInvoice/1700001/Content",
"IsBlobUri": true,
"IsLink": false,
"FileName": "88123.pdf",
"Tags": []
}
PATCH Approve a Purchase Invoice (PATCH)
PATCH {{serverURL}}/PurchaseInvoices(1700001L)
Partial update – approve, reject or mark as paid (State: "eIsPaid", IsPaid: true, DateOfPayment: …).
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"State": "eIsConfirmed"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#PurchaseInvoices/@Element",
"Id": "1700001",
"Version": 2,
"Name": "Bearings Ltd – 88123",
"DateModified": "2026-08-25T08:00:00Z",
"IsPaid": false,
"DateOfUpload": "2026-08-25T08:00:00Z",
"DateCreated": "2026-08-25T08:00:00Z",
"State": "eIsConfirmed",
"Costs": "74.40",
"ReceiptNumber": "88123",
"URI": "https://portal.mobilefieldreport.com/mfr/PurchaseInvoice/1700001/Content",
"IsBlobUri": true,
"IsLink": false,
"FileName": "88123.pdf"
}
PUT Update a Purchase Invoice (PUT)
PUT {{serverURL}}/PurchaseInvoices(1700001L)
Replaces the editable fields (GET first). Create and delete are not available through the API.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 1700001,
"Version": 1,
"Name": "Bearings Ltd – 88123",
"DateModified": "2026-08-25T08:00:00Z",
"IsPaid": true,
"DateOfUpload": "2026-08-25T08:00:00Z",
"DateCreated": "2026-08-25T08:00:00Z",
"State": "eIsPaid",
"Costs": "74.40",
"ReceiptNumber": "88123",
"URI": "https://portal.mobilefieldreport.com/mfr/PurchaseInvoice/1700001/Content",
"IsBlobUri": true,
"IsLink": false,
"FileName": "88123.pdf",
"DateOfPayment": "2026-09-05T00:00:00Z",
"Note": "Paid with weekly run"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#PurchaseInvoices/@Element",
"Id": "1700001",
"Version": 2,
"Name": "Bearings Ltd – 88123",
"DateModified": "2026-08-25T08:00:00Z",
"IsPaid": true,
"DateOfUpload": "2026-08-25T08:00:00Z",
"DateCreated": "2026-08-25T08:00:00Z",
"State": "eIsPaid",
"Costs": "74.40",
"ReceiptNumber": "88123",
"URI": "https://portal.mobilefieldreport.com/mfr/PurchaseInvoice/1700001/Content",
"IsBlobUri": true,
"IsLink": false,
"FileName": "88123.pdf",
"DateOfPayment": "2026-09-05T00:00:00Z",
"Note": "Paid with weekly run"
}
POST Link a Tag to Purchase Invoice
POST {{serverURL}}/PurchaseInvoices(1700001L)/$links/Tags
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/Tags(6001L)"
}
Responses
204 204 No Content
No body.
DELETE Unlink a Tag from Purchase Invoice
DELETE {{serverURL}}/PurchaseInvoices(1700001L)/$links/Tags(6001L)
Responses
204 204 No Content
No body.
Project 18 endpoints
A Project bundles jobs, offers, orders and invoices for one customer under a budget. Technically it is a cost center plus a job template; jobs belong to the project through their CostCenterId.
Projects also have a lightweight task board: Tasks are appointments of type Task that move through Pipelines (tags linked to the project).
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Projects(123L). |
| Version | int | Row version, incremented on every update. Read-only. |
| Name | string | Project name. Required. |
| ExternalId | string | Free identifier for your own system (ERP number, foreign key, …). |
| BudgetTime | decimal | Time budget in hours. |
| BudgetMaterial | decimal | Material budget (currency). |
| CurrentAmountTime | decimal | Hours booked so far. Read-only. |
| CurrentAmountMaterial | decimal | Material costs so far. Read-only. |
| CustomerId | long | Customer. Required (must not be 0). |
| ClosedAt | datetime | Closing date. Read-only. |
| IsClosed | bool | Closed projects accept no new jobs. |
| CostCenter | CostCenter | The cost center behind the project – jobs join the project via ServiceRequest.CostCenterId. Navigation. |
| ServiceRequestTemplate | ServiceRequest | Template used for new project jobs. Navigation. |
| Invoices | Invoice[] | Invoices of the project. Navigation / GET Projects(id)/Invoices. |
| ServiceRequests | ServiceRequest[] | Jobs. GET Projects(id)/ServiceRequests. |
| Offers | ServiceRequest[] | Offers. GET Projects(id)/Offers. |
| Orders | ServiceRequest[] | Orders. GET Projects(id)/Orders. |
| Tags | Tag[] | Tags ($links/Tags). |
| Pipelines | Tag[] | Pipeline stages for tasks – these are Tags linked via $links/Pipelines. |
| Tasks | Appointment[] | Project tasks (appointments of type Task). GET/POST Projects(id)/Tasks. |
Endpoints
GET Get Projects
GET {{serverURL}}/Projects?$filter=IsClosed eq false&$expand=CostCenter
Open projects with their cost center (use CostCenter.Id as CostCenterId on jobs).
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Projects",
"value": [
{
"Id": "1800001",
"Version": 1,
"Name": "Building A – heating renewal",
"ExternalId": "PRJ-2026-03",
"BudgetTime": "400",
"BudgetMaterial": "85000",
"CurrentAmountTime": "120.5",
"CurrentAmountMaterial": "23100",
"CustomerId": "2001",
"IsClosed": false,
"CostCenter": {
"Id": "19001",
"Version": 1,
"Name": "Building A – heating renewal"
}
}
]
}
GET Retrieve a Project
GET {{serverURL}}/Projects(1800001L)?$expand=CostCenter,ServiceRequestTemplate,Tags,Pipelines
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Projects/@Element",
"Id": "1800001",
"Version": 1,
"Name": "Building A – heating renewal",
"ExternalId": "PRJ-2026-03",
"BudgetTime": "400",
"BudgetMaterial": "85000",
"CurrentAmountTime": "120.5",
"CurrentAmountMaterial": "23100",
"CustomerId": "2001",
"IsClosed": false,
"Tags": [],
"Pipelines": [
{
"Id": "6201",
"Name": "To do",
"Type": "ServiceRequest",
"ColorDefinition": "#9e9e9e"
},
{
"Id": "6202",
"Name": "Done",
"Type": "ServiceRequest",
"ColorDefinition": "#2e7d32"
}
]
}
POST Create a Project
POST {{serverURL}}/Projects
Creates a project (cost center and job template are created with it). Name and a non-zero CustomerId are required.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"Name": "Building A – heating renewal",
"ExternalId": "PRJ-2026-03",
"CustomerId": 2001,
"BudgetTime": 400,
"BudgetMaterial": 85000
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Projects/@Element",
"Id": "1800001",
"Version": 1,
"Name": "Building A – heating renewal",
"ExternalId": "PRJ-2026-03",
"BudgetTime": "400",
"BudgetMaterial": "85000",
"CurrentAmountTime": "0",
"CurrentAmountMaterial": "0",
"CustomerId": "2001",
"IsClosed": false
}
400 400 Bad Request
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "CustomerId must be set for creating projects"
}
}
}
PUT Update a Project (PUT)
PUT {{serverURL}}/Projects(1800001L)
Replaces name, budgets and closed flag (GET first).
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 1800001,
"Name": "Building A – heating renewal",
"ExternalId": "PRJ-2026-03",
"CustomerId": 2001,
"BudgetTime": 450,
"BudgetMaterial": 90000,
"IsClosed": false
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Projects/@Element",
"Id": "1800001",
"Version": 2,
"Name": "Building A – heating renewal",
"ExternalId": "PRJ-2026-03",
"BudgetTime": "450",
"BudgetMaterial": "90000",
"CurrentAmountTime": "120.5",
"CurrentAmountMaterial": "23100",
"CustomerId": "2001",
"IsClosed": false
}
PATCH Close a Project (PATCH)
PATCH {{serverURL}}/Projects(1800001L)
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"IsClosed": true
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Projects/@Element",
"Id": "1800001",
"Version": 2,
"Name": "Building A – heating renewal",
"ExternalId": "PRJ-2026-03",
"BudgetTime": "400",
"BudgetMaterial": "85000",
"CurrentAmountTime": "120.5",
"CurrentAmountMaterial": "23100",
"CustomerId": "2001",
"IsClosed": true,
"ClosedAt": "2026-08-25T08:00:00Z"
}
DELETE Delete a Project
DELETE {{serverURL}}/Projects(1800001L)
Deletes the project (jobs keep existing without a cost center).
Responses
204 204 No Content
No body.
GET Get Service Requests of a Project
GET {{serverURL}}/Projects(1800001L)/ServiceRequests?$select=Id,Name,State
Jobs of the project. Filters on CostCenter are rejected – the navigation already scopes the result.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests",
"value": [
{
"Id": "1234567890",
"Name": "Repair heating pump",
"State": "Released"
}
]
}
GET Get Offers of a Project
GET {{serverURL}}/Projects(1800001L)/Offers
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests",
"value": [
{
"Id": "1300001",
"Name": "Offer – Boiler replacement",
"State": "OfferIsSend",
"Type": "IsOffer"
}
]
}
GET Get Orders of a Project
GET {{serverURL}}/Projects(1800001L)/Orders
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests",
"value": [
{
"Id": "1500001",
"Name": "Order – Bearings Ltd",
"State": "Created",
"Type": "IsOrder"
}
]
}
GET Get Invoices of a Project
GET {{serverURL}}/Projects(1800001L)/Invoices
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Invoices",
"value": [
{
"Id": "1600001",
"Version": 1,
"URI": "https://portal.mobilefieldreport.com/mfr/Report/1600001/Content",
"DocumentName": "Invoice 2026-00042.pdf",
"ReportDefinitionCode": "INVOICE",
"InvoiceDraftId": "1234570000",
"ReportDefinitionId": "23002",
"FileType": "PdfInvoice",
"InvoiceBalance": "1190.00",
"InvoiceBalanceNetto": "1000.00",
"WageBalanceNet": "300.00",
"InvoiceId": "2026-00042",
"DueDate": "2026-09-08T00:00:00Z",
"WithoutVAT": false,
"Skonto": "0",
"PartialPayment": "0",
"DateOfCreation": "2026-08-25T08:00:00Z",
"PerformanceDate": "2026-09-02T00:00:00Z",
"InvoiceDate": "2026-08-25T00:00:00Z",
"InvoiceState": "eIsOpen"
}
]
}
GET Get Tasks of a Project
GET {{serverURL}}/Projects(1800001L)/Tasks?$expand=Pipeline,Contact
Task board of the project (appointments of type Task) with pipeline stage and assignee.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Appointments",
"value": [
{
"Id": "5201",
"Version": 1,
"AppointmentType": "Task",
"Type": "Task",
"State": "NotVisited",
"StartDateTime": "2026-09-08T07:00:00Z",
"EndDateTime": "2026-09-08T09:00:00Z",
"ContactId": "3002",
"ContactIds": [
"3002"
],
"Note": "Order radiators",
"Pipeline": {
"Id": "6201",
"Name": "To do",
"Type": "ServiceRequest",
"ColorDefinition": "#9e9e9e"
},
"CreatedAt": "2026-08-25T08:00:00Z"
}
]
}
POST Create a Task in a Project
POST {{serverURL}}/Projects(1800001L)/Tasks
Creates a task. Pipeline.Id is required and must be a pipeline tag linked to the project ($links/Pipelines). ContactId is the assignee's contact.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"AppointmentType": "Task",
"StartDateTime": "2026-09-08T07:00:00Z",
"EndDateTime": "2026-09-08T09:00:00Z",
"ContactId": 3002,
"Note": "Order radiators",
"Pipeline": {
"Id": 6201
}
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Appointments/@Element",
"Id": "5201",
"Version": 1,
"AppointmentType": "Task",
"Type": "Task",
"State": "NotVisited",
"StartDateTime": "2026-09-08T07:00:00Z",
"EndDateTime": "2026-09-08T09:00:00Z",
"ContactId": "3002",
"ContactIds": [
"3002"
],
"Note": "Order radiators",
"Pipeline": {
"Id": "6201",
"Name": "To do",
"Type": "ServiceRequest",
"ColorDefinition": "#9e9e9e"
},
"CreatedAt": "2026-08-25T08:00:00Z"
}
PUT Update a Task of a Project
PUT {{serverURL}}/Projects(1800001L)/Tasks(5201L)
Moves the task to another pipeline stage / changes assignee or dates.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 5201,
"AppointmentType": "Task",
"StartDateTime": "2026-09-08T07:00:00Z",
"EndDateTime": "2026-09-08T09:00:00Z",
"ContactId": 3002,
"Note": "Order radiators – done",
"Pipeline": {
"Id": 6202
}
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Appointments/@Element",
"Id": "5201",
"Version": 2,
"AppointmentType": "Task",
"Type": "Task",
"State": "NotVisited",
"StartDateTime": "2026-09-08T07:00:00Z",
"EndDateTime": "2026-09-08T09:00:00Z",
"ContactId": "3002",
"ContactIds": [
"3002"
],
"Note": "Order radiators – done",
"Pipeline": {
"Id": "6202",
"Name": "Done",
"Type": "ServiceRequest",
"ColorDefinition": "#2e7d32"
},
"CreatedAt": "2026-08-25T08:00:00Z"
}
DELETE Delete a Task of a Project
DELETE {{serverURL}}/Projects(1800001L)/Tasks(5201L)
Responses
204 204 No Content
No body.
POST Link a Tag to a Project
POST {{serverURL}}/Projects(1800001L)/$links/Tags
Adds a tag (type ServiceRequest). PUT works too.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/Tags(6001L)"
}
Responses
204 204 No Content
No body.
DELETE Unlink a Tag from a Project
DELETE {{serverURL}}/Projects(1800001L)/$links/Tags(6001L)
Removes the tag. Alternative: DELETE …/$links/Tags with { "url": "…/Tags(6001L)" }.
Responses
204 204 No Content
No body.
POST Link a Pipeline to a Project
POST {{serverURL}}/Projects(1800001L)/$links/Pipelines
Adds a pipeline stage. Pipelines are tags – create them with POST Tags first.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/Tags(6201L)"
}
Responses
204 204 No Content
No body.
DELETE Unlink a Pipeline from a Project
DELETE {{serverURL}}/Projects(1800001L)/$links/Pipelines(6201L)
Removes the pipeline stage. Alternative: DELETE …/$links/Pipelines with { "url": "…/Tags(6201L)" }.
Responses
204 204 No Content
No body.
Order 11 endpoints
Orders are purchase orders to suppliers (service requests of type IsOrder). Creating an order collects all open stock movements of type OrderBy for the supplier (optionally limited to one warehouse) into order positions.
Orders of a warehouse: GET Warehouses(id)/Orders. Filtering on Type is rejected.
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Orders(123L). |
| Version | int | Row version, incremented on every update. Read-only. |
| ExternalId | string | Free identifier for your own system (ERP number, foreign key, …). |
| Name | string | Title (generated from the supplier when omitted). |
| Description | string | Free text. |
| State | string | See State values. |
| DateOfCreation | datetime | Date of creation (UTC). Read-only. |
| DateModified | datetime | Date of the last modification (UTC). Read-only. |
| DueDateRangeStart | datetime | Requested delivery from. |
| DueDateRangeEnd | datetime | Requested delivery until. |
| CustomerId | long | Customer (for drop-shipping). Optional. |
| Customer | Company | Customer. Navigation. |
| Destination | ServiceObject | Delivery address (service object / warehouse). Navigation. |
| Items | Item[] | Ordered positions – created from the open OrderBy stock movements of the supplier. Navigation. |
| Tags | Tag[] | Tags. Navigation. |
| SupplierId | long | Supplier company (IsSupplier = true). Required on create. |
| WarehouseId | long | Warehouse the goods are ordered for. Optional – restricts the stock movements picked up. |
State values
| Value | Meaning |
|---|
| Created | Open order. |
| OrderPrinted | Order document generated / sent to the supplier. |
| Closed | Goods received, order completed. |
| OrderCancelled | Cancelled. |
Endpoints
GET Get Orders
GET {{serverURL}}/Orders?$expand=Items,Destination&$orderby=DateOfCreation desc
All orders with positions.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Orders",
"value": [
{
"Id": "1500001",
"Version": 1,
"ExternalId": "PO-2026-017",
"Name": "Order – Bearings Ltd",
"State": "Created",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-10T22:00:00Z",
"SupplierId": "2100",
"WarehouseId": "4500",
"Items": [
{
"Id": "17201",
"NameOrNumber": "Ball bearing 6204",
"ItemTypeId": "15001",
"QuantityHours": "20",
"Price": "3.10",
"Type": "Material",
"ServiceRequestId": "1500001"
}
]
}
]
}
GET Count Orders
GET {{serverURL}}/Orders/$count?$filter=State eq 'Created'
Responses
200 200 OK
2
GET Retrieve an Order
GET {{serverURL}}/Orders(1500001L)?$expand=Items,Tags,Destination
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Orders/@Element",
"Id": "1500001",
"Version": 1,
"ExternalId": "PO-2026-017",
"Name": "Order – Bearings Ltd",
"State": "Created",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-10T22:00:00Z",
"SupplierId": "2100",
"WarehouseId": "4500",
"Items": [],
"Tags": []
}
POST Create an Order
POST {{serverURL}}/Orders
Creates an order for SupplierId from its open OrderBy stock movements (of WarehouseId when given). Fails with 400 when SupplierId is missing or there is nothing to order. Orders cannot be created under a warehouse (POST Warehouses(id)/Orders → 405).
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"SupplierId": 2100,
"WarehouseId": 4500,
"ExternalId": "PO-2026-017",
"DueDateRangeEnd": "2026-09-10T22:00:00Z",
"Description": "Weekly replenishment"
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Orders/@Element",
"Id": "1500001",
"Version": 1,
"ExternalId": "PO-2026-017",
"Name": "Order – Bearings Ltd",
"State": "Created",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-10T22:00:00Z",
"SupplierId": "2100",
"WarehouseId": "4500"
}
PUT Update an Order (PUT)
PUT {{serverURL}}/Orders(1500001L)
Replaces the order (GET first).
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 1500001,
"Version": 1,
"ExternalId": "PO-2026-017",
"Name": "Order – Bearings Ltd",
"State": "Created",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-10T22:00:00Z",
"SupplierId": "2100",
"WarehouseId": "4500",
"Description": "Weekly replenishment – urgent"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Orders/@Element",
"Id": "1500001",
"Version": 2,
"ExternalId": "PO-2026-017",
"Name": "Order – Bearings Ltd",
"State": "Created",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-10T22:00:00Z",
"SupplierId": "2100",
"WarehouseId": "4500",
"Description": "Weekly replenishment – urgent"
}
PATCH Change Order State (PATCH)
PATCH {{serverURL}}/Orders(1500001L)
Partial update, e.g. mark the order as sent.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"State": "OrderPrinted"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Orders/@Element",
"Id": "1500001",
"Version": 2,
"ExternalId": "PO-2026-017",
"Name": "Order – Bearings Ltd",
"State": "OrderPrinted",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"DueDateRangeEnd": "2026-09-10T22:00:00Z",
"SupplierId": "2100",
"WarehouseId": "4500"
}
DELETE Delete an Order
DELETE {{serverURL}}/Orders(1500001L)
Deletes the order. Returns 400 if the entity is not an order.
Responses
204 204 No Content
No body.
400 400 Bad Request
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "The specified entity is not an order"
}
}
}
POST Link a Tag to Order
POST {{serverURL}}/Orders(1500001L)/$links/Tags
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/Tags(6001L)"
}
Responses
204 204 No Content
No body.
DELETE Unlink a Tag from Order
DELETE {{serverURL}}/Orders(1500001L)/$links/Tags(6001L)
Removes the tag. Alternative: DELETE …/$links/Tags with { "url": "…/Tags(6001L)" }.
Responses
204 204 No Content
No body.
POST Set the Destination of an Order
POST {{serverURL}}/Orders(1500001L)/$links/Destination
Sets the delivery destination (warehouse or service object).
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/ServiceObjects(4500L)"
}
Responses
204 204 No Content
No body.
DELETE Remove the Destination of an Order
DELETE {{serverURL}}/Orders(1500001L)/$links/Destination
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"url": "{{serverURL}}/ServiceObjects(4500L)"
}
Responses
204 204 No Content
No body.
Warehouse 18 endpoints
Warehouses are stock locations (central store, technician's van, consignment stock at a customer). A warehouse is a special service object (IsWarehouse) with an inventory of stock items and stock movements.
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Warehouses(123L). |
| Version | int | Row version, incremented on every update. Read-only. |
| Name | string | Warehouse name. Required. |
| Note | string | Free text. |
| CustomValues | CustomValue[] | Custom field values: [{ "Meta": "<field name>", "Value": "<value>" }]. |
| DateOfCreation | datetime | Date of creation (UTC). Read-only. |
| DateModified | datetime | Date of the last modification (UTC). Read-only. |
| ExternalId | string | Free identifier for your own system (ERP number, foreign key, …). |
| Location | Location | Address. See Company → Location attributes. |
| WarehouseManagerId | long | Contact id of the responsible manager (read). On create/update the manager is passed as the object WarehouseManager: { "Id": … }. |
| WarehouseManager | Contact | Manager contact. Required on create and update – send "WarehouseManager": { "Id": 3001 }; missing manager → 400 "WarehouseManager is mandatory you need to provide one". Navigation ($expand=WarehouseManager). |
| CompanyId | long | Owning company (own company or customer for consignment stock). |
| Company | Company | Company. Navigation. |
| Tags | Tag[] | Tags. Navigation. |
| Contacts | Contact[] | Contacts. Navigation. |
| Inventory | WarehouseInventoryItem[] | Stock items. GET/POST Warehouses(id)/Inventory, PUT/DELETE Warehouses(id)/Inventory(itemId). |
| Orders | Order[] | Orders delivered to this warehouse. GET Warehouses(id)/Orders. |
| StockMovements | StockMovement[] | Movements. GET/POST Warehouses(id)/StockMovements, PUT/DELETE …/StockMovements(id). |
Inventory item attributes (Warehouses(id)/Inventory)
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: WarehouseInventoryItems(123L). |
| Version | int | Row version, incremented on every update. Read-only. |
| ItemNumber | string | Article number. |
| NameOrNumber | string | Name. Required. |
| QuantityHours | decimal | Current stock quantity. |
| MinimumStock | int | Reorder level – below it an OrderBy demand is created. |
| MaximumStock | int | Target stock when reordering. |
| ItemTypeId | long | Article (item type). |
| ItemType | ItemType | Article. Navigation. |
| Price | decimal | Valuation price. |
| CreatorId | long | Creator contact. |
| Creator | Contact | Creator. Navigation. |
| UnitId | long | Unit. |
| Unit | ItemUnit | Unit. Navigation. |
Endpoints
GET Get Warehouses
GET {{serverURL}}/Warehouses?$expand=WarehouseManager,Location
All warehouses with manager and address.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Warehouses",
"value": [
{
"Id": "4500",
"Version": 1,
"Name": "Central store",
"Note": "Gate 3",
"CustomValues": [],
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"ExternalId": "WH-01",
"Location": {
"AddressString": "Lagerstraße 5",
"Postal": "10245",
"City": "Berlin",
"Country": "DE",
"Longitude": 13.45,
"Latitude": 52.5,
"IsValidLocation": true,
"IsMoveable": false
},
"WarehouseManagerId": "3001",
"CompanyId": "2000",
"WarehouseManager": {
"Id": "3001",
"FirstName": "Anna",
"LastName": "Office"
}
},
{
"Id": "4501",
"Version": 1,
"Name": "Van – Max Mustermann",
"CustomValues": [],
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"ExternalId": "WH-VAN-12",
"Location": {
"AddressString": "Lagerstraße 5",
"Postal": "10245",
"City": "Berlin",
"Country": "DE",
"Longitude": 13.45,
"Latitude": 52.5,
"IsValidLocation": true,
"IsMoveable": true
},
"WarehouseManagerId": "3002",
"CompanyId": "2000"
}
]
}
GET Retrieve a Warehouse
GET {{serverURL}}/Warehouses(4500L)?$expand=Inventory/ItemType,WarehouseManager
Warehouse with its stock.
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Warehouses/@Element",
"Id": "4500",
"Version": 1,
"Name": "Central store",
"Note": "Gate 3",
"CustomValues": [],
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"ExternalId": "WH-01",
"Location": {
"AddressString": "Lagerstraße 5",
"Postal": "10245",
"City": "Berlin",
"Country": "DE",
"Longitude": 13.45,
"Latitude": 52.5,
"IsValidLocation": true,
"IsMoveable": false
},
"WarehouseManagerId": "3001",
"CompanyId": "2000",
"Inventory": [
{
"Id": "24001",
"Version": 1,
"ItemNumber": "BB-6204",
"NameOrNumber": "Ball bearing 6204",
"QuantityHours": "35",
"MinimumStock": 10,
"MaximumStock": 50,
"ItemTypeId": "15001",
"Price": "3.10",
"CreatorId": "3001",
"UnitId": "16001",
"ItemType": {
"Id": "15001",
"NameOrNumber": "Ball bearing 6204",
"ExternalId": "BB-6204"
}
}
]
}
404 404 Not Found
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "The entity Warehouse with Key: 4500 can not be found"
}
}
}
POST Create a Warehouse
POST {{serverURL}}/Warehouses
Creates a warehouse. Name and WarehouseManager (as object with the contact Id) are required.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"Name": "Central store",
"ExternalId": "WH-01",
"Note": "Gate 3",
"WarehouseManager": {
"Id": 3001
},
"CompanyId": 2000,
"Location": {
"AddressString": "Lagerstraße 5",
"Postal": "10245",
"City": "Berlin",
"Country": "DE"
}
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Warehouses/@Element",
"Id": "4500",
"Version": 1,
"Name": "Central store",
"Note": "Gate 3",
"CustomValues": [],
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"ExternalId": "WH-01",
"Location": {
"AddressString": "Lagerstraße 5",
"Postal": "10245",
"City": "Berlin",
"Country": "DE",
"Longitude": 13.45,
"Latitude": 52.5,
"IsValidLocation": true,
"IsMoveable": false
},
"WarehouseManagerId": "3001",
"CompanyId": "2000"
}
400 400 Bad Request
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "WarehouseManager is mandatory you need to provide one"
}
}
}
PUT Update a Warehouse (PUT)
PUT {{serverURL}}/Warehouses(4500L)
Replaces the warehouse (GET first). WarehouseManager: { Id } must be present.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 4500,
"Name": "Central store",
"ExternalId": "WH-01",
"Note": "Gate 3, ring bell",
"WarehouseManager": {
"Id": 3001
},
"CompanyId": 2000,
"Location": {
"AddressString": "Lagerstraße 5",
"Postal": "10245",
"City": "Berlin",
"Country": "DE"
}
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Warehouses/@Element",
"Id": "4500",
"Version": 2,
"Name": "Central store",
"Note": "Gate 3, ring bell",
"CustomValues": [],
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"ExternalId": "WH-01",
"Location": {
"AddressString": "Lagerstraße 5",
"Postal": "10245",
"City": "Berlin",
"Country": "DE",
"Longitude": 13.45,
"Latitude": 52.5,
"IsValidLocation": true,
"IsMoveable": false
},
"WarehouseManagerId": "3001",
"CompanyId": "2000"
}
PATCH Update a Warehouse partially (PATCH)
PATCH {{serverURL}}/Warehouses(4500L)
Changes only the given properties. (The manager check still applies: a PATCH body without WarehouseManager is completed from the stored entity.)
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Note": "Gate 3, ring bell twice"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Warehouses/@Element",
"Id": "4500",
"Version": 2,
"Name": "Central store",
"Note": "Gate 3, ring bell twice",
"CustomValues": [],
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"ExternalId": "WH-01",
"Location": {
"AddressString": "Lagerstraße 5",
"Postal": "10245",
"City": "Berlin",
"Country": "DE",
"Longitude": 13.45,
"Latitude": 52.5,
"IsValidLocation": true,
"IsMoveable": false
},
"WarehouseManagerId": "3001",
"CompanyId": "2000"
}
DELETE Delete a Warehouse
DELETE {{serverURL}}/Warehouses(4500L)
Deletes the warehouse and its inventory records.
Responses
204 204 No Content
No body.
GET Get Warehouse Inventory
GET {{serverURL}}/Warehouses(4500L)/Inventory?$expand=ItemType,Unit
Stock items of the warehouse with article and unit.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#WarehouseInventoryItems",
"value": [
{
"Id": "24001",
"Version": 1,
"ItemNumber": "BB-6204",
"NameOrNumber": "Ball bearing 6204",
"QuantityHours": "35",
"MinimumStock": 10,
"MaximumStock": 50,
"ItemTypeId": "15001",
"Price": "3.10",
"CreatorId": "3001",
"UnitId": "16001",
"ItemType": {
"Id": "15001",
"NameOrNumber": "Ball bearing 6204"
},
"Unit": {
"Id": "16001",
"Name": "pcs"
}
}
]
}
POST Create an Inventory Item
POST {{serverURL}}/Warehouses(4500L)/Inventory
Adds an article to the warehouse stock with the initial quantity and reorder levels.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"ItemTypeId": 15001,
"NameOrNumber": "Ball bearing 6204",
"ItemNumber": "BB-6204",
"QuantityHours": 35,
"MinimumStock": 10,
"MaximumStock": 50,
"UnitId": 16001
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#WarehouseInventoryItems/@Element",
"Id": "24001",
"Version": 1,
"ItemNumber": "BB-6204",
"NameOrNumber": "Ball bearing 6204",
"QuantityHours": "35",
"MinimumStock": 10,
"MaximumStock": 50,
"ItemTypeId": "15001",
"Price": "3.10",
"CreatorId": "3001",
"UnitId": "16001"
}
PUT Update an Inventory Item
PUT {{serverURL}}/Warehouses(4500L)/Inventory(24001L)
Corrects quantity / reorder levels of a stock item.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 24001,
"ItemTypeId": 15001,
"NameOrNumber": "Ball bearing 6204",
"ItemNumber": "BB-6204",
"QuantityHours": 33,
"MinimumStock": 12,
"MaximumStock": 50,
"UnitId": 16001
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#WarehouseInventoryItems/@Element",
"Id": "24001",
"Version": 2,
"ItemNumber": "BB-6204",
"NameOrNumber": "Ball bearing 6204",
"QuantityHours": "33",
"MinimumStock": 12,
"MaximumStock": 50,
"ItemTypeId": "15001",
"Price": "3.10",
"CreatorId": "3001",
"UnitId": "16001"
}
DELETE Delete an Inventory Item
DELETE {{serverURL}}/Warehouses(4500L)/Inventory(24001L)
Removes the article from the warehouse.
Responses
204 204 No Content
No body.
GET Get Warehouse Stock Movements
GET {{serverURL}}/Warehouses(4500L)/StockMovements?$filter=State eq 'Open'&$expand=ItemType
Movements of the warehouse (e.g. open demands).
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#StockMovements",
"value": [
{
"Id": "25001",
"Version": 1,
"Amount": "20",
"AmountReceived": "0",
"ItemTypeId": "15001",
"StockMovementType": "OrderBy",
"State": "Open",
"WarehouseId": "4500",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"TargetDate": "2026-09-10T00:00:00Z",
"CreatedById": "3001",
"ItemType": {
"Id": "15001",
"NameOrNumber": "Ball bearing 6204"
}
}
]
}
POST Create a Stock Movement in a Warehouse
POST {{serverURL}}/Warehouses(4500L)/StockMovements
Same as POST StockMovements with WarehouseId preset.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"ItemTypeId": 15001,
"Amount": 20,
"StockMovementType": "OrderBy",
"TargetDate": "2026-09-10T00:00:00Z"
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#StockMovements/@Element",
"Id": "25001",
"Version": 1,
"Amount": "20",
"AmountReceived": "0",
"ItemTypeId": "15001",
"StockMovementType": "OrderBy",
"State": "Open",
"WarehouseId": "4500",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"TargetDate": "2026-09-10T00:00:00Z",
"CreatedById": "3001"
}
PUT Update a Stock Movement in a Warehouse
PUT {{serverURL}}/Warehouses(4500L)/StockMovements(25001L)
Confirms / edits a movement. The movement must belong to the warehouse (400 otherwise).
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 25001,
"ItemTypeId": 15001,
"Amount": 20,
"AmountReceived": 20,
"StockMovementType": "OrderBy",
"State": "Confirmed",
"WarehouseId": 4500,
"DeliveryDate": "2026-09-09T00:00:00Z"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#StockMovements/@Element",
"Id": "25001",
"Version": 2,
"Amount": "20",
"AmountReceived": "20",
"ItemTypeId": "15001",
"StockMovementType": "OrderBy",
"State": "Confirmed",
"WarehouseId": "4500",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"TargetDate": "2026-09-10T00:00:00Z",
"CreatedById": "3001",
"DeliveryDate": "2026-09-09T00:00:00Z"
}
DELETE Delete a Stock Movement in a Warehouse
DELETE {{serverURL}}/Warehouses(4500L)/StockMovements(25001L)
Deletes the movement (only possible through the warehouse navigation).
Responses
204 204 No Content
No body.
GET Get Warehouse Orders
GET {{serverURL}}/Warehouses(4500L)/Orders?$expand=Items
Orders delivered to this warehouse.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Orders",
"value": [
{
"Id": "1500001",
"Version": 1,
"Name": "Order – Bearings Ltd",
"ExternalId": "PO-2026-017",
"State": "Created",
"SupplierId": "2100",
"WarehouseId": "4500",
"DateOfCreation": "2026-08-25T08:00:00Z",
"Items": []
}
]
}
POST Create an Order in a Warehouse (not supported)
POST {{serverURL}}/Warehouses(4500L)/Orders
Documented for completeness: returns 405. Create orders with POST Orders { SupplierId, WarehouseId }.
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"SupplierId": 2100
}
Responses
405 405 Method Not Allowed
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "Creating orders on a warehouse is not supported. Please create them through the Orders endpoint (POST /Orders) with a WarehouseId."
}
}
}
PUT Update an Order in a Warehouse
PUT {{serverURL}}/Warehouses(4500L)/Orders(1500001L)
Updates an order of this warehouse (400 if it belongs to another warehouse).
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 1500001,
"Name": "Order – Bearings Ltd",
"ExternalId": "PO-2026-017",
"State": "OrderPrinted",
"SupplierId": 2100,
"WarehouseId": 4500
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Orders/@Element",
"Id": "1500001",
"Version": 2,
"Name": "Order – Bearings Ltd",
"ExternalId": "PO-2026-017",
"State": "OrderPrinted",
"SupplierId": "2100",
"WarehouseId": "4500",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z"
}
DELETE Delete an Order in a Warehouse
DELETE {{serverURL}}/Warehouses(4500L)/Orders(1500001L)
Deletes an order of this warehouse.
Responses
204 204 No Content
No body.
Stock Movement 6 endpoints
Stock Movements record demand and flow of articles: reorder demands (OrderBy), returns, refills and corrections. Open OrderBy movements are turned into Orders; confirming a movement updates the warehouse inventory.
Movements cannot be deleted through this set (use DELETE Warehouses(id)/StockMovements(id)).
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: StockMovements(123L). |
| Version | int | Row version, incremented on every update. Read-only. |
| Amount | decimal | Quantity moved / demanded. Required. |
| AmountReceived | decimal | Quantity actually received (set on confirmation). |
| ExternalId | string | Free identifier for your own system (ERP number, foreign key, …). |
| ItemId | long | Job item that caused the movement (consumption). |
| Item | Item | Job item. Navigation. |
| ItemTypeId | long | Article. Required (unless ItemId is given). |
| ItemType | ItemType | Article. Navigation. |
| StockMovementType | string | See StockMovementType values. Required. |
| State | string | See State values. Default Open. |
| ServiceRequestId | long | Job the movement belongs to (consumption / return). |
| ServiceRequest | ServiceRequest | Job. Navigation. |
| WarehouseId | long | Warehouse. Required. |
| Warehouse | ServiceObject | Warehouse (service object). Navigation. |
| DateOfCreation | datetime | Date of creation (UTC). Read-only. |
| DateModified | datetime | Date of the last modification (UTC). Read-only. |
| TargetDate | datetime | Requested date. |
| CreatedById | long | Creator contact. |
| CreatedBy | Contact | Creator. Navigation. |
| ConfirmedById | long | Contact who confirmed. |
| ConfirmedBy | Contact | Confirmer. Navigation. |
| DeliveryDate | datetime | Actual delivery date. |
| SourceWarehouseId | long | Source warehouse for transfers. |
StockMovementType values
| Value | Meaning |
|---|
| OrderBy | Demand: article to be ordered from the supplier (collected by Orders). |
| ReturnBy | Return to the warehouse. |
| FillUp | Refill of a car stock / consumption on a job. |
| Corrected | Manual stock correction. |
State values
| Value | Meaning |
|---|
| Open | Created, not yet processed. |
| Confirmed | Goods received / movement confirmed (AmountReceived). |
| Closed | Completed. |
| Canceled | Cancelled. |
Endpoints
GET Get Stock Movements
GET {{serverURL}}/StockMovements?$filter=State eq 'Open' and StockMovementType eq 'OrderBy'&$expand=ItemType,Warehouse
Open demands across all warehouses – what needs to be ordered.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#StockMovements",
"value": [
{
"Id": "25001",
"Version": 1,
"Amount": "20",
"AmountReceived": "0",
"ItemTypeId": "15001",
"StockMovementType": "OrderBy",
"State": "Open",
"WarehouseId": "4500",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"TargetDate": "2026-09-10T00:00:00Z",
"CreatedById": "3001",
"ItemType": {
"Id": "15001",
"NameOrNumber": "Ball bearing 6204"
},
"Warehouse": {
"Id": "4500",
"Name": "Central store"
}
}
]
}
GET Get Stock Movements of a Service Request
GET {{serverURL}}/StockMovements?$filter=ServiceRequestId eq 1234567890L
Material flow caused by a job.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#StockMovements",
"value": [
{
"Id": "25002",
"Version": 1,
"Amount": "2",
"AmountReceived": "0",
"ItemTypeId": "15001",
"StockMovementType": "FillUp",
"State": "Closed",
"WarehouseId": "4501",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"TargetDate": "2026-09-10T00:00:00Z",
"CreatedById": "3001",
"ServiceRequestId": "1234567890",
"ItemId": "17001"
}
]
}
GET Retrieve a Stock Movement
GET {{serverURL}}/StockMovements(25001L)
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#StockMovements/@Element",
"Id": "25001",
"Version": 1,
"Amount": "20",
"AmountReceived": "0",
"ItemTypeId": "15001",
"StockMovementType": "OrderBy",
"State": "Open",
"WarehouseId": "4500",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"TargetDate": "2026-09-10T00:00:00Z",
"CreatedById": "3001"
}
POST Create a Stock Movement
POST {{serverURL}}/StockMovements
Creates a movement, e.g. a reorder demand.
| Body | Type | Description |
|---|
| WarehouseId | long | Required. |
| ItemTypeId | long | Required. Article. |
| Amount | decimal | Required. |
| StockMovementType | string | Required. OrderBy, ReturnBy, FillUp, Corrected. |
| State | string | Default Open. |
| ServiceRequestId, TargetDate, SourceWarehouseId, ExternalId | | Optional. |
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"WarehouseId": 4500,
"ItemTypeId": 15001,
"Amount": 20,
"StockMovementType": "OrderBy",
"TargetDate": "2026-09-10T00:00:00Z"
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#StockMovements/@Element",
"Id": "25001",
"Version": 1,
"Amount": "20",
"AmountReceived": "0",
"ItemTypeId": "15001",
"StockMovementType": "OrderBy",
"State": "Open",
"WarehouseId": "4500",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"TargetDate": "2026-09-10T00:00:00Z",
"CreatedById": "3001"
}
PATCH Confirm a Stock Movement (PATCH)
PATCH {{serverURL}}/StockMovements(25001L)
Books the goods receipt: sets AmountReceived and Confirmed; the inventory quantity is updated.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"State": "Confirmed",
"AmountReceived": 20,
"DeliveryDate": "2026-09-09T00:00:00Z"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#StockMovements/@Element",
"Id": "25001",
"Version": 2,
"Amount": "20",
"AmountReceived": "20",
"ItemTypeId": "15001",
"StockMovementType": "OrderBy",
"State": "Confirmed",
"WarehouseId": "4500",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"TargetDate": "2026-09-10T00:00:00Z",
"CreatedById": "3001",
"DeliveryDate": "2026-09-09T00:00:00Z",
"ConfirmedById": "3001"
}
PUT Update a Stock Movement (PUT)
PUT {{serverURL}}/StockMovements(25001L)
Replaces the movement (GET first).
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 25001,
"WarehouseId": 4500,
"ItemTypeId": 15001,
"Amount": 25,
"AmountReceived": 0,
"StockMovementType": "OrderBy",
"State": "Open",
"TargetDate": "2026-09-12T00:00:00Z"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#StockMovements/@Element",
"Id": "25001",
"Version": 2,
"Amount": "25",
"AmountReceived": "0",
"ItemTypeId": "15001",
"StockMovementType": "OrderBy",
"State": "Open",
"WarehouseId": "4500",
"DateOfCreation": "2026-08-25T08:00:00Z",
"DateModified": "2026-08-25T08:00:00Z",
"TargetDate": "2026-09-12T00:00:00Z",
"CreatedById": "3001"
}
WebHooks 5 endpoints
WebHooks push notifications to your system when something happens in MFR, so you do not have to poll. Register a callback URL per event type (max. 5 webhooks per type).
- MFR calls the URL with an HTTP POST carrying a JSON payload with two parts:
WebHook (event data, e.g. PreviousState / NewState) and Payload (a compact view of the entity – id, name, external id, state, customer/destination ids). Fetch the entity afterwards with a normal OData request (GET {Set}(id)?$expand=…) for the full details – do not rely on the payload alone.
{
"WebHook": { "PreviousState": "eReleased", "NewState": "eClosed" },
"Payload": {
"Id": 1234567890, "Name": "Repair heating pump", "ExternalId": "ERP-4711",
"State": "Closed", "StateCode": "eClosed", "InvoiceId": null,
"Description": "<p>Pump makes noise, check bearing.</p>",
"CustomerId": 2001, "DestinationId": 4001
}
}
- The callback must answer within 2 seconds; otherwise the call is aborted. Failing hooks are marked (
LastAttempt, BrokenSince). - Use HTTPS and put a secret token into the URL (e.g.
?token=…); credentials in the URL are not supported.
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: WebHooks(123L). |
| Version | int | Row version, incremented on every update. Read-only. |
| UserId | long | Owner of the webhook (the API user). Read-only. |
| WebHookType | string | Event type – see WebHookType values. Required. |
| CallbackUrl | string | HTTPS URL that receives the POST. Required. |
| ExternalId | string | Your description / identifier. |
| DateOfCreation | datetime | Date of creation (UTC). Read-only. |
| LastAttempt | datetime | Last delivery attempt. Read-only. |
| BrokenSince | datetime | Set when deliveries keep failing. Read-only. |
WebHookType values
| Value | Meaning |
|---|
| ServiceRequestStateChanged | The state of a job changed (released, closed, …). |
| NewServiceRequest | A job was created. |
| NewAppointment | An appointment was created / assigned. |
| AppointmentChanged | An appointment was modified (time, technician, state). |
| NewCompany | A customer was created. |
| NewServiceObject | A service object was created. |
| NewTimeEvent | A time recording was created. |
| NewReport | A report was generated. |
| NewInvoice | An invoice was generated. |
| NewPurchaseInvoiceDocument | A purchase invoice document was uploaded. |
| TagServiceRequestAdded / TagServiceRequestRemoved | A tag was added to / removed from a job. |
| TagCompanyAdded / TagCompanyRemoved | A tag was added to / removed from a company. |
| TagServiceObjectAdded / TagServiceObjectRemoved | A tag was added to / removed from a service object. |
Endpoints
GET Get WebHooks
GET {{serverURL}}/WebHooks
All webhooks of the API user.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#WebHooks",
"value": [
{
"Id": "18001",
"Version": 1,
"UserId": "1001",
"WebHookType": "ServiceRequestStateChanged",
"CallbackUrl": "https://erp.example.com/mfr/hooks?token=s3cr3t",
"ExternalId": "ERP job sync",
"DateOfCreation": "2026-08-25T08:00:00Z"
}
]
}
GET Retrieve a WebHook
GET {{serverURL}}/WebHooks(18001L)
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#WebHooks/@Element",
"Id": "18001",
"Version": 1,
"UserId": "1001",
"WebHookType": "ServiceRequestStateChanged",
"CallbackUrl": "https://erp.example.com/mfr/hooks?token=s3cr3t",
"ExternalId": "ERP job sync",
"DateOfCreation": "2026-08-25T08:00:00Z"
}
POST Create a WebHook
POST {{serverURL}}/WebHooks
Registers a callback. Fails with 400 when 5 webhooks of that type already exist ("You cannot have more than 5 Webhooks of the same type…") or the URL is invalid ("Invalid webhook url!").
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"WebHookType": "ServiceRequestStateChanged",
"CallbackUrl": "https://erp.example.com/mfr/hooks?token=s3cr3t",
"ExternalId": "ERP job sync"
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#WebHooks/@Element",
"Id": "18001",
"Version": 1,
"UserId": "1001",
"WebHookType": "ServiceRequestStateChanged",
"CallbackUrl": "https://erp.example.com/mfr/hooks?token=s3cr3t",
"ExternalId": "ERP job sync",
"DateOfCreation": "2026-08-25T08:00:00Z"
}
400 400 Bad Request
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "You cannot have more than 5 Webhooks of the same typeServiceRequestStateChanged. Delete otheres first"
}
}
}
PUT Update a WebHook
PUT {{serverURL}}/WebHooks(18001L)
Changes the callback URL / description.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 18001,
"WebHookType": "ServiceRequestStateChanged",
"CallbackUrl": "https://erp.example.com/mfr/hooks/v2?token=s3cr3t",
"ExternalId": "ERP job sync"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#WebHooks/@Element",
"Id": "18001",
"Version": 2,
"UserId": "1001",
"WebHookType": "ServiceRequestStateChanged",
"CallbackUrl": "https://erp.example.com/mfr/hooks/v2?token=s3cr3t",
"ExternalId": "ERP job sync",
"DateOfCreation": "2026-08-25T08:00:00Z"
}
DELETE Delete a WebHook
DELETE {{serverURL}}/WebHooks(18001L)
Unregisters the callback.
Responses
204 204 No Content
No body.
Report Definition 6 endpoints
Report Definitions are the templates (HTML + JavaScript helpers) that reports and invoices are rendered from. The API lets you manage them programmatically – e.g. to deploy the same layout to several accounts.
Attributes
| Attribute | Type | Description |
|---|
| Id | long | Unique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: ReportDefinitions(123L). |
| Version | int | Row version, incremented on every update. Read-only. |
| Code | string | Unique code, generated by the server. Do not send on create. |
| HtmlTemplate | string | HTML body template (Handlebars-style). May be sent Base64-encoded. |
| JsHelpers | string | JavaScript helpers used by the template. May be sent Base64-encoded. |
| ConfigJson | string | Designer configuration JSON (stored inside JsHelpers between // === Configuration === markers). |
| HtmlHeaderTemplate | string | Page header HTML (when HasHeader). May be Base64-encoded. |
| HtmlFooterTemplate | string | Page footer HTML (when HasFooter). May be Base64-encoded. |
| IsDefault | bool | Default definition for its type. |
| IsEnabled | bool | Offered to users. |
| VisibleName | string | Display name. Required. |
| DateModified | string | Last modification. Read-only. |
| RequiredCustomValues | string | Comma-separated custom value names the template needs. |
| RequiredStepTrackingIds | string | Comma-separated step tracking ids the template needs. |
| RequiredTemplateId | long | Step list template the report requires on the job. |
| FileType | string | Output type – see Report → FileType values (e.g. Pdf, PdfInvoice, HtmlToXlsx). |
| DataSource | string | Data the template is rendered with (e.g. ServiceRequest, ServiceObject, Company, Appointment, …). |
| ReportingEngine | string | CHROME (default), WKHTMLTOPDF, PHANTOMJS or HtmlToXlsx. |
| Note | string | Internal note. |
| HasHeader | bool | Render HtmlHeaderTemplate on every page. |
| HasFooter | bool | Render HtmlFooterTemplate on every page. |
| ServiceRequestExpandQueryString | string | Additional $expand applied when loading the job for rendering. |
Endpoints
GET Get Report Definitions
GET {{serverURL}}/ReportDefinitions?$select=Id,Code,VisibleName,FileType,DataSource,IsEnabled,IsDefault
All definitions – $select avoids downloading the templates.
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ReportDefinitions",
"value": [
{
"Id": "23001",
"Code": "SERVICE_REPORT",
"VisibleName": "Service report",
"FileType": "Pdf",
"DataSource": "ServiceRequest",
"IsEnabled": true,
"IsDefault": true
},
{
"Id": "23002",
"Code": "INVOICE",
"VisibleName": "Invoice",
"FileType": "PdfInvoice",
"DataSource": "ServiceRequest",
"IsEnabled": true,
"IsDefault": true
}
]
}
GET Retrieve a Report Definition
GET {{serverURL}}/ReportDefinitions(23001L)
Full definition including templates.
Headers
| Header | Value |
|---|
| ProperStatusCodes | true |
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ReportDefinitions/@Element",
"Id": "23001",
"Version": 1,
"Code": "SERVICE_REPORT",
"HtmlTemplate": "<h1>{{Name}}</h1> …",
"JsHelpers": "// helpers …",
"ConfigJson": "{}",
"HtmlHeaderTemplate": "<div class=\"header\">{{Customer.Name}}</div>",
"HtmlFooterTemplate": "<div class=\"footer\">Page {{page}}</div>",
"IsDefault": true,
"IsEnabled": true,
"VisibleName": "Service report",
"DateModified": "2026-08-25T08:00:00Z",
"FileType": "Pdf",
"DataSource": "ServiceRequest",
"ReportingEngine": "CHROME",
"HasHeader": true,
"HasFooter": true
}
POST Create a Report Definition
POST {{serverURL}}/ReportDefinitions
Creates a definition. VisibleName is required; Code is generated – sending one is rejected. Template fields may be plain text or Base64 (recommended for HTML/JS to avoid escaping issues).
Headers
| Header | Value |
|---|
| Content-Type | application/json |
Request body
{
"VisibleName": "Service report (API)",
"FileType": "Pdf",
"DataSource": "ServiceRequest",
"ReportingEngine": "CHROME",
"IsEnabled": true,
"HasHeader": false,
"HasFooter": false,
"HtmlTemplate": "PGgxPnt7TmFtZX19PC9oMT4=",
"JsHelpers": "Ly8gaGVscGVycw==",
"ConfigJson": "{}"
}
Responses
201 201 Created
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ReportDefinitions/@Element",
"Id": "23003",
"Version": 1,
"Code": "SERVICE_REPORT_API",
"HtmlTemplate": "<h1>{{Name}}</h1> …",
"JsHelpers": "// helpers …",
"ConfigJson": "{}",
"HtmlHeaderTemplate": "<div class=\"header\">{{Customer.Name}}</div>",
"HtmlFooterTemplate": "<div class=\"footer\">Page {{page}}</div>",
"IsDefault": false,
"IsEnabled": true,
"VisibleName": "Service report (API)",
"DateModified": "2026-08-25T08:00:00Z",
"FileType": "Pdf",
"DataSource": "ServiceRequest",
"ReportingEngine": "CHROME",
"HasHeader": false,
"HasFooter": false
}
400 400 Bad Request
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "Code must not be provided; it is generated on creation."
}
}
}
400 400 Bad Request (missing VisibleName)
{
"odata.error": {
"code": "",
"message": {
"lang": "en-US",
"value": "VisibleName is required"
}
}
}
PUT Update a Report Definition
PUT {{serverURL}}/ReportDefinitions(23003L)
Replaces the definition (GET first, send everything back – templates included).
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"Id": 23003,
"VisibleName": "Service report (API) v2",
"FileType": "Pdf",
"DataSource": "ServiceRequest",
"ReportingEngine": "CHROME",
"IsEnabled": true,
"HasHeader": true,
"HtmlHeaderTemplate": "PGRpdj5IZWFkZXI8L2Rpdj4=",
"HtmlTemplate": "PGgxPnt7TmFtZX19PC9oMT4=",
"JsHelpers": "Ly8gaGVscGVycw==",
"ConfigJson": "{}"
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ReportDefinitions/@Element",
"Id": "23003",
"Version": 2,
"Code": "SERVICE_REPORT_API",
"HtmlTemplate": "<h1>{{Name}}</h1> …",
"JsHelpers": "// helpers …",
"ConfigJson": "{}",
"HtmlHeaderTemplate": "<div class=\"header\">{{Customer.Name}}</div>",
"HtmlFooterTemplate": "<div class=\"footer\">Page {{page}}</div>",
"IsDefault": true,
"IsEnabled": true,
"VisibleName": "Service report (API) v2",
"DateModified": "2026-08-25T08:00:00Z",
"FileType": "Pdf",
"DataSource": "ServiceRequest",
"ReportingEngine": "CHROME",
"HasHeader": true,
"HasFooter": true
}
PATCH Enable / Disable a Report Definition (PATCH)
PATCH {{serverURL}}/ReportDefinitions(23003L)
Partial update without touching the templates.
Headers
| Header | Value |
|---|
| Prefer | return-content |
| Content-Type | application/json |
Request body
{
"IsEnabled": false
}
Responses
200 200 OK
{
"odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ReportDefinitions/@Element",
"Id": "23003",
"Version": 2,
"Code": "SERVICE_REPORT_API",
"HtmlTemplate": "<h1>{{Name}}</h1> …",
"JsHelpers": "// helpers …",
"ConfigJson": "{}",
"HtmlHeaderTemplate": "<div class=\"header\">{{Customer.Name}}</div>",
"HtmlFooterTemplate": "<div class=\"footer\">Page {{page}}</div>",
"IsDefault": true,
"IsEnabled": false,
"VisibleName": "Service report",
"DateModified": "2026-08-25T08:00:00Z",
"FileType": "Pdf",
"DataSource": "ServiceRequest",
"ReportingEngine": "CHROME",
"HasHeader": true,
"HasFooter": true
}
DELETE Delete a Report Definition
DELETE {{serverURL}}/ReportDefinitions(23003L)
Deletes the definition. Already generated reports are kept.
Responses
204 204 No Content
No body.