MFR Developer API Documentation
33 entity sets · 293 documented endpoints · generated 2026-08-25

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 URLhttps://portal.mobilefieldreport.com/odata (written as {{serverURL}})
Host for non-OData endpointshttps://portal.mobilefieldreport.com (written as {{baseURL}})
Metadata documentGET {{serverURL}}/$metadata
ProtocolOData v3, JSON light (application/json;odata=minimalmetadata)
AuthenticationHTTP Basic (e-mail address / password of an API user)

Getting started

  1. Ask your MFR administrator for a user with the API permission (see Authentication); its e-mail address and password are used for HTTP Basic authentication.
  2. Throughout this documentation {{serverURL}} stands for https://portal.mobilefieldreport.com/odata and {{baseURL}} for https://portal.mobilefieldreport.com. Replace them with your test environment if you have one.
  3. Try GET {{serverURL}}/ServiceRequests?$top=5 with your credentials – you should receive a JSON document with a value array.
  4. To run every request shown here directly, import the Postman collection MFR-OData-Extended.postman_collection.json (same content as this page).

Authentication & permissions

All requests need HTTP Basic authentication with the e-mail address and password of an MFR user. Send the Authorization: Basic <base64(email:password)> header with every request.

Rate limiting

Each user has a budget of 60 points per minute. A GET costs 1 point, every other verb (POST, PUT, PATCH, DELETE, $batch) costs 4 points – i.e. 60 reads or 15 writes per minute. Requests above the budget are not rejected but delayed by 500 ms per point over the limit, so a burst of writes gets slower and slower. Additionally:

Use $batch or paging to keep the number of round trips low, and use $select/$expand to fetch exactly what you need.

Conventions

Keys and numbers
Query options
OptionExampleNotes
$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/ContactsLoads navigation properties in the same request. Max depth 5. Navigations are never included unless expanded.
$select$select=Id,Name,StateRestricts 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.
/$countGET {{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
VerbBehaviour
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)" }
Creating related entities

Some children can be created directly under their parent, which sets the parent link for you:

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" }
  }
}
StatusMeaning
400Validation or business-rule violation (message explains what is wrong).
401Missing/invalid credentials or missing API permission.
404Entity not found (with ProperStatusCodes, on PATCH, and on most write endpoints).
405Operation not supported on this set (e.g. POST Warehouses(id)/Orders).
429Login throttling – wait for Retry-After.
500Unexpected 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).

Webhooks

Instead of polling, register WebHooks to get notified about new/changed service requests, appointments, companies, etc. See the WebHooks chapter.

Entity sets

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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: ServiceRequests(123L).
NamestringTitle of the job. Required on create.
ExternalIdstringFree identifier for your own system (ERP number, foreign key, …).
InvoiceIdstringInvoice number if the job has been invoiced. Read-only.
CreatedByContactContact of the user who created the job. Navigation, read-only.
ClosedByUserUser who closed the job. Navigation, read-only.
ReleasedByUserUser who released the job. Navigation, read-only.
ClosedAtdatetimeWhen the job was closed. Read-only.
ReleasedAtdatetimeWhen the job was released. Read-only.
WorkDoneAtdatetimeWhen the technician reported the work as done. Read-only.
TargetTimeInMinuteslongPlanned duration in minutes.
DateModifieddatetimeDate of the last modification (UTC). Read-only.
DateOfCreationdatetimeDate of creation (UTC). Read-only.
DueDateRangeStartdatetimeStart of the due-date window.
DueDateRangeEnddatetimeEnd of the due-date window (deadline).
PortalLinkstringCustomer-portal link (see the ResolveCustomerPortalLink action). Read-only.
CostCenterIdlongId of the cost center / project the job belongs to.
CostCenterCostCenterNavigation property (CostCenter). Load it with $expand=CostCenter.
DescriptionstringDescription of the work (may contain HTML).
StatestringWorkflow state – see the table below. Serialized without the e prefix used internally (Released, not eReleased).
DestinationServiceObjectThe service object where the work takes place (root service object). Navigation.
AppointmentsAppointment[]Appointments (planned visits). Navigation – $expand=Appointments/Contacts includes the technicians.
ItemsItem[]Material / services booked on the job. Navigation.
CustomValuesCustomValue[]Custom field values: [{ "Meta": "<field name>", "Value": "<value>" }].
DocumentIdslong[]Ids of linked documents. Read-only.
DocumentsDocument[]Linked documents. Navigation.
ReportsReport[]Generated reports and invoices. Navigation.
ContactIdslong[]Ids of linked contacts. Read-only.
ContactsContact[]Customer contacts linked to the job. Navigation.
ServiceObjectIdslong[]Ids of linked service objects. Read-only.
StepListTemplatesStepListTemplate[]Checklist templates applied to the job. Navigation.
ServiceObjectsServiceObject[]Service objects / products of this job. Navigation – $expand=ServiceObjects/Location includes addresses.
StepListTemplateIdslong[]Ids of the applied checklist templates. Read-only.
TimeEventsTimeEvent[]Time recordings of the job. Navigation.
CommentsComment[]Comments. Navigation.
CurrentOwnerIdlongId of the contact (office user) responsible for the job.
CurrentOwnerContactResponsible office user. Navigation.
CustomerIdlongId of the customer company.
ParentServiceRequestIdlongId of the parent job (follow-up jobs).
CustomerCompanyCustomer company. Navigation.
LocationLocationLocation of the job (copied from the destination). Navigation.
VersionintRow version, incremented on every update. Read-only.
TagIdslong[]Ids of the assigned tags. Read-only – use $links/Tags.
TagsTag[]Assigned tags. Navigation.
StepsStep[]Checklist steps. Navigation – $expand=Steps (use Steps/StepListTemplate or Steps/Attachments for more).
StockMovementsStockMovement[]Stock movements booked on the job. Navigation.
IsTemplatebooltrue for service request templates. Filter IsTemplate eq true lists templates instead of jobs.
IsTemplateMobileboolTemplate is offered on the mobile app for ad-hoc jobs.
CreateFromServiceRequestTemplateIdlongWrite-only on create: id of the template the new job is copied from (steps, items, documents).
TypestringKind of service request – see the table below. Read-only.
QualificationsQualification[]Qualifications a technician needs for this job. Navigation.
InvoicesInvoice[]Invoices generated from this job. Navigation.
State values
ValueMeaning
CreatedJob created, not planned yet (Open).
ReadyForSchedulingJob is complete and waits for planning.
ScheduledAn appointment exists but the job is not released yet.
ReleasedReleased to the technician(s); visible on the mobile app.
InProgressA technician is working on the job.
IsWorkDoneTechnician reported the work as done; waiting for office approval.
ClosedApproved and closed.
InvoicedAn invoice was generated for the job.
RejectedRejected / cancelled.
WaitingForResponseWaiting for a response from the customer.
SubcontractorPendingConfirmation / SubcontractorConfirmed / SubcontractorRejected / SubcontractorAdditionalTasksSubcontractor workflow states.
CollaborationWaitingConfirmation / CollaborationRejected / CollaborationMerged / CollaborationAdditionalTasksCollaboration (multi-tenant) workflow states.
OfferIsSend / OfferIsConfirmed / OfferIsConfirmedAndCreateJob / OfferIsRejected / OfferIsExpired / OfferIsCancelledUsed by Offers only.
OrderPrinted / OrderCancelledUsed by Orders only.
Type values
ValueMeaning
IsServiceRequestRegular job (default).
IsStandardTemplateService request template.
IsProjectSRTemplateTemplate that belongs to a project.
IsRecurringJobJob generated by a recurring event.
IsMaintenanceMaintenance job.
IsOfferOffer – exposed through the Offers set.
IsOrderOrder – exposed through the Orders set.
IsCustomerRequestCustomer request – exposed through the CustomerRequests set.
IsInvoiceInvoice draft – used by CreateInvoiceDraft / POST Invoices.
IsProjectProject – exposed through the Projects set.
IsActivity / IsHoliday / IsAdditionalCosts / IsInventoryInternal types.
Useful filters
FilterEffect
$filter=IsTemplate eq trueReturns 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 123LJobs of a customer.
$filter=ExternalId eq 'ERP-4711'Lookup by your own id.

Endpoints

MethodURLDescription
GET{{serverURL}}/ServiceRequests?$top=50&$orderby=DateModified descGet Service Requests
GET{{serverURL}}/ServiceRequests?$expand=Customer,ServiceObjects/Location,Appointments/Contacts,Tags,Steps&$select=Id,Name,State,Customer,ServiceObjects,Appointments,Tags,Steps&$top=20Get Service Requests with related data
GET{{serverURL}}/ServiceRequests?$filter=DateModified gt datetime'2026-08-01T00:00:00Z' and State eq 'Closed'&$orderby=DateModifiedGet Service Requests modified since (delta sync)
GET{{serverURL}}/ServiceRequests?$filter=IsTemplate eq true&$expand=Steps,ItemsGet Service Request Templates
GET{{serverURL}}/ServiceRequests/$count?$filter=State eq 'Released'Count Service Requests
GET{{serverURL}}/ServiceRequests(1234567890L)?$expand=Customer,Destination,Contacts,Documents,QualificationsRetrieve a Service Request
POST{{serverURL}}/ServiceRequestsCreate a Service Request
POST{{serverURL}}/ServiceRequestsCreate a Service Request from a Template
POST{{serverURL}}/ServiceRequests/DeepCreate 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)/CommentsGet Comments of a Service Request
POST{{serverURL}}/ServiceRequests(1234567890L)/AppointmentsCreate an Appointment for a Service Request
POST{{serverURL}}/ServiceRequests(1234567890L)/$links/ServiceObjectsLink 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/TagsLink 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/QualificationsLink 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/ContactsLink a Contact to a Service Request
POST{{serverURL}}/ServiceRequests(1234567890L)/$links/DocumentsLink a Document to a Service Request
POST{{serverURL}}/ServiceRequests(1234567890L)/$links/StepListTemplatesLink a Step List Template to a Service Request
POST{{serverURL}}/ServiceRequests(1234567890L)/ResolveCustomerPortalLinkAction: Resolve Customer Portal Link
POST{{serverURL}}/ServiceRequests(1234567890L)/CreateInvoiceDraftAction: Create Invoice Draft
POST{{serverURL}}/ServiceRequests(1234567890L)/BestTechnicianForJobAction: 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 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

HeaderValue
ProperStatusCodestrue

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.

BodyTypeDescription
NamestringRequired.
CustomerIdlongCustomer company. Alternatively Customer: { "Id": ... }.
CurrentOwnerIdlongResponsible office contact.
Description, ExternalId, TargetTimeInMinutes, DueDateRangeStart/End, CostCenterId, CustomValuesOptional.
CreateFromServiceRequestTemplateIdlongCopy steps, items and documents from a template (see next request).
StatestringOptional 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

HeaderValue
Content-Typeapplication/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

HeaderValue
Content-Typeapplication/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.

AttributeTypeDescription
NamestringRequired. Job title.
DescriptionstringJob description.
CustomerCompanyCustomer to create or reuse (Id, Name, ExternalId, CreateGeoLocation, IsPhysicalPerson, Location).
ServiceObjectsServiceObject[]Service objects to create or reuse (Id, Name, ExternalId, CreateGeoLocation, Location, Contacts[]).
StatestringInitial state.
CreateFromServiceRequestTemplateIdlongTemplate to copy from.

Headers

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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: CreatedReadyForScheduling → (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

HeaderValue
Preferreturn-content
Content-Typeapplication/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.

GET Get Comments of a Service Request

GET {{serverURL}}/ServiceRequests(1234567890L)/Comments

Navigation: all comments of the job (equivalent to Comments?$filter=ServiceRequestId eq 1234567890L).

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Comments",
  "value": [
    {
      "Id": "8001",
      "Version": 1,
      "DateOfCreation": "2026-08-25T08:00:00Z",
      "IsInternal": false,
      "IsCustomer": false,
      "OwnerId": "3001",
      "ServiceRequestId": "1234567890",
      "Content": "Customer will be on site from 8:00"
    }
  ]
}

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

HeaderValue
Content-Typeapplication/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 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

HeaderValue
Content-Typeapplication/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.

ParameterTypeDescription
maxDistanceintMaximum distance to the job location in km.
startDateTime / endDateTimedatetimeTime 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

HeaderValue
Content-Typeapplication/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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Appointments(123L).
VersionintRow version, incremented on every update. Read-only.
StatestringProgress of the visit – see State values. Read-only (set by the technician).
TypestringSame as AppointmentType; kept for backwards compatibility. Use AppointmentType.
AppointmentTypestringKind of appointment – see AppointmentType values. Default Standard.
CreatedAtdatetimeDate of creation (UTC). Read-only.
EndDateTimedatetimePlanned end (UTC). Required.
StartDateTimedatetimePlanned start (UTC). Required.
DrivingDistanceFromintDriving distance to the site in km (calculated).
DrivingDistanceTointDriving distance from the site in km (calculated).
WasReadOnClientSideboolThe technician has seen the appointment on the mobile app. Read-only.
ContactIdslong[]Ids of all assigned technicians (contacts). Read-only – set ContactId / Contacts.
ServiceRequestIdlongJob the visit belongs to. Required for Standard appointments, omitted for absences.
ServiceRequestServiceRequestThe job. Navigation.
ContactsContact[]Assigned technicians. Navigation – $expand=Contacts. On create you may pass [{ "Id": … }] to assign several technicians.
PipelineTagPipeline tag (project tasks only). Navigation.
ContactIdlongId of the (first) assigned technician's contact (not the user id).
ContactContactAssigned technician. Navigation.
NotestringFree text shown to the technician.
ExternalIdstringYour own identifier.
State values
ValueMeaning
NotVisitedPlanned, technician has not started yet.
InProgressTechnician is on site / working.
IsWorkDoneTechnician finished the visit.
RejectedTechnician rejected the appointment.
AppointmentType values
ValueMeaning
StandardVisit for a service request (requires ServiceRequestId).
TaskProject task (see Project → Tasks).
VacationVacation of a technician (no service request).
IllnessSick leave (no service request).
OtherOther absence with a time range.
OtherWithoutTimeOther all-day absence.
WorktimeCompensationCompensation of overtime.
RepeatingRecurring appointment (created by the portal).
Filters
FilterNotes
StartDateTime ge datetime'…' and EndDateTime le datetime'…'Time window.
ContactId eq 3002LAppointments of a technician (matches all assigned technicians, not only the first).
Type eq 'Vacation' or AppointmentType eq 'Vacation'By kind.
ServiceRequestId eq 1234567890LAppointments of a job.

Endpoints

MethodURLDescription
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=StartDateTimeGet Appointments
GET{{serverURL}}/Appointments?$filter=ContactId eq 3002L and StartDateTime ge datetime'2026-09-01T00:00:00Z'Get Appointments of a Technician
GET{{serverURL}}/Appointments?$filter=Type eq 'Vacation' or Type eq 'Illness'&$expand=ContactGet Absences (Vacation, Illness, …)
GET{{serverURL}}/Appointments/$count?$filter=State eq 'NotVisited'Count Appointments
GET{{serverURL}}/Appointments(5001L)?$expand=Contacts,ServiceRequestRetrieve an Appointment
POST{{serverURL}}/AppointmentsCreate an Appointment
POST{{serverURL}}/AppointmentsCreate a Team Appointment
POST{{serverURL}}/AppointmentsCreate a Vacation
POST{{serverURL}}/AppointmentsCreate an Illness
PUT{{serverURL}}/Appointments(5001L)Update an Appointment (PUT)
PATCH{{serverURL}}/Appointments(5001L)Reassign an Appointment (PATCH)
DELETE{{serverURL}}/Appointments(5001L)Delete an Appointment

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

Loads one appointment.

Headers

HeaderValue
ProperStatusCodestrue

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.

BodyTypeDescription
ServiceRequestIdlongRequired for Standard.
ContactIdlongRequired. Technician's contact id. To assign a team pass Contacts: [{ "Id": 3002 }, { "Id": 3003 }] in addition.
StartDateTime / EndDateTimedatetimeRequired, UTC.
AppointmentTypestringDefault Standard.
Note, ExternalIdstringOptional.

Headers

HeaderValue
Content-Typeapplication/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

HeaderValue
Content-Typeapplication/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

HeaderValue
Content-Typeapplication/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

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: TimeEvents(123L).
VersionintRow version, incremented on every update. Read-only.
StatestringInternal state of the recording (e.g. Closed). Read-only.
IsApprovedboolApproved by the office (time sheet approval).
IsManualboolEntered manually (not tracked automatically on the device).
TimeEventTypestringKind of time – see TimeEventType values. Required.
ExternalIdstringFree identifier for your own system (ERP number, foreign key, …).
DateModifieddatetimeDate of the last modification (UTC). Read-only.
StartDateTimedatetimeStart (UTC). Required.
EndDateTimedatetimeEnd (UTC). Required.
ProposedDrivingDistanceintDriving distance in km proposed by the system (driving events).
ContactIdlongTechnician's contact id. Required.
ContactContactTechnician. Navigation.
ServiceRequestIdlongJob the time was booked on (working/driving events).
ServiceRequestServiceRequestThe job. Navigation.
DescriptionstringFree text.
TimeEventType values
ValueMeaning
eWorkingWorking time on a job.
eDrivingDriving time.
ePauseBreak.
eCustomTimeEventCompany time / custom time type.
eVacationVacation.
eIllnessIllness.
eOtherOther (global) time.
eWorktimeCompensationOvertime compensation.
eNotWorkingIdle.

Endpoints

MethodURLDescription
GET{{serverURL}}/TimeEvents?$filter=StartDateTime ge datetime'2026-09-01T00:00:00Z'&$expand=Contact&$orderby=StartDateTimeGet Time Events
GET{{serverURL}}/TimeEvents?$filter=ServiceRequestId eq 1234567890LGet Time Events of a Service Request
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'Get Time Events of a Technician
GET{{serverURL}}/TimeEvents(13001L)Retrieve a Time Event
POST{{serverURL}}/TimeEventsCreate a Time Event
PUT{{serverURL}}/TimeEvents(13001L)Update a Time Event (PUT)
PATCH{{serverURL}}/TimeEvents(13001L)Approve a Time Event (PATCH)
DELETE{{serverURL}}/TimeEvents(13001L)Delete a Time Event

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)

Loads one recording.

Headers

HeaderValue
ProperStatusCodestrue

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.

BodyTypeDescription
TimeEventTypestringRequired.
ContactIdlongRequired. Technician's contact id.
StartDateTime / EndDateTimedatetimeRequired, UTC.
ServiceRequestIdlongRequired for eWorking / eDriving.
IsManual, IsApproved, Description, ExternalIdOptional.

Headers

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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)

Deletes the recording.

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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Steps(123L).
MobileIdlongId used by the mobile app while offline. Read-only.
VersionintRow version, incremented on every update. Read-only.
NamestringTitle shown to the technician. Required.
IsDoneboolStep completed.
IsVisibleboolStep visible on the mobile app (hidden steps hold data only).
HasErrorboolTechnician marked a defect / the chosen option is flagged as error.
TrackingIdstringYour stable identifier for the step (used to find the same step across jobs and in report definitions).
TypestringStep type – see Type values. Required.
SortOrderintPosition within the checklist / group.
DatastringJSON string with the step definition and the captured value (see Data format).
DateModifiedOfflinedatetimeLast change on the device. Read-only.
ServiceRequestIdlongJob the step belongs to. Required on create (unless the step belongs to a template).
DescriptionstringInstruction text (HTML allowed).
CommentstringComment entered by the technician.
InternalCommentstringInternal comment (office).
ServiceObjectIdlongService object the step refers to (custom-value steps).
ServiceRequestServiceRequestThe job. Navigation.
ServiceObjectServiceObjectService object. Navigation.
StepListTemplateIdlongTemplate the step was created from.
StepListTemplateStepListTemplateTemplate. Navigation.
ParentIdlongId of the parent Group step.
ParentStepParent step. Navigation.
AttachmentsAttachment[]Photos / signatures. Navigation – $expand=Attachments.
Type values
ValueMeaning
ChoiceSingle choice from a list of options (Data.fields[0].enumeration).
EnterValueNumeric value (meter reading, measurement).
EnterTextFree text.
PicturePhoto(s) – stored as attachments.
SignDocumentSignature.
MaterialMaterial / items used.
GroupContainer for child steps (ParentId).
CustomStepCustom form defined by Data.
ActionTriggers 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

MethodURLDescription
GET{{serverURL}}/ServiceRequests(1234567890L)?$expand=Steps/Attachments&$select=Id,Name,StepsGet Steps of a Service Request
GET{{serverURL}}/Steps(7001L)?$expand=Attachments,StepListTemplateRetrieve a Step
GET{{serverURL}}/Steps(7001L)/AttachmentsGet Attachments of a Step
POST{{serverURL}}/StepsCreate a Step in a Service Request
POST{{serverURL}}/StepsCreate a Choice Step
POST{{serverURL}}/StepsCreate a Step inside a Group
POST{{serverURL}}/$batchBatch create Steps
PUT{{serverURL}}/Steps(7001L)Update a Step (PUT)
PATCH{{serverURL}}/Steps(7001L)Complete a Step (PATCH)
DELETE{{serverURL}}/Steps(7001L)Delete a Step

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

Loads one step by id.

Headers

HeaderValue
ProperStatusCodestrue

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.

BodyTypeDescription
ServiceRequestIdlongRequired.
NamestringRequired.
TypestringRequired – see Type values.
TrackingIdstringRecommended: stable id for reporting.
SortOrderintPosition.
ParentIdlongPut the step inside a Group step.
DatastringStep definition JSON (required for Choice).
Description, Comment, IsVisibleOptional.

Headers

HeaderValue
Content-Typeapplication/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

HeaderValue
Content-Typeapplication/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

HeaderValue
Content-Typeapplication/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

HeaderValue
Content-Typemultipart/mixed; boundary=batch_36522ad7-fc75-4b56-8c71-56071383e77b
Acceptmultipart/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Items(123L).
VersionintRow version, incremented on every update. Read-only.
QuantityHoursdecimalQuantity used (pieces, hours, metres – depends on the unit).
DateModifieddatetimeDate of the last modification (UTC). Read-only.
PlannedQuantityHoursdecimalPlanned quantity (from the offer / planning).
ItemTypeIdlongArticle the item is based on (copies name, price, VAT when given).
ItemNumberstringArticle number.
TrackingIdstringYour stable identifier (e.g. offer position).
ManufacturestringManufacturer.
PricedecimalSelling price per unit (net).
CostsdecimalPurchase price per unit.
NameOrNumberstringName shown on the job / invoice. Required if no ItemTypeId.
CustomValuesCustomValue[]Custom field values: [{ "Meta": "<field name>", "Value": "<value>" }].
NotestringFree text / description line.
ExternalIdstringFree identifier for your own system (ERP number, foreign key, …).
DiscountdecimalDiscount in percent.
VATdecimalVAT rate in percent. 0 is treated as not set (falls back to the article/account rate) unless the header X-TreatZeroVatAsValid: true is sent.
IsManualboolEntered manually by the technician (not from the article master).
SortOrderintPosition on the item list.
ItemTypeItemTypeArticle. Navigation.
TypestringKind – see Item Type → Type values.
ServiceRequestIdlongJob. Required.
ParentIdlongParent item for set components.
ServiceRequestServiceRequestThe job. Navigation.
ServiceObjectIdlongService object the material was used on. Set automatically from the job.
ServiceObjectServiceObjectService object. Navigation.
CreatorIdlongContact who booked the item. Defaults to the API user.
CreatorContactCreator. Navigation.
UnitIdlongUnit.
UnitStringstringUnit name. Read-only.
UnitItemUnitUnit. Navigation.

Endpoints

MethodURLDescription
GET{{serverURL}}/ServiceRequests(1234567890L)?$expand=Items/ItemType&$select=Id,Name,ItemsGet Items of a Service Request
GET{{serverURL}}/Items(17001L)?$expand=ItemType,UnitRetrieve an Item
POST{{serverURL}}/ItemsCreate an Item from an Item Type
POST{{serverURL}}/ItemsCreate a manual Item (no Item Type)
PUT{{serverURL}}/Items(17001L)Update an Item (PUT)
PATCH{{serverURL}}/Items(17001L)Update Quantity (PATCH)
DELETE{{serverURL}}/Items(17001L)Delete an Item
POST{{serverURL}}/Items/ApplyPriceListAction: Apply Price List

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

Loads one item by id.

Headers

HeaderValue
ProperStatusCodestrue

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.

BodyTypeDescription
ServiceRequestIdlongRequired.
ItemTypeIdlongArticle to copy from.
QuantityHoursdecimalQuantity used. Default 0.
PlannedQuantityHoursdecimalPlanned quantity.
NameOrNumber, Price, Costs, VAT, Discount, UnitId, Note, ExternalId, TrackingId, SortOrderOverride 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

HeaderValue
Content-Typeapplication/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

HeaderValue
X-TreatZeroVatAsValidtrue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Content-Typeapplication/json

Request body

{
  "itemIds": [
    17001,
    17002
  ]
}

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Edm.Int32",
  "value": 2
}

Comment 5 endpoints

Comments are the message thread of a service request (office ↔ technician ↔ customer). Querying the set requires a ServiceRequestId eq … filter; $select is not available.

Attributes
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Comments(123L).
VersionintRow version, incremented on every update. Read-only.
DateOfCreationdatetimeSet by the server on create. Read-only.
IsInternalboolInternal note – not visible on the customer portal.
IsCustomerboolWritten by the customer (customer portal). Read-only in practice.
OwnerContactAuthor (contact). Navigation.
OwnerIdlongAuthor's contact id. Defaults to the API user; may be set explicitly on create.
ServiceRequestServiceRequestThe job. Navigation.
ServiceRequestIdlongJob the comment belongs to. Required, cannot be changed.
CompanyCompanyCustomer company of the job. Navigation, read-only.
CompanyIdlongCustomer company id. Read-only.
ContentstringText of the comment. Required.
PublicUriImagestringAvatar URL of the author. Read-only.

Endpoints

MethodURLDescription
GET{{serverURL}}/Comments?$filter=ServiceRequestId eq 1234567890L&$expand=Owner&$orderby=DateOfCreationGet Comments (ServiceRequestId filter)
GET{{serverURL}}/Comments(8001L)Retrieve a Comment
POST{{serverURL}}/CommentsCreate a Comment
PATCH{{serverURL}}/Comments(8001L)Update a Comment
DELETE{{serverURL}}/Comments(8001L)Delete a Comment

GET Get Comments (ServiceRequestId filter)

GET {{serverURL}}/Comments?$filter=ServiceRequestId eq 1234567890L&$expand=Owner&$orderby=DateOfCreation

The ServiceRequestId filter is mandatory. Alternative: ServiceRequests(id)/Comments.

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Comments",
  "value": [
    {
      "Id": "8001",
      "Version": 1,
      "DateOfCreation": "2026-08-25T08:00:00Z",
      "IsInternal": false,
      "IsCustomer": false,
      "OwnerId": "3001",
      "ServiceRequestId": "1234567890",
      "CompanyId": "2001",
      "Content": "Customer will be on site from 8:00",
      "Owner": {
        "Id": "3001",
        "FirstName": "Anna",
        "LastName": "Office"
      }
    }
  ]
}
400 400 Bad Request
{
  "odata.error": {
    "code": "",
    "message": {
      "lang": "en-US",
      "value": "Querying comments requires a 'ServiceRequestId eq {id}' filter."
    }
  }
}

GET Retrieve a Comment

GET {{serverURL}}/Comments(8001L)

Loads one comment.

Headers

HeaderValue
ProperStatusCodestrue

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Comments/@Element",
  "Id": "8001",
  "Version": 1,
  "DateOfCreation": "2026-08-25T08:00:00Z",
  "IsInternal": false,
  "IsCustomer": false,
  "OwnerId": "3001",
  "ServiceRequestId": "1234567890",
  "CompanyId": "2001",
  "Content": "Customer will be on site from 8:00"
}

POST Create a Comment

POST {{serverURL}}/Comments

Adds a comment to a job. DateOfCreation is set by the server; OwnerId defaults to the API user's contact but can be overridden to post on behalf of another user. Technicians get a push notification.

Headers

HeaderValue
Content-Typeapplication/json

Request body

{
  "ServiceRequestId": 1234567890,
  "Content": "Customer will be on site from 8:00",
  "IsInternal": false
}

Responses

201 201 Created
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Comments/@Element",
  "Id": "8001",
  "Version": 1,
  "DateOfCreation": "2026-08-25T08:00:00Z",
  "IsInternal": false,
  "IsCustomer": false,
  "OwnerId": "3001",
  "ServiceRequestId": "1234567890",
  "CompanyId": "2001",
  "Content": "Customer will be on site from 8:00"
}

PATCH Update a Comment

PATCH {{serverURL}}/Comments(8001L)

Edits the text. Only Content / IsInternal can change; ServiceRequestId is fixed. (PUT is not supported on comments – it returns 405.)

Headers

HeaderValue
Preferreturn-content
Content-Typeapplication/json

Request body

{
  "Content": "Customer will be on site from 8:30"
}

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Comments/@Element",
  "Id": "8001",
  "Version": 2,
  "DateOfCreation": "2026-08-25T08:00:00Z",
  "IsInternal": false,
  "IsCustomer": false,
  "OwnerId": "3001",
  "ServiceRequestId": "1234567890",
  "CompanyId": "2001",
  "Content": "Customer will be on site from 8:30"
}

DELETE Delete a Comment

DELETE {{serverURL}}/Comments(8001L)

Deletes the comment.

Responses

204 204 No Content

No body.

Attachment 7 endpoints

Attachments are files captured on checklist steps – mainly photos and signatures taken by the technician on the mobile app.

Querying the set requires a StepId eq … filter (or use the navigation Steps(id)/Attachments). $select is not available. Binary upload goes through POST {{baseURL}}/mfr/Step/{stepId}/Attachment.

Attributes
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Attachments(123L).
VersionintRow version, incremented on every update. Read-only.
URIstringDownload URL of the file. Read-only for uploads.
FileNamestringFile name.
ContentTypestringMIME type.
SharedAccessPathstringTime-limited public download URL (for reports). Read-only.
StepIdlongStep the attachment belongs to. Required.
StepStepThe step. Navigation.
UploadDatedatetimeUpload timestamp. Read-only.

Endpoints

MethodURLDescription
GET{{serverURL}}/Attachments?$filter=StepId eq 7001LGet Attachments (StepId filter)
GET{{serverURL}}/Steps(7001L)/AttachmentsGet Attachments of a Step (navigation)
GET{{serverURL}}/Attachments(14001L)Retrieve an Attachment
POST{{baseURL}}/mfr/Step/7001/AttachmentUpload an Attachment to a Step (REST)
POST{{serverURL}}/AttachmentsCreate an Attachment from a URL
PUT{{serverURL}}/Attachments(14001L)Update an Attachment
DELETE{{serverURL}}/Attachments(14001L)Delete an Attachment

GET Get Attachments (StepId filter)

GET {{serverURL}}/Attachments?$filter=StepId eq 7001L

The StepId filter is mandatory – without it the request fails with 400.

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Attachments",
  "value": [
    {
      "Id": "14001",
      "Version": 1,
      "URI": "https://portal.mobilefieldreport.com/mfr/Attachment/14001/Content",
      "FileName": "IMG_0042.jpg",
      "ContentType": "image/jpeg",
      "StepId": "7001",
      "UploadDate": "2026-08-25T08:00:00Z"
    }
  ]
}
400 400 Bad Request
{
  "odata.error": {
    "code": "",
    "message": {
      "lang": "en-US",
      "value": "Querying attachments requires a 'StepId eq {id}' filter."
    }
  }
}

GET Get Attachments of a Step (navigation)

GET {{serverURL}}/Steps(7001L)/Attachments

Same result via the step's navigation property. For a whole job use ServiceRequests(id)?$expand=Steps/Attachments.

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Attachments",
  "value": [
    {
      "Id": "14001",
      "Version": 1,
      "URI": "https://portal.mobilefieldreport.com/mfr/Attachment/14001/Content",
      "FileName": "IMG_0042.jpg",
      "ContentType": "image/jpeg",
      "StepId": "7001",
      "UploadDate": "2026-08-25T08:00:00Z"
    }
  ]
}

GET Retrieve an Attachment

GET {{serverURL}}/Attachments(14001L)

Metadata of one attachment; download the file from URI.

Headers

HeaderValue
ProperStatusCodestrue

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Attachments/@Element",
  "Id": "14001",
  "Version": 1,
  "URI": "https://portal.mobilefieldreport.com/mfr/Attachment/14001/Content",
  "FileName": "IMG_0042.jpg",
  "ContentType": "image/jpeg",
  "StepId": "7001",
  "UploadDate": "2026-08-25T08:00:00Z"
}

POST Upload an Attachment to a Step (REST)

POST {{baseURL}}/mfr/Step/7001/Attachment

Uploads a file (photo, PDF, signature image) as an attachment of the step. Send multipart/form-data with one file part; the part's file name and content type are stored with the attachment. Returns the created attachment as JSON. Photos uploaded this way appear on Picture steps in the report.

Request body (multipart/form-data)

FieldTypeValue
filefile(file)

Responses

200 200 OK
{
  "Id": "14002",
  "Version": 1,
  "URI": "https://portal.mobilefieldreport.com/mfr/Attachment/14001/Content",
  "FileName": "IMG_0042.jpg",
  "ContentType": "image/jpeg",
  "StepId": "7001",
  "UploadDate": "2026-08-25T08:00:00Z"
}

POST Create an Attachment from a URL

POST {{serverURL}}/Attachments

Creates the attachment record for a file that is hosted elsewhere (metadata only, no upload).

Headers

HeaderValue
Content-Typeapplication/json

Request body

{
  "StepId": 7001,
  "URI": "https://files.example.com/photo.jpg",
  "FileName": "photo.jpg",
  "ContentType": "image/jpeg"
}

Responses

201 201 Created
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Attachments/@Element",
  "Id": "14003",
  "Version": 1,
  "URI": "https://files.example.com/photo.jpg",
  "FileName": "photo.jpg",
  "ContentType": "image/jpeg",
  "StepId": "7001",
  "UploadDate": "2026-08-25T08:00:00Z"
}

PUT Update an Attachment

PUT {{serverURL}}/Attachments(14001L)

Updates the metadata (e.g. rename).

Headers

HeaderValue
Preferreturn-content
Content-Typeapplication/json

Request body

{
  "Id": 14001,
  "StepId": 7001,
  "FileName": "bearing-before.jpg",
  "ContentType": "image/jpeg",
  "URI": "https://portal.mobilefieldreport.com/mfr/Attachment/14001/Content"
}

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Attachments/@Element",
  "Id": "14001",
  "Version": 2,
  "URI": "https://portal.mobilefieldreport.com/mfr/Attachment/14001/Content",
  "FileName": "bearing-before.jpg",
  "ContentType": "image/jpeg",
  "StepId": "7001",
  "UploadDate": "2026-08-25T08:00:00Z"
}

DELETE Delete an Attachment

DELETE {{serverURL}}/Attachments(14001L)

Deletes the attachment and its file.

Responses

204 204 No Content

No body.

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:

  1. Upload the file with POST {{baseURL}}/mfr/Document/UploadAndCreate (multipart, field Filedata) → returns the document with its Id.
  2. Attach it: POST ServiceRequests(id)/$links/Documents, PUT {{baseURL}}/mfr/ServiceRequest/{id}/Document/{documentId} or PUT {{baseURL}}/mfr/ServiceObject/{id}/Document/{documentId}.
  3. Download it later through the URI property (authenticated).
Attributes
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Documents(123L).
CustomValuesCustomValue[]Custom field values: [{ "Meta": "<field name>", "Value": "<value>" }].
VersionintRow version, incremented on every update. Read-only.
StatestringInternal state. Read-only.
ExternalIdstringFree identifier for your own system (ERP number, foreign key, …).
URIstringDownload URL of the file (or the target URL if IsLink). Read-only for uploads.
IsGlobalboolGlobal document (available on every job, e.g. safety instructions).
StartDateTimedatetimeValidity start (global documents).
EndDateTimedatetimeValidity end (global documents).
FileNamestringFile name shown to the user.
DateModifieddatetimeDate of the last modification (UTC). Read-only.
UploadDatedatetimeUpload timestamp. Read-only.
IsLinkbooltrue if the document is a link to an external URL instead of an uploaded file.
ContentTypestringMIME type.
HTMLCodestringEmbedded HTML (link documents).
ServiceRequestIdlongJob the document is attached to (documents may also be linked to several jobs via $links).
ServiceRequestServiceRequestThe job. Navigation.
NotestringDescription.

Endpoints

MethodURLDescription
GET{{serverURL}}/Documents?$filter=DateModified gt datetime'2026-08-01T00:00:00Z'&$orderby=DateModified descGet Documents
GET{{serverURL}}/Documents?$filter=IsGlobal eq trueGet Global Documents
GET{{serverURL}}/Documents(10001L)Retrieve a Document
POST{{baseURL}}/mfr/Document/UploadAndCreateUpload a Document (REST)
POST{{serverURL}}/DocumentsCreate a Link Document
PUT{{serverURL}}/Documents(10001L)Update a Document (PUT)
DELETE{{serverURL}}/Documents(10001L)Delete a Document
PUT{{baseURL}}/mfr/ServiceRequest/1234567890/Document/10001Attach a Document to a Service Request (REST)
DELETE{{baseURL}}/mfr/ServiceRequest/1234567890/Document/10001Detach a Document from a Service Request (REST)
PUT{{baseURL}}/mfr/ServiceObject/4001/Document/10001Attach a Document to a Service Object (REST)
DELETE{{baseURL}}/mfr/ServiceObject/4001/Document/10001Detach a Document from a Service Object (REST)

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

HeaderValue
ProperStatusCodestrue

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)

FieldTypeValue
Filedatafile(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
}

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

HeaderValue
Preferreturn-content
Content-Typeapplication/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.

Report 7 endpoints

Reports are generated documents – service reports, offers, invoices, exports – produced from a job with a Report Definition. Every generated file is stored as a report and can be downloaded via URI.

Generation from the API is a two-step process:

  1. POST ServiceRequests(id)/GenerateReportHash with the reportDefinitionId → returns a one-time hash.
  2. GET {{baseURL}}/System/CustomerReport/{hash} → downloads the PDF (no authentication needed for the hash URL, it expires).

Reports cannot be created with POST Reports.

Attributes
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Reports(123L).
VersionintRow version, incremented on every update. Read-only.
DateOfCreationdatetimeDate of creation (UTC). Read-only.
ServiceRequestServiceRequestJob the report belongs to. Navigation.
URIstringDownload URL of the generated file (authenticated). Read-only.
DocumentNamestringFile name.
FileTypeStringstringFile type – see FileType values. Read-only.
ReportDefinitionCodestringCode of the report definition used. Read-only.
ServiceObjectIdlongService object the report was generated for.
ReportDefinitionIdlongReport definition used.
CanBeDeletedboolfalse for invoices and other legally relevant documents.
InvoiceBalancedecimalGross total (invoices).
InvoiceBalanceNettodecimalNet total (invoices).
WageBalanceNetdecimalNet labour share (invoices).
WithoutVATboolInvoice without VAT (reverse charge).
InvoiceIdstringInvoice number (invoices).
DueDatedatetimePayment due date (invoices).
IsPayedboolPaid (invoices).
IsInvoiceboolThe report is an invoice – use the Invoice set for the full invoice record.
IsCanceledboolCancelled invoice.
ServiceObjectServiceObjectService object. Navigation.
CustomValuesCustomValue[]Custom field values: [{ "Meta": "<field name>", "Value": "<value>" }].
FileType values
ValueMeaning
PdfPDF service report.
PdfSummaryPDF summary over several jobs.
PdfOfferOffer PDF.
PdfInvoiceInvoice PDF.
PdfPartialInvoicePartial invoice PDF.
PdfCancelInvoiceCancellation invoice PDF.
PdfDunningDunning letter PDF.
HtmlHTML report.
HtmlToXlsxExcel export rendered from HTML.
HtmlToCsvCSV export rendered from HTML.
XLSExcel export.
XMLXML export.
ProductSummaryProduct summary.

Endpoints

MethodURLDescription
GET{{serverURL}}/Reports?$filter=DateOfCreation gt datetime'2026-08-01T00:00:00Z'&$expand=ServiceRequest&$orderby=DateOfCreation descGet Reports
GET{{serverURL}}/ServiceRequests(1234567890L)?$expand=Reports&$select=Id,ReportsGet Reports of a Service Request
GET{{serverURL}}/Reports(22001L)Retrieve a Report
POST{{serverURL}}/ServiceRequests(1234567890L)/GenerateReportHashAction: Generate Report Hash
GET{{baseURL}}/System/CustomerReport/MTYxNjQxNzkxNDg4XzM5MzI1Nzg3MTM0MzlfMTc2NzUyNTEzODQzMg2Download a generated Report (REST)
PUT{{serverURL}}/Reports(22001L)Update a Report
DELETE{{serverURL}}/Reports(22001L)Delete a Report

GET Get Reports

GET {{serverURL}}/Reports?$filter=DateOfCreation gt datetime'2026-08-01T00:00:00Z'&$expand=ServiceRequest&$orderby=DateOfCreation desc

Generated documents (paged). Reports of one job: ServiceRequests(id)?$expand=Reports.

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Reports",
  "value": [
    {
      "Id": "22001",
      "Version": 1,
      "DateOfCreation": "2026-08-25T08:00:00Z",
      "URI": "https://portal.mobilefieldreport.com/mfr/Report/22001/Content",
      "DocumentName": "Service report 1234567890.pdf",
      "FileTypeString": "Pdf",
      "ReportDefinitionCode": "SERVICE_REPORT",
      "ServiceObjectId": "4001",
      "ReportDefinitionId": "23001",
      "CanBeDeleted": true,
      "InvoiceBalance": "0",
      "InvoiceBalanceNetto": "0",
      "WageBalanceNet": "0",
      "WithoutVAT": false,
      "IsPayed": false,
      "IsInvoice": false,
      "IsCanceled": false,
      "CustomValues": [],
      "ServiceRequest": {
        "Id": "1234567890",
        "Name": "Repair heating pump",
        "State": "Closed"
      }
    }
  ]
}

GET Get Reports of a Service Request

GET {{serverURL}}/ServiceRequests(1234567890L)?$expand=Reports&$select=Id,Reports

All documents generated for a job (service reports and invoices).

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests/@Element",
  "Id": "1234567890",
  "Reports": [
    {
      "Id": "22001",
      "Version": 1,
      "DateOfCreation": "2026-08-25T08:00:00Z",
      "URI": "https://portal.mobilefieldreport.com/mfr/Report/22001/Content",
      "DocumentName": "Service report 1234567890.pdf",
      "FileTypeString": "Pdf",
      "ReportDefinitionCode": "SERVICE_REPORT",
      "ServiceObjectId": "4001",
      "ReportDefinitionId": "23001",
      "CanBeDeleted": true,
      "InvoiceBalance": "0",
      "InvoiceBalanceNetto": "0",
      "WageBalanceNet": "0",
      "WithoutVAT": false,
      "IsPayed": false,
      "IsInvoice": false,
      "IsCanceled": false,
      "CustomValues": []
    }
  ]
}

GET Retrieve a Report

GET {{serverURL}}/Reports(22001L)

Metadata of one report; download the file from URI with your credentials.

Headers

HeaderValue
ProperStatusCodestrue

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Reports/@Element",
  "Id": "22001",
  "Version": 1,
  "DateOfCreation": "2026-08-25T08:00:00Z",
  "URI": "https://portal.mobilefieldreport.com/mfr/Report/22001/Content",
  "DocumentName": "Service report 1234567890.pdf",
  "FileTypeString": "Pdf",
  "ReportDefinitionCode": "SERVICE_REPORT",
  "ServiceObjectId": "4001",
  "ReportDefinitionId": "23001",
  "CanBeDeleted": true,
  "InvoiceBalance": "0",
  "InvoiceBalanceNetto": "0",
  "WageBalanceNet": "0",
  "WithoutVAT": false,
  "IsPayed": false,
  "IsInvoice": false,
  "IsCanceled": false,
  "CustomValues": []
}
404 404 Not Found
{
  "odata.error": {
    "code": "",
    "message": {
      "lang": "en-US",
      "value": "The entity Report with Key: 22001 can not be found"
    }
  }
}

POST Action: Generate Report Hash

POST {{serverURL}}/ServiceRequests(1234567890L)/GenerateReportHash

Renders the report definition for the job and returns a download hash (value). Get definition ids from Report Definition → Get Report Definitions. Rate limit: 4 report generations in parallel per user.

Headers

HeaderValue
Content-Typeapplication/json

Request body

{
  "reportDefinitionId": 23001
}

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Edm.String",
  "value": "MTYxNjQxNzkxNDg4XzM5MzI1Nzg3MTM0MzlfMTc2NzUyNTEzODQzMg2"
}

GET Download a generated Report (REST)

GET {{baseURL}}/System/CustomerReport/MTYxNjQxNzkxNDg4XzM5MzI1Nzg3MTM0MzlfMTc2NzUyNTEzODQzMg2

Append the hash from Generate Report Hash to the URL. Returns the PDF (application/pdf). The link is temporary.

Responses

200 200 OK
%PDF-1.7 … (binary)

PUT Update a Report

PUT {{serverURL}}/Reports(22001L)

Updates metadata (name, custom values). The generated file is immutable.

Headers

HeaderValue
Preferreturn-content
Content-Typeapplication/json

Request body

{
  "Id": 22001,
  "DocumentName": "Service report 1234567890 – final.pdf",
  "CustomValues": [
    {
      "Meta": "SentToCustomer",
      "Value": "true"
    }
  ]
}

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Reports/@Element",
  "Id": "22001",
  "Version": 2,
  "DateOfCreation": "2026-08-25T08:00:00Z",
  "URI": "https://portal.mobilefieldreport.com/mfr/Report/22001/Content",
  "DocumentName": "Service report 1234567890 – final.pdf",
  "FileTypeString": "Pdf",
  "ReportDefinitionCode": "SERVICE_REPORT",
  "ServiceObjectId": "4001",
  "ReportDefinitionId": "23001",
  "CanBeDeleted": true,
  "InvoiceBalance": "0",
  "InvoiceBalanceNetto": "0",
  "WageBalanceNet": "0",
  "WithoutVAT": false,
  "IsPayed": false,
  "IsInvoice": false,
  "IsCanceled": false,
  "CustomValues": [
    {
      "Meta": "SentToCustomer",
      "Value": "true"
    }
  ]
}

DELETE Delete a Report

DELETE {{serverURL}}/Reports(22001L)

Deletes the report if CanBeDeleted is true (never for invoices).

Responses

204 204 No Content

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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Companys(123L).
VersionintRow version, incremented on every update. Read-only.
IsPhysicalPersonboolPrivate customer (person) instead of a company.
IsOwnerboolThe own company (account owner). Read-only.
IsEmailInvoicingActiveboolInvoices are sent by e-mail.
IsSupplierboolSupplier (used for orders and purchase invoices).
MappingIdstringAdditional mapping key for integrations.
ExternalIdstringFree identifier for your own system (ERP number, foreign key, …).
NamestringCompany name. Required.
NotestringFree text.
BillingAddressstringBilling address as text (when it differs from Location).
SupportTelephonestringCentral phone number.
SupportFaxstringFax.
SupportMailstringCentral e-mail address.
QuickSearchstringWrite-only filter helper: $filter=QuickSearch eq 'text' searches name, external id, address and contacts.
DateOfCreationdatetimeDate of creation (UTC). Read-only.
DateModifieddatetimeDate of the last modification (UTC). Read-only.
CustomValuesCustomValue[]Custom field values: [{ "Meta": "<field name>", "Value": "<value>" }].
LocationLocationAddress – see Location attributes. Pass CreateGeoLocation inside Location to geocode it.
ContactIdslong[]Ids of the contacts. Read-only.
MainContactIdlongMain contact person.
MainContactContactMain contact. Navigation.
TagIdslong[]Ids of the tags. Read-only.
TagsTag[]Tags of type Company. Navigation (managed in the portal).
ContactsContact[]Contact persons. Navigation – $expand=Contacts.
ServiceObjectIdslong[]Ids of the service objects. Read-only.
ServiceObjectsServiceObject[]Service objects (assets) of the customer. Navigation.
Location attributes
AttributeTypeDescription
AddressStringstringStreet and house number.
PostalstringPostal code.
CitystringCity.
StatestringState / region.
CountrystringCountry (ISO code or name).
LongitudedoubleLongitude (set by geocoding or by you).
LatitudedoubleLatitude.
IsValidLocationboolGeocoding succeeded. Read-only.
IsMoveableboolLocation can be changed by the technician (mobile objects).
Filters
FilterNotes
$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 trueSuppliers.
$filter=DateModified gt datetime'…'Delta sync.

Endpoints

MethodURLDescription
GET{{serverURL}}/Companies?$expand=Location,MainContact&$orderby=Name&$top=50Get Companies
GET{{serverURL}}/Companies?$filter=QuickSearch eq 'acme'&$expand=LocationQuick Search Companies
GET{{serverURL}}/Companies?$filter=ExternalId eq 'C-100'Find a Company by External Id
GET{{serverURL}}/Companies(2001L)?$expand=Location,Contacts,ServiceObjects/Location,TagsRetrieve a Company
POST{{serverURL}}/CompaniesCreate a Company
POST{{serverURL}}/Companies(2001L)/ContactsCreate a Contact for a Company
POST{{serverURL}}/Companies(2001L)/ServiceObjectsCreate a Service Object for a Company
PUT{{serverURL}}/Companies(2001L)Update a Company (PUT)
PATCH{{serverURL}}/Companies(2001L)Update a Company partially (PATCH)
DELETE{{serverURL}}/Companies(2001L)Delete a Company
POST{{serverURL}}/Companies(2001L)/$links/ContactsLink an existing Contact to a Company
DELETE{{serverURL}}/Companies(2001L)/$links/Contacts(3100L)Unlink a Contact from a Company

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

HeaderValue
ProperStatusCodestrue

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.

BodyTypeDescription
NamestringRequired.
ExternalIdstringRecommended – your customer number. If a company with the same ExternalId already exists it is returned instead of creating a duplicate.
LocationobjectAddress. CreateGeoLocation: true geocodes it.
IsPhysicalPerson, IsSupplier, SupportTelephone, SupportMail, Note, BillingAddress, CustomValuesOptional.

Add contacts with POST Companies(id)/Contacts and assets with POST Companies(id)/ServiceObjects.

Headers

HeaderValue
Content-Typeapplication/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

HeaderValue
Content-Typeapplication/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

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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.

Contact 7 endpoints

A Contact is a person: either a contact person of a customer company or the person record behind an MFR user (technician / office user). Appointments and time events reference technicians by their contact id.

Attributes
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Contacts(123L).
CustomValuesCustomValue[]Custom field values: [{ "Meta": "<field name>", "Value": "<value>" }].
FirstNamestringFirst name.
LastNamestringLast name. Required.
EmailstringE-mail address.
JobTitlestringPosition / role.
MobilePhonestringMobile number.
TelephonestringLandline number.
FaxstringFax number.
NotestringFree text.
DateModifieddatetimeDate of the last modification (UTC). Read-only.
VersionintRow version, incremented on every update. Read-only.
CompanyIdlongCompany the contact belongs to. Required on create.
IsUserbooltrue if the contact is an MFR user (technician / office user). Read-only.
ExternalIdstringFree identifier for your own system (ERP number, foreign key, …).
GenderstringMale, Female or Unknown.
CostsPerHourdecimalInternal hourly cost rate (users only).
CompanyCompanyThe company. Navigation.
UserIdlongId of the linked user (if IsUser). Read-only.
UserUserLinked user. Navigation.
GroupIdlongId of the technician group (users only).
GroupGroupTechnician group. Navigation.

Endpoints

MethodURLDescription
GET{{serverURL}}/Contacts?$filter=CompanyId eq 2001L&$orderby=LastNameGet Contacts
GET{{serverURL}}/Contacts?$filter=IsUser eq true&$expand=User,GroupGet Technician Contacts (users)
GET{{serverURL}}/Contacts(3100L)?$expand=CompanyRetrieve a Contact
POST{{serverURL}}/ContactsCreate a Contact
PUT{{serverURL}}/Contacts(3100L)Update a Contact (PUT)
PATCH{{serverURL}}/Contacts(3100L)Update a Contact partially (PATCH)
DELETE{{serverURL}}/Contacts(3100L)Delete a Contact

GET Get Contacts

GET {{serverURL}}/Contacts?$filter=CompanyId eq 2001L&$orderby=LastName

Contacts of a company. Without the filter all contacts of the account are returned (paged). Use IsUser eq true for technicians / users.

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Contacts",
  "value": [
    {
      "Id": "3100",
      "CustomValues": [],
      "FirstName": "Erika",
      "LastName": "Musterfrau",
      "Email": "erika@example.com",
      "JobTitle": "Facility manager",
      "MobilePhone": "+49 170 1234",
      "Telephone": "+49 30 1234",
      "DateModified": "2026-08-25T08:00:00Z",
      "Version": 1,
      "CompanyId": "2001",
      "IsUser": false,
      "Gender": "Female",
      "CostsPerHour": "0"
    }
  ]
}

GET Get Technician Contacts (users)

GET {{serverURL}}/Contacts?$filter=IsUser eq true&$expand=User,Group

All contacts that belong to an MFR user, with the user and technician group. Use these ids as ContactId on appointments and time events.

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Contacts",
  "value": [
    {
      "Id": "3002",
      "CustomValues": [],
      "FirstName": "Max",
      "LastName": "Mustermann",
      "Email": "max@example.com",
      "DateModified": "2026-08-25T08:00:00Z",
      "Version": 1,
      "CompanyId": "2000",
      "IsUser": true,
      "CostsPerHour": "45.00",
      "UserId": "1002",
      "User": {
        "Id": "1002",
        "UserName": "max@example.com",
        "IsActive": true,
        "IsMobile": true
      },
      "GroupId": "1500",
      "Group": {
        "Id": "1500",
        "Name": "North team"
      }
    }
  ]
}

GET Retrieve a Contact

GET {{serverURL}}/Contacts(3100L)?$expand=Company

Loads one contact.

Headers

HeaderValue
ProperStatusCodestrue

Responses

200 200 OK
{
  "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",
  "Telephone": "+49 30 1234",
  "DateModified": "2026-08-25T08:00:00Z",
  "Version": 1,
  "CompanyId": "2001",
  "IsUser": false,
  "Gender": "Female",
  "CostsPerHour": "0",
  "Company": {
    "Id": "2001",
    "Name": "ACME GmbH"
  }
}

POST Create a Contact

POST {{serverURL}}/Contacts

Creates a contact person for a company (CompanyId required). Alternative: POST Companies(2001L)/Contacts with the same body minus CompanyId.

Headers

HeaderValue
Content-Typeapplication/json

Request body

{
  "FirstName": "Erika",
  "LastName": "Musterfrau",
  "Email": "erika@example.com",
  "JobTitle": "Facility manager",
  "MobilePhone": "+49 170 1234",
  "Telephone": "+49 30 1234",
  "Gender": "Female",
  "CompanyId": 2001,
  "ExternalId": "CRM-77"
}

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",
  "Telephone": "+49 30 1234",
  "DateModified": "2026-08-25T08:00:00Z",
  "Version": 1,
  "CompanyId": "2001",
  "IsUser": false,
  "Gender": "Female",
  "CostsPerHour": "0",
  "ExternalId": "CRM-77"
}

PUT Update a Contact (PUT)

PUT {{serverURL}}/Contacts(3100L)

Replaces the contact. GET first and send everything back.

Headers

HeaderValue
Preferreturn-content
Content-Typeapplication/json

Request body

{
  "Id": 3100,
  "FirstName": "Erika",
  "LastName": "Musterfrau",
  "Email": "erika.musterfrau@example.com",
  "JobTitle": "Head of facilities",
  "MobilePhone": "+49 170 1234",
  "Telephone": "+49 30 1234",
  "Gender": "Female",
  "CompanyId": 2001
}

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Contacts/@Element",
  "Id": "3100",
  "CustomValues": [],
  "FirstName": "Erika",
  "LastName": "Musterfrau",
  "Email": "erika.musterfrau@example.com",
  "JobTitle": "Head of facilities",
  "MobilePhone": "+49 170 1234",
  "Telephone": "+49 30 1234",
  "DateModified": "2026-08-25T08:00:00Z",
  "Version": 2,
  "CompanyId": "2001",
  "IsUser": false,
  "Gender": "Female",
  "CostsPerHour": "0"
}

PATCH Update a Contact partially (PATCH)

PATCH {{serverURL}}/Contacts(3100L)

Changes only the given properties.

Headers

HeaderValue
Preferreturn-content
Content-Typeapplication/json

Request body

{
  "MobilePhone": "+49 170 9999"
}

Responses

200 200 OK
{
  "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 9999",
  "Telephone": "+49 30 1234",
  "DateModified": "2026-08-25T08:00:00Z",
  "Version": 2,
  "CompanyId": "2001",
  "IsUser": false,
  "Gender": "Female",
  "CostsPerHour": "0"
}

DELETE Delete a Contact

DELETE {{serverURL}}/Contacts(3100L)

Deletes the contact. For contacts of MFR users prefer deactivating the user (Users → PATCH IsActive: false).

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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: ServiceObjects(123L).
NamestringName of the asset. Required.
NotestringFree text (location hints, access, …).
CustomValuesCustomValue[]Custom field values: [{ "Meta": "<field name>", "Value": "<value>" }].
DateOfCreationdatetimeDate of creation (UTC). Read-only.
DateModifieddatetimeDate of the last modification (UTC). Read-only.
ExternalIdstringFree identifier for your own system (ERP number, foreign key, …).
MappingIdstringAdditional mapping key for integrations.
QuickSearchstringWrite-only filter helper: $filter=QuickSearch eq 'text' searches name, external id, address and customer.
LocationLocationAddress / coordinates. See Company → Location attributes.
VersionintRow version, incremented on every update. Read-only.
CreateGeoLocationboolWrite-only: geocode Location on create/update (set automatically on create).
IsWarehouseboolThe object is a warehouse (see Warehouse). Read-only here.
WarehouseManagerContactWarehouse manager contact (warehouses only). Navigation.
ParentServiceObjectIdlongParent object for hierarchies (building → floor → device).
ParentServiceObjectServiceObjectParent object. Navigation.
CustomValueStepsStep[]Steps of a durable checklist that store custom values of the object. Navigation.
CompanyIdlongOwning customer. Required on create.
CompanyCompanyCustomer. Navigation.
IsProductboolThe object is an instance of a Product.
ProductIdlongProduct the object is an instance of.
ProductProductProduct. Navigation.
ContactIdslong[]Ids of the linked contacts. Read-only.
TagIdslong[]Ids of the tags. Read-only – use $links/Tags.
TagsTag[]Tags of type ServiceObject. Navigation.
ChildServiceObjectServiceObject[]Child objects. Navigation – or GET ServiceObjects(id)/ChildServiceObject.
ContactsContact[]Contact persons responsible for the object. Navigation.
ItemsItem[]Items (spare parts) attached to the object. Navigation.
Filters
FilterNotes
$filter=QuickSearch eq 'pump'Full-text quick search. Use it alone.
$filter=CompanyId eq 2001LObjects of a customer.
$filter=ExternalId eq 'HP-3'Lookup by your id (serial number).
$filter=ParentServiceObjectId eq 4000LNot supported – use ServiceObjects(4000L)/ChildServiceObject.

Endpoints

MethodURLDescription
GET{{serverURL}}/ServiceObjects?$expand=Location,Company&$orderby=Name&$top=50Get Service Objects
GET{{serverURL}}/ServiceObjects?$filter=QuickSearch eq 'pump'&$expand=LocationQuick Search Service Objects
GET{{serverURL}}/ServiceObjects?$filter=CompanyId eq 2001L&$expand=LocationGet Service Objects of a Company
GET{{serverURL}}/ServiceObjects(4001L)?$expand=Location,Company,Contacts,Tags,ProductRetrieve a Service Object
GET{{serverURL}}/ServiceObjects(4000L)/ChildServiceObject?$expand=LocationGet Child Service Objects
POST{{serverURL}}/ServiceObjectsCreate a Service Object
POST{{serverURL}}/ServiceObjectsCreate a Child Service Object
PUT{{serverURL}}/ServiceObjects(4001L)Update a Service Object (PUT)
PATCH{{serverURL}}/ServiceObjects(4001L)Update a Service Object partially (PATCH)
DELETE{{serverURL}}/ServiceObjects(4001L)Delete a Service Object
POST{{serverURL}}/ServiceObjects(4001L)/$links/ContactsLink a Contact to a Service Object
DELETE{{serverURL}}/ServiceObjects(4001L)/$links/Contacts(3100L)Unlink a Contact from a Service Object
POST{{serverURL}}/ServiceObjects(4001L)/$links/TagsLink a Tag to a Service Object
DELETE{{serverURL}}/ServiceObjects(4001L)/$links/Tags(6101L)Unlink a Tag from a Service Object

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

HeaderValue
ProperStatusCodestrue

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.

BodyTypeDescription
NamestringRequired.
CompanyIdlongRequired. Owning customer.
ExternalIdstringRecommended – serial number / your id.
LocationobjectAddress; omit to reuse the customer's address in the portal.
ParentServiceObjectIdlongAttach as child of another object.
ProductIdlongMake it an instance of a product (custom-value checklist is applied).
Note, MappingId, CustomValuesOptional.

Headers

HeaderValue
Content-Typeapplication/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

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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.

Product 5 endpoints

A Product is a type of service object (e.g. "Boiler X200"). Service objects with IsProduct = true / ProductId are instances of a product; a product can carry a durable step list template that defines the custom values (technical data) of every instance.

Attributes
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Products(123L).
VersionintRow version, incremented on every update. Read-only.
NamestringProduct name. Required.
SubKeystringVariant / model key.
DescriptionstringDescription.
DateModifieddatetimeDate of the last modification (UTC). Read-only.
MappingIdstringYour identifier.
CustomValueStepTemplateIdlongDurable step list template whose steps become the custom values of each instance.
CustomValueStepTemplateStepListTemplateThe template. Navigation.

Endpoints

MethodURLDescription
GET{{serverURL}}/Products?$expand=CustomValueStepTemplateGet Products
GET{{serverURL}}/Products(20001L)Retrieve a Product
POST{{serverURL}}/ProductsCreate a Product
PUT{{serverURL}}/Products(20001L)Update a Product
DELETE{{serverURL}}/Products(20001L)Delete a Product

GET Get Products

GET {{serverURL}}/Products?$expand=CustomValueStepTemplate

All products with their custom-value template.

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Products",
  "value": [
    {
      "Id": "20001",
      "Version": 1,
      "Name": "Boiler X200",
      "SubKey": "X200-24kW",
      "Description": "Condensing gas boiler, 24 kW",
      "DateModified": "2026-08-25T08:00:00Z",
      "MappingId": "PRD-X200",
      "CustomValueStepTemplateId": "12002",
      "CustomValueStepTemplate": {
        "Id": "12002",
        "Name": "Boiler technical data",
        "IsReleased": true,
        "IsDurable": true
      }
    }
  ]
}

GET Retrieve a Product

GET {{serverURL}}/Products(20001L)

Loads one product.

Headers

HeaderValue
ProperStatusCodestrue

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Products/@Element",
  "Id": "20001",
  "Version": 1,
  "Name": "Boiler X200",
  "SubKey": "X200-24kW",
  "Description": "Condensing gas boiler, 24 kW",
  "DateModified": "2026-08-25T08:00:00Z",
  "MappingId": "PRD-X200",
  "CustomValueStepTemplateId": "12002"
}
404 404 Not Found
{
  "odata.error": {
    "code": "",
    "message": {
      "lang": "en-US",
      "value": "The entity Product with Key: 20001 can not be found"
    }
  }
}

POST Create a Product

POST {{serverURL}}/Products

Creates a product. Name is required; CustomValueStepTemplateId must reference a released, durable step list template.

Headers

HeaderValue
Content-Typeapplication/json

Request body

{
  "Name": "Boiler X200",
  "SubKey": "X200-24kW",
  "Description": "Condensing gas boiler, 24 kW",
  "MappingId": "PRD-X200",
  "CustomValueStepTemplateId": 12002
}

Responses

201 201 Created
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Products/@Element",
  "Id": "20001",
  "Version": 1,
  "Name": "Boiler X200",
  "SubKey": "X200-24kW",
  "Description": "Condensing gas boiler, 24 kW",
  "DateModified": "2026-08-25T08:00:00Z",
  "MappingId": "PRD-X200",
  "CustomValueStepTemplateId": "12002"
}

PUT Update a Product

PUT {{serverURL}}/Products(20001L)

Replaces the product.

Headers

HeaderValue
Preferreturn-content
Content-Typeapplication/json

Request body

{
  "Id": 20001,
  "Name": "Boiler X200",
  "SubKey": "X200-28kW",
  "Description": "Condensing gas boiler, 28 kW",
  "MappingId": "PRD-X200",
  "CustomValueStepTemplateId": 12002
}

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Products/@Element",
  "Id": "20001",
  "Version": 2,
  "Name": "Boiler X200",
  "SubKey": "X200-28kW",
  "Description": "Condensing gas boiler, 28 kW",
  "DateModified": "2026-08-25T08:00:00Z",
  "MappingId": "PRD-X200",
  "CustomValueStepTemplateId": "12002"
}

DELETE Delete a Product

DELETE {{serverURL}}/Products(20001L)

Deletes the product; instances stay as plain service objects.

Responses

204 204 No Content

No body.

Service Object Recurring Event 4 endpoints

Service Object Recurring Events (maintenance plans) generate service requests from a template on a schedule for a service object – e.g. a yearly inspection. Generated jobs have Type = IsRecurringJob.

The set supports listing, retrieving and creating; plans are edited in the portal.

Attributes
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: ServiceObjectReocurringEvents(123L).
VersionintRow version, incremented on every update. Read-only.
NamestringName of the maintenance plan. Required.
ExternalIdstringFree identifier for your own system (ERP number, foreign key, …).
CustomerCompanyCustomer. Navigation.
CustomerIdlongCustomer the jobs are created for (taken from the service object when omitted).
NotestringNote copied into the generated jobs (see DeleteNoteWithNextExecution).
ServiceObjectServiceObjectService object. Navigation.
ServiceObjectIdlongService object the recurring job is for. Required.
ProductInstancesServiceObject[]Additional product instances covered by the plan. Navigation.
ServiceRequestTemplateIdlongTemplate the jobs are created from. Required.
ServiceRequestTemplateServiceRequestThe template. Navigation.
IntervalstringSchedule as a 5-part cron pattern minute hour day-of-month month day-of-week, e.g. 0 8 1 * * (monthly on the 1st at 08:00), 0 8 1 1,7 * (twice a year), 0 8 * * 1 (every Monday). Required.
FirstExecutiondatetimeFirst date a job is generated.
LastExecutiondatetimeTimestamp of the last generation run. Read-only.
LastExecutionDatedatetimeDate of the last generated job. Read-only.
NextExecutiondatetimeNext scheduled generation. Read-only.
IntervalPeriodintRepeat every n periods of the cron interval (e.g. 2 with a monthly pattern = every second month).
DeleteNoteWithNextExecutionboolClear Note after the next job has been generated (one-off remark).

Endpoints

MethodURLDescription
GET{{serverURL}}/ServiceObjectReocurringEvents?$expand=ServiceObject,ServiceRequestTemplateGet Recurring Events
GET{{serverURL}}/ServiceObjectReocurringEvents?$filter=ServiceObjectId eq 4001LGet Recurring Events of a Service Object
GET{{serverURL}}/ServiceObjectReocurringEvents(21001L)Retrieve a Recurring Event
POST{{serverURL}}/ServiceObjectReocurringEventsCreate a Recurring Event

GET Get Recurring Events

GET {{serverURL}}/ServiceObjectReocurringEvents?$expand=ServiceObject,ServiceRequestTemplate

All maintenance plans with object and template. Note the spelling of the set name (Reocurring).

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceObjectReocurringEvents",
  "value": [
    {
      "Id": "21001",
      "Version": 1,
      "Name": "Yearly inspection – Heating pump 3",
      "CustomerId": "2001",
      "Note": "Bring replacement filter",
      "ServiceObjectId": "4001",
      "ServiceRequestTemplateId": "1111",
      "Interval": "0 8 1 3 *",
      "FirstExecution": "2027-03-01T08:00:00Z",
      "NextExecution": "2027-03-01T08:00:00Z",
      "IntervalPeriod": 1,
      "DeleteNoteWithNextExecution": false,
      "ServiceObject": {
        "Id": "4001",
        "Name": "Heating pump 3"
      },
      "ServiceRequestTemplate": {
        "Id": "1111",
        "Name": "Standard maintenance",
        "IsTemplate": true
      }
    }
  ]
}

GET Get Recurring Events of a Service Object

GET {{serverURL}}/ServiceObjectReocurringEvents?$filter=ServiceObjectId eq 4001L

Plans of one asset.

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceObjectReocurringEvents",
  "value": [
    {
      "Id": "21001",
      "Version": 1,
      "Name": "Yearly inspection – Heating pump 3",
      "CustomerId": "2001",
      "Note": "Bring replacement filter",
      "ServiceObjectId": "4001",
      "ServiceRequestTemplateId": "1111",
      "Interval": "0 8 1 3 *",
      "FirstExecution": "2027-03-01T08:00:00Z",
      "NextExecution": "2027-03-01T08:00:00Z",
      "IntervalPeriod": 1,
      "DeleteNoteWithNextExecution": false
    }
  ]
}

GET Retrieve a Recurring Event

GET {{serverURL}}/ServiceObjectReocurringEvents(21001L)

Loads one plan.

Headers

HeaderValue
ProperStatusCodestrue

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceObjectReocurringEvents/@Element",
  "Id": "21001",
  "Version": 1,
  "Name": "Yearly inspection – Heating pump 3",
  "CustomerId": "2001",
  "Note": "Bring replacement filter",
  "ServiceObjectId": "4001",
  "ServiceRequestTemplateId": "1111",
  "Interval": "0 8 1 3 *",
  "FirstExecution": "2027-03-01T08:00:00Z",
  "NextExecution": "2027-03-01T08:00:00Z",
  "IntervalPeriod": 1,
  "DeleteNoteWithNextExecution": false
}

POST Create a Recurring Event

POST {{serverURL}}/ServiceObjectReocurringEvents

Creates a maintenance plan.

BodyTypeDescription
NamestringRequired.
ServiceObjectIdlongRequired.
ServiceRequestTemplateIdlongRequired. A service request template (IsTemplate eq true).
IntervalstringRequired. 5-part cron pattern, e.g. 0 8 1 3 * = every 1 March 08:00. An invalid pattern is rejected with 400 ("Invalid CronPattern. Expected 5 Cron parts").
IntervalPeriodintEvery *n*-th occurrence. Default 1.
FirstExecutiondatetimeStart date.
CustomerId, Note, DeleteNoteWithNextExecution, ExternalIdOptional.

Headers

HeaderValue
Content-Typeapplication/json

Request body

{
  "Name": "Yearly inspection – Heating pump 3",
  "ServiceObjectId": 4001,
  "ServiceRequestTemplateId": 1111,
  "Interval": "0 8 1 3 *",
  "IntervalPeriod": 1,
  "FirstExecution": "2027-03-01T08:00:00Z",
  "Note": "Bring replacement filter",
  "DeleteNoteWithNextExecution": false
}

Responses

201 201 Created
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceObjectReocurringEvents/@Element",
  "Id": "21001",
  "Version": 1,
  "Name": "Yearly inspection – Heating pump 3",
  "CustomerId": "2001",
  "Note": "Bring replacement filter",
  "ServiceObjectId": "4001",
  "ServiceRequestTemplateId": "1111",
  "Interval": "0 8 1 3 *",
  "FirstExecution": "2027-03-01T08:00:00Z",
  "NextExecution": "2027-03-01T08:00:00Z",
  "IntervalPeriod": 1,
  "DeleteNoteWithNextExecution": false
}
400 400 Bad Request
{
  "odata.error": {
    "code": "",
    "message": {
      "lang": "en-US",
      "value": "Invalid CronPattern. Expected 5 Cron parts got 3"
    }
  }
}

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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Users(123L).
VersionintRow version, incremented on every update. Read-only.
UserNamestringLogin name (e-mail address). Required on create.
IsSystemboolSystem account (integration user). Read-only.
CreationDatedatetimeDate of creation (UTC). Read-only.
IsApprovedboolAccount approved. Read-only.
ContactIdlongContact record of the user. Required on create – create the contact first.
ContactContactThe contact (name, phone, group). Navigation.
PreferedLanguagestringUI language, e.g. de-DE, en-US, fr-FR, it-IT.
EmailChannelEnabledboolReceives e-mail notifications.
HasFullScreenPreferenceboolUI preference. Read-only.
TimeZoneintTime-zone offset preference.
PreferedCulturestringNumber/date formatting culture, e.g. de-DE.
IsActiveboolAccount enabled. Set false to deactivate a user (frees the licence).
IsMobileboolMay use the mobile app (technician licence).
LastLoginDatedatetimeLast login. Read-only.
UserGuideProgressstringOnboarding state. Read-only.
DashboardSettingsstringDashboard configuration JSON. Read-only.

Endpoints

MethodURLDescription
GET{{serverURL}}/Users?$expand=Contact&$filter=IsActive eq trueGet Users
GET{{serverURL}}/Users/$count?$filter=IsActive eq true and IsMobile eq trueCount Users
GET{{serverURL}}/Users(1002L)?$expand=ContactRetrieve a User
POST{{serverURL}}/UsersCreate a User
PUT{{serverURL}}/Users(1002L)Update a User (PUT)
PATCH{{serverURL}}/Users(1002L)Deactivate / Activate a User (PATCH)
DELETE{{serverURL}}/Users(1002L)Delete a User

GET Get Users

GET {{serverURL}}/Users?$expand=Contact&$filter=IsActive eq true

Active users with their contact. Map Contact.IdContactId 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

Loads one user.

Headers

HeaderValue
ProperStatusCodestrue

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.

BodyTypeDescription
UserNamestringRequired. E-mail address used to log in.
ContactIdlongRequired. Existing contact (create it with POST Contacts first).
IsMobilebooltrue for technicians (mobile licence), false for office users.
IsActiveboolDefault true.
PreferedLanguage / PreferedCulturestringOptional.

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

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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.

Group 2 endpoints

Groups are technician teams (used for filtering the planning board and for team appointments). Read-only through the API; assign a contact to a group via Contact.GroupId.

Attributes
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Groups(123L).
VersionintRow version, incremented on every update. Read-only.
NamestringTeam name.

Endpoints

MethodURLDescription
GET{{serverURL}}/GroupsGet Groups
GET{{serverURL}}/Groups(1500L)Retrieve a Group

GET Get Groups

GET {{serverURL}}/Groups

All technician groups.

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Groups",
  "value": [
    {
      "Id": "1500",
      "Version": 1,
      "Name": "North team"
    },
    {
      "Id": "1501",
      "Version": 1,
      "Name": "South team"
    }
  ]
}

GET Retrieve a Group

GET {{serverURL}}/Groups(1500L)

Loads one group.

Headers

HeaderValue
ProperStatusCodestrue

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Groups/@Element",
  "Id": "1500",
  "Version": 1,
  "Name": "North team"
}

Qualification 5 endpoints

Qualifications are skills / certificates. Link them to service requests (ServiceRequests(id)/$links/Qualifications) and offers; technicians get their qualifications in the portal. The scheduler (BestTechnicianForJob) only proposes technicians who hold all required qualifications.

Attributes
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Qualifications(123L).
VersionintRow version, incremented on every update. Read-only.
NamestringName of the skill. Required.

Endpoints

MethodURLDescription
GET{{serverURL}}/QualificationsGet Qualifications
GET{{serverURL}}/Qualifications(9001L)Retrieve a Qualification
POST{{serverURL}}/QualificationsCreate a Qualification
PUT{{serverURL}}/Qualifications(9001L)Update a Qualification
DELETE{{serverURL}}/Qualifications(9001L)Delete a Qualification

GET Get Qualifications

GET {{serverURL}}/Qualifications

All qualifications.

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Qualifications",
  "value": [
    {
      "Id": "9001",
      "Version": 1,
      "Name": "Gas installations (certified)"
    }
  ]
}

GET Retrieve a Qualification

GET {{serverURL}}/Qualifications(9001L)

Loads one qualification.

Headers

HeaderValue
ProperStatusCodestrue

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Qualifications/@Element",
  "Id": "9001",
  "Version": 1,
  "Name": "Gas installations (certified)"
}

POST Create a Qualification

POST {{serverURL}}/Qualifications

Creates a qualification. Name is required.

Headers

HeaderValue
Content-Typeapplication/json

Request body

{
  "Name": "Gas installations (certified)"
}

Responses

201 201 Created
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Qualifications/@Element",
  "Id": "9001",
  "Version": 1,
  "Name": "Gas installations (certified)"
}

PUT Update a Qualification

PUT {{serverURL}}/Qualifications(9001L)

Renames the qualification.

Headers

HeaderValue
Preferreturn-content
Content-Typeapplication/json

Request body

{
  "Id": 9001,
  "Name": "Gas installations (certified, 2026)"
}

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Qualifications/@Element",
  "Id": "9001",
  "Version": 2,
  "Name": "Gas installations (certified, 2026)"
}

DELETE Delete a Qualification

DELETE {{serverURL}}/Qualifications(9001L)

Deletes the qualification and removes it from all jobs and technicians.

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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: ItemTypes(123L).
CustomValuesCustomValue[]Custom field values: [{ "Meta": "<field name>", "Value": "<value>" }].
VersionintRow version, incremented on every update. Read-only.
CostsdecimalPurchase price (net).
DescriptionstringLong description.
ListPricedecimalList price before discount.
ManufacturestringManufacturer / manufacturer part number.
ExternalIdstringFree identifier for your own system (ERP number, foreign key, …).
ItemNumberstringArticle number (same meaning as ExternalId).
NameOrNumberstringName of the article. Required.
GlobalTradeItemNrstringEAN / GTIN.
TypestringKind of article – see Type values. Default Material.
PricedecimalSelling price per unit (net).
VATdecimalVAT rate in percent (e.g. 19).
IsPortalOnlyboolNot offered on the mobile app.
DiscountdecimalDefault discount in percent.
DateModifieddatetimeDate of the last modification (UTC). Read-only.
IsDiscontinuedboolNo longer orderable (hidden from pick lists).
IsWarehouseboolStock-managed article.
UnitIdlongUnit (see Item Unit).
UnitStringstringUnit name. Read-only.
UnitItemUnitUnit. Navigation.
Type values
ValueMeaning
MaterialMaterial / spare part.
ServiceService / labour position.
EquipmentEquipment / tool.
ExchangePartExchange part of a product (requires ItemNumber).
SetSet of items (bill of material); HiddenSet hides the components.
TextText line on the item list (no price).
TitleHeading line.
SubtotalSubtotal line.
PageBreakPage break in reports.
PartialInvoicePartial-invoice position.
QuickFilterQuick-filter entry (portal only).
WageAndMaterialCombined wage & material (GAEB).

Endpoints

MethodURLDescription
GET{{serverURL}}/ItemTypes?$expand=Unit&$filter=IsDiscontinued eq false&$orderby=NameOrNumberGet Item Types
GET{{serverURL}}/ItemTypes?$filter=ExternalId eq 'BB-6204'Find an Item Type by External Id
GET{{serverURL}}/ItemTypes(15001L)?$expand=UnitRetrieve an Item Type
POST{{serverURL}}/ItemTypesCreate an Item Type
PUT{{serverURL}}/ItemTypes(15001L)Update an Item Type (PUT)
PATCH{{serverURL}}/ItemTypes(15001L)Update Prices (PATCH)
DELETE{{serverURL}}/ItemTypes(15001L)Delete an Item Type

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

Loads one article.

Headers

HeaderValue
ProperStatusCodestrue

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.

BodyTypeDescription
NameOrNumberstringRequired.
TypestringDefault Material.
ExternalIdstringRecommended – your article number.
Price, Costs, VAT, DiscountdecimalDefault 0.
UnitIdlongExisting item unit.
Manufacture, GlobalTradeItemNr, Description, IsWarehouse, IsDiscontinued, CustomValuesOptional.

Headers

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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.

Item Unit 5 endpoints

Item Units are the units of measure for articles and items (pcs, h, m, kg, …).

Attributes
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: ItemUnits(123L).
VersionintRow version, incremented on every update. Read-only.
NamestringUnit name / symbol. Required.

Endpoints

MethodURLDescription
GET{{serverURL}}/ItemUnitsGet Item Units
GET{{serverURL}}/ItemUnits(16001L)Retrieve an Item Unit
POST{{serverURL}}/ItemUnitsCreate an Item Unit
PUT{{serverURL}}/ItemUnits(16004L)Update an Item Unit
DELETE{{serverURL}}/ItemUnits(16004L)Delete an Item Unit

GET Get Item Units

GET {{serverURL}}/ItemUnits

All units.

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ItemUnits",
  "value": [
    {
      "Id": "16001",
      "Version": 1,
      "Name": "pcs"
    },
    {
      "Id": "16002",
      "Version": 1,
      "Name": "h"
    },
    {
      "Id": "16003",
      "Version": 1,
      "Name": "m"
    }
  ]
}

GET Retrieve an Item Unit

GET {{serverURL}}/ItemUnits(16001L)

Loads one unit.

Headers

HeaderValue
ProperStatusCodestrue

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ItemUnits/@Element",
  "Id": "16001",
  "Version": 1,
  "Name": "pcs"
}

POST Create an Item Unit

POST {{serverURL}}/ItemUnits

Creates a unit. Name is required.

Headers

HeaderValue
Content-Typeapplication/json

Request body

{
  "Name": "kg"
}

Responses

201 201 Created
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ItemUnits/@Element",
  "Id": "16004",
  "Version": 1,
  "Name": "kg"
}

PUT Update an Item Unit

PUT {{serverURL}}/ItemUnits(16004L)

Renames the unit.

Headers

HeaderValue
Preferreturn-content
Content-Typeapplication/json

Request body

{
  "Id": 16004,
  "Name": "kilogram"
}

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ItemUnits/@Element",
  "Id": "16004",
  "Version": 2,
  "Name": "kilogram"
}

DELETE Delete an Item Unit

DELETE {{serverURL}}/ItemUnits(16004L)

Deletes the unit.

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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: StepListTemplates(123L).
VersionintRow version, incremented on every update. Read-only.
NamestringTemplate name. Required.
MappingIdstringYour own identifier for the template.
DateModifieddatetimeDate of the last modification (UTC). Read-only.
IsReleasedboolOnly released templates can be applied to jobs. Unreleased templates return an empty Steps list.
IsDurableboolDurable checklists keep their values across jobs of the same service object (custom values).
StepsStep[]Steps of the template. Navigation – $expand=Steps. On create you may pass the steps inline.

Endpoints

MethodURLDescription
GET{{serverURL}}/StepListTemplates?$expand=Steps&$filter=IsReleased eq trueGet Step List Templates
GET{{serverURL}}/StepListTemplates(12001L)?$expand=StepsRetrieve a Step List Template
POST{{serverURL}}/StepListTemplatesCreate a Step List Template
PUT{{serverURL}}/StepListTemplates(12001L)Update a Step List Template
DELETE{{serverURL}}/StepListTemplates(12001L)Delete a Step List Template

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

HeaderValue
ProperStatusCodestrue

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

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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.

Step List Template Instance 2 endpoints

A Step List Template Instance records that a template was applied to a job. Creating one copies the template's steps into the job – the same effect as POST ServiceRequests(id)/$links/StepListTemplates.

The collection cannot be listed; retrieve instances by id or via ServiceRequests(id)?$expand=StepListTemplates.

Attributes
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: StepListTemplateInstances(123L).
VersionintRow version, incremented on every update. Read-only.
NamestringName (defaults to the template name).
ServiceRequestIdlongJob. Required.
ServiceRequestServiceRequestThe job. Navigation.
TemplateIdlongTemplate. Required.
TemplateStepListTemplateThe template. Navigation.

Endpoints

MethodURLDescription
POST{{serverURL}}/StepListTemplateInstancesCreate a Step List Template Instance (apply template to job)
GET{{serverURL}}/StepListTemplateInstances(12501L)?$expand=TemplateRetrieve a Step List Template Instance

POST Create a Step List Template Instance (apply template to job)

POST {{serverURL}}/StepListTemplateInstances

Applies the released template TemplateId to job ServiceRequestId; its steps are copied into the job.

Headers

HeaderValue
Content-Typeapplication/json

Request body

{
  "ServiceRequestId": 1234567890,
  "TemplateId": 12001
}

Responses

201 201 Created
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#StepListTemplateInstances/@Element",
  "Id": "12501",
  "Version": 1,
  "Name": "Heating pump inspection",
  "ServiceRequestId": "1234567890",
  "TemplateId": "12001"
}

GET Retrieve a Step List Template Instance

GET {{serverURL}}/StepListTemplateInstances(12501L)?$expand=Template

Loads one instance.

Headers

HeaderValue
ProperStatusCodestrue

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#StepListTemplateInstances/@Element",
  "Id": "12501",
  "Version": 1,
  "Name": "Heating pump inspection",
  "ServiceRequestId": "1234567890",
  "TemplateId": "12001",
  "Template": {
    "Id": "12001",
    "Version": 1,
    "Name": "Heating pump inspection",
    "MappingId": "HP-INSP",
    "DateModified": "2026-08-25T08:00:00Z",
    "IsReleased": true,
    "IsDurable": false
  }
}

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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Offers(123L).
NamestringTitle. Required.
ExternalIdstringFree identifier for your own system (ERP number, foreign key, …).
CreatedByContactCreator. Navigation, read-only.
ClosedByUserUser who closed it. Navigation.
ReleasedByUserUser who sent it. Navigation.
ClosedAtdatetimeClosing date.
ReleasedAtdatetimeSent date.
WorkDoneAtdatetimeNot used for offers.
TargetTimeInMinuteslongPlanned duration of the resulting job.
DateModifieddatetimeDate of the last modification (UTC). Read-only.
DateOfCreationdatetimeDate of creation (UTC). Read-only.
DueDateRangeStartdatetimeValidity start.
DueDateRangeEnddatetimeValidity end (offer expires).
PortalLinkstringCustomer-portal link where the customer can accept the offer. Read-only.
CostCenterIdlongCost center / project.
CostCenterCostCenterCost center. Navigation.
DescriptionstringOffer text (HTML).
StatestringSee State values.
ItemsItem[]Offer positions – create them with POST Items using the offer id as ServiceRequestId. Navigation.
CustomValuesCustomValue[]Custom field values: [{ "Meta": "<field name>", "Value": "<value>" }].
DestinationServiceObjectService object the offer is for. Navigation – set via $links/Destination.
QualificationsQualification[]Required qualifications. Navigation.
DocumentIdslong[]Ids of linked documents. Read-only.
DocumentsDocument[]Documents. Navigation.
ReportsReport[]Generated offer PDFs. Navigation.
ContactIdslong[]Ids of linked contacts. Read-only.
ContactsContact[]Customer contacts. Navigation.
CommentsComment[]Comments. Navigation.
CurrentOwnerIdlongResponsible office contact.
CurrentOwnerContactResponsible office user. Navigation.
CustomerIdlongCustomer. Required.
CustomerCompanyCustomer. Navigation.
VersionintRow version, incremented on every update. Read-only.
TagIdslong[]Ids of the tags. Read-only.
TagsTag[]Tags. Navigation.
IsTemplateboolOffer template.
CreateFromServiceRequestTemplateIdlongWrite-only: template to copy positions from.
InvoicesInvoice[]Invoices created from the offer. Navigation.
State values
ValueMeaning
CreatedDraft.
OfferIsSendSent to the customer.
OfferIsConfirmedAccepted by the customer.
OfferIsConfirmedAndCreateJobAccepted – a follow-up job is created from the offer.
OfferIsRejectedDeclined.
OfferIsExpiredValidity expired.
OfferIsCancelledWithdrawn.

Endpoints

MethodURLDescription
GET{{serverURL}}/Offers?$expand=Customer,Destination&$orderby=DateModified descGet Offers
GET{{serverURL}}/Offers?$filter=State eq 'OfferIsSend'&$expand=ItemsGet Offers in a State
GET{{serverURL}}/Offers/$count?$filter=State eq 'OfferIsSend'Count Offers
GET{{serverURL}}/Offers(1300001L)?$expand=Items,Contacts,Documents,Qualifications,Destination,TagsRetrieve an Offer
POST{{serverURL}}/OffersCreate an Offer
PUT{{serverURL}}/Offers(1300001L)Update an Offer (PUT)
PATCH{{serverURL}}/Offers(1300001L)Change Offer State (PATCH)
DELETE{{serverURL}}/Offers(1300001L)Delete an Offer
POST{{serverURL}}/Offers(1300001L)/$links/TagsLink a Tag to Offer
DELETE{{serverURL}}/Offers(1300001L)/$links/Tags(6001L)Unlink a Tag from Offer
POST{{serverURL}}/Offers(1300001L)/$links/ContactsLink a Contact to Offer
DELETE{{serverURL}}/Offers(1300001L)/$links/Contacts(3100L)Unlink a Contact from Offer
POST{{serverURL}}/Offers(1300001L)/$links/QualificationsLink a Qualification to Offer
DELETE{{serverURL}}/Offers(1300001L)/$links/Qualifications(9001L)Unlink a Qualification from Offer
POST{{serverURL}}/Offers(1300001L)/$links/DocumentsLink a Document to Offer
POST{{serverURL}}/Offers(1300001L)/$links/DestinationSet the Destination of an Offer
DELETE{{serverURL}}/Offers(1300001L)/$links/DestinationRemove the Destination of an Offer

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

HeaderValue
ProperStatusCodestrue

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

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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 Set the Destination of an Offer

POST {{serverURL}}/Offers(1300001L)/$links/Destination

Sets the service object the offer is for.

Headers

HeaderValue
Content-Typeapplication/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

Clears the destination.

Headers

HeaderValue
Content-Typeapplication/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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: CustomerRequests(123L).
VersionintRow version, incremented on every update. Read-only.
NamestringSubject. Required.
ExternalIdstringFree identifier for your own system (ERP number, foreign key, …).
DescriptionstringRequest text.
StatestringSee State values. Setting Closed confirms the request and creates a job; Rejected declines it.
DateOfCreationdatetimeDate of creation (UTC). Read-only.
DateModifieddatetimeDate of the last modification (UTC). Read-only.
DueDateRangeStartdatetimeRequested start.
DueDateRangeEnddatetimeRequested end.
IsTemplateboolNot used.
CreateFromServiceRequestTemplateIdlongTemplate for the job created on confirmation.
CustomerIdlongCustomer. Required.
CustomerCompanyCustomer. Navigation.
DestinationServiceObjectService object. Navigation – set via $links/Destination.
CommentsComment[]Comments. Navigation.
DocumentsDocument[]Documents. Navigation.
TagsTag[]Tags. Navigation.
CreatedByContactCreator contact (customer-portal user or API user). Navigation.
CurrentOwnerContactResponsible office user. Navigation.
State values
ValueMeaning
CreatedNew request in the inbox.
InProgressBeing handled by the office.
ClosedConfirmed – setting this state creates the follow-up job.
RejectedDeclined.

Endpoints

MethodURLDescription
GET{{serverURL}}/CustomerRequests?$filter=State eq 'Created'&$expand=Customer,DestinationGet Customer Requests
GET{{serverURL}}/CustomerRequests/$count?$filter=State eq 'Created'Count Customer Requests
GET{{serverURL}}/CustomerRequests(1400001L)?$expand=Customer,Destination,Documents,TagsRetrieve a Customer Request
GET{{serverURL}}/CustomerRequests(1400001L)/CommentsGet Comments of a Customer Request
POST{{serverURL}}/CustomerRequestsCreate a Customer Request
PATCH{{serverURL}}/CustomerRequests(1400001L)Confirm a Customer Request (creates a job)
PATCH{{serverURL}}/CustomerRequests(1400001L)Reject a Customer Request
PUT{{serverURL}}/CustomerRequests(1400001L)Update a Customer Request (PUT)
DELETE{{serverURL}}/CustomerRequests(1400001L)Delete a Customer Request
POST{{serverURL}}/CustomerRequests(1400001L)/$links/TagsLink a Tag to CustomerRequest
DELETE{{serverURL}}/CustomerRequests(1400001L)/$links/Tags(6001L)Unlink a Tag from CustomerRequest
POST{{serverURL}}/CustomerRequests(1400001L)/$links/DestinationSet the Destination of a Customer Request
DELETE{{serverURL}}/CustomerRequests(1400001L)/$links/DestinationRemove the Destination of a Customer Request

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

Loads one request.

Headers

HeaderValue
ProperStatusCodestrue

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": []
}

GET Get Comments of a Customer Request

GET {{serverURL}}/CustomerRequests(1400001L)/Comments

Conversation on the request.

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Comments",
  "value": [
    {
      "Id": "8101",
      "Version": 1,
      "DateOfCreation": "2026-08-25T08:00:00Z",
      "IsInternal": false,
      "IsCustomer": false,
      "OwnerId": "3001",
      "ServiceRequestId": "1400001",
      "Content": "Technician will call you tomorrow."
    }
  ]
}

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

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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)

Deletes the request.

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

HeaderValue
Content-Typeapplication/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

Clears the destination.

Headers

HeaderValue
Content-Typeapplication/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 URIPATCH to eIsSent / eIsPaid.

Invoices cannot be deleted; cancel them with the Cancel action (creates a cancellation invoice).

Attributes
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Invoices(123L).
VersionintRow version, incremented on every update. Read-only.
URIstringDownload URL of the invoice PDF. Read-only.
DocumentNamestringFile name. Read-only.
ReportDefinitionCodestringInvoice layout used. Read-only.
InvoiceDraftIdlongId of the invoice draft (service request of type IsInvoice) the invoice was generated from. Required on create.
ReportDefinitionIdlongInvoice report definition to render with. Optional on create (account default).
SourceServiceRequestServiceRequestJob the invoice was created for. Navigation.
AuthorContactUser who created it. Navigation.
CustomerCompanyBilled customer. Navigation.
CostCenterCostCenterCost center. Navigation.
ServiceObjectServiceObjectService object. Navigation.
FileTypestringPdfInvoice, PdfPartialInvoice, PdfCancelInvoice. Read-only.
InvoiceBalancedecimalGross total.
InvoiceBalanceNettodecimalNet total.
WageBalanceNetdecimalNet labour share (for §35a statements).
DatePayeddatetimePayment date.
InvoiceIdstringInvoice number. Read-only.
DueDatedatetimePayment due date.
WithoutVATboolReverse charge / no VAT.
SkontodecimalCash discount in percent.
PartialPaymentdecimalAmount already paid.
DateOfCreationdatetimeDate of creation (UTC). Read-only.
PerformanceDatedatetimeDate of service.
InvoiceDatedatetimeInvoice date.
InvoiceStatestringSee 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.
NotestringInternal note (editable).
DunningsReport[]Dunning letters generated for the invoice. Navigation.
TagIdslong[]Ids of the tags. Read-only.
TagsTag[]Tags. Navigation.
GobdBrokenDatedatetimeSet when the invoice was modified after issuing (GoBD audit flag). Read-only.
DetailedPriceInformationstringJSON with the price breakdown (VAT groups, discounts). Read-only.
InvoiceState values
ValueMeaning
eIsDraftDraft (not yet numbered).
eIsOpenIssued, unpaid.
eIsSentSent to the customer.
eIsPaidPaid.
eIsDunnedReminder sent (via the Dun action).
eIsCancelledCancelled (via the Cancel action).
eIsWrittenOffWritten off (bad debt).

Endpoints

MethodURLDescription
GET{{serverURL}}/Invoices?$filter=InvoiceState eq 'eIsOpen'&$expand=Customer&$orderby=InvoiceDate descGet Invoices
GET{{serverURL}}/Invoices(1600001L)?$expand=Customer,SourceServiceRequest,Tags,DunningsRetrieve an Invoice
POST{{serverURL}}/InvoicesCreate an Invoice from a Draft
PATCH{{serverURL}}/Invoices(1600001L)Mark an Invoice as Paid (PATCH)
PUT{{serverURL}}/Invoices(1600001L)Update an Invoice (PUT)
POST{{serverURL}}/Invoices(1600001L)/CancelAction: Cancel an Invoice
POST{{serverURL}}/Invoices(1600001L)/DunAction: Dun an Invoice
POST{{serverURL}}/Invoices(1600001L)/ReopenAction: Reopen an Invoice
POST{{serverURL}}/Invoices(1600001L)/CloneAction: Clone an Invoice
POST{{serverURL}}/Invoices(1600001L)/$links/TagsLink a Tag to Invoice
DELETE{{serverURL}}/Invoices(1600001L)/$links/Tags(6001L)Unlink a Tag from Invoice

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

HeaderValue
ProperStatusCodestrue

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.

BodyTypeDescription
InvoiceDraftIdlongRequired. Service request of type IsInvoice (from CreateInvoiceDraft).
ReportDefinitionIdlongInvoice layout; account default when omitted.

Returns 201 with the invoice; download the PDF from URI.

Headers

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Content-Typeapplication/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

HeaderValue
Content-Typeapplication/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

HeaderValue
Content-Typeapplication/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

HeaderValue
Content-Typeapplication/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"
}

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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: PurchaseInvoices(123L).
VersionintRow version, incremented on every update. Read-only.
NotestringNote.
NamestringTitle / description.
DateModifieddatetimeDate of the last modification (UTC). Read-only.
IsPaidboolPaid.
DateOfPaymentdatetimePayment date.
DateOfUploaddatetimeUpload date. Read-only.
DateCreateddatetimeDate of creation (UTC). Read-only.
AuthorContactUploader. Navigation.
SupplierCompanySupplier company. Navigation.
StatestringSee State values.
CostsdecimalGross amount.
CostCenterCostCenterCost center. Navigation.
ExternalIdstringFree identifier for your own system (ERP number, foreign key, …).
ReceiptNumberstringSupplier's invoice number.
ServiceRequestServiceRequestJob the costs are booked on. Navigation.
URIstringDownload URL of the receipt. Read-only.
ExtractedItemsUristringURL of the extracted positions (OCR). Read-only.
IsBlobUriboolFile stored in blob storage. Read-only.
IsLinkboolExternal link instead of upload.
FileNamestringFile name.
TagIdslong[]Ids of the tags. Read-only.
TagsTag[]Tags. Navigation.
State values
ValueMeaning
eInInboxUploaded, not yet assigned.
eIsToBeConfirmedAssigned to a job / cost center, awaiting approval.
eIsConfirmedApproved, to be paid.
eIsRejectedRejected.
eIsPaidPaid.

Endpoints

MethodURLDescription
GET{{serverURL}}/PurchaseInvoices?$filter=State eq 'eIsToBeConfirmed'&$expand=Supplier,ServiceRequest,CostCenterGet Purchase Invoices
GET{{serverURL}}/PurchaseInvoices?extractInboundInvoices=true&$filter=DateOfUpload gt datetime'2026-08-01T00:00:00Z'Get Purchase Invoices with extracted positions
GET{{serverURL}}/PurchaseInvoices(1700001L)?$expand=Supplier,TagsRetrieve a Purchase Invoice
PATCH{{serverURL}}/PurchaseInvoices(1700001L)Approve a Purchase Invoice (PATCH)
PUT{{serverURL}}/PurchaseInvoices(1700001L)Update a Purchase Invoice (PUT)
POST{{serverURL}}/PurchaseInvoices(1700001L)/$links/TagsLink a Tag to Purchase Invoice
DELETE{{serverURL}}/PurchaseInvoices(1700001L)/$links/Tags(6001L)Unlink a Tag from Purchase Invoice

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 Get Purchase Invoices with extracted positions

GET {{serverURL}}/PurchaseInvoices?extractInboundInvoices=true&$filter=DateOfUpload gt datetime'2026-08-01T00:00:00Z'

The custom query parameter extractInboundInvoices=true includes the OCR-extracted positions (ExtractedItemsUri) for each receipt.

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",
      "ExtractedItemsUri": "https://portal.mobilefieldreport.com/mfr/PurchaseInvoice/1700001/Items"
    }
  ]
}

GET Retrieve a Purchase Invoice

GET {{serverURL}}/PurchaseInvoices(1700001L)?$expand=Supplier,Tags

Loads one receipt.

Headers

HeaderValue
ProperStatusCodestrue

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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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"
}

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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Projects(123L).
VersionintRow version, incremented on every update. Read-only.
NamestringProject name. Required.
ExternalIdstringFree identifier for your own system (ERP number, foreign key, …).
BudgetTimedecimalTime budget in hours.
BudgetMaterialdecimalMaterial budget (currency).
CurrentAmountTimedecimalHours booked so far. Read-only.
CurrentAmountMaterialdecimalMaterial costs so far. Read-only.
CustomerIdlongCustomer. Required (must not be 0).
ClosedAtdatetimeClosing date. Read-only.
IsClosedboolClosed projects accept no new jobs.
CostCenterCostCenterThe cost center behind the project – jobs join the project via ServiceRequest.CostCenterId. Navigation.
ServiceRequestTemplateServiceRequestTemplate used for new project jobs. Navigation.
InvoicesInvoice[]Invoices of the project. Navigation / GET Projects(id)/Invoices.
ServiceRequestsServiceRequest[]Jobs. GET Projects(id)/ServiceRequests.
OffersServiceRequest[]Offers. GET Projects(id)/Offers.
OrdersServiceRequest[]Orders. GET Projects(id)/Orders.
TagsTag[]Tags ($links/Tags).
PipelinesTag[]Pipeline stages for tasks – these are Tags linked via $links/Pipelines.
TasksAppointment[]Project tasks (appointments of type Task). GET/POST Projects(id)/Tasks.

Endpoints

MethodURLDescription
GET{{serverURL}}/Projects?$filter=IsClosed eq false&$expand=CostCenterGet Projects
GET{{serverURL}}/Projects(1800001L)?$expand=CostCenter,ServiceRequestTemplate,Tags,PipelinesRetrieve a Project
POST{{serverURL}}/ProjectsCreate a Project
PUT{{serverURL}}/Projects(1800001L)Update a Project (PUT)
PATCH{{serverURL}}/Projects(1800001L)Close a Project (PATCH)
DELETE{{serverURL}}/Projects(1800001L)Delete a Project
GET{{serverURL}}/Projects(1800001L)/ServiceRequests?$select=Id,Name,StateGet Service Requests of a Project
GET{{serverURL}}/Projects(1800001L)/OffersGet Offers of a Project
GET{{serverURL}}/Projects(1800001L)/OrdersGet Orders of a Project
GET{{serverURL}}/Projects(1800001L)/InvoicesGet Invoices of a Project
GET{{serverURL}}/Projects(1800001L)/Tasks?$expand=Pipeline,ContactGet Tasks of a Project
POST{{serverURL}}/Projects(1800001L)/TasksCreate a Task in a Project
PUT{{serverURL}}/Projects(1800001L)/Tasks(5201L)Update a Task of a Project
DELETE{{serverURL}}/Projects(1800001L)/Tasks(5201L)Delete a Task of a Project
POST{{serverURL}}/Projects(1800001L)/$links/TagsLink a Tag to a Project
DELETE{{serverURL}}/Projects(1800001L)/$links/Tags(6001L)Unlink a Tag from a Project
POST{{serverURL}}/Projects(1800001L)/$links/PipelinesLink a Pipeline to a Project
DELETE{{serverURL}}/Projects(1800001L)/$links/Pipelines(6201L)Unlink a Pipeline from a Project

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

Loads one project.

Headers

HeaderValue
ProperStatusCodestrue

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

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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)

Partial update.

Headers

HeaderValue
Preferreturn-content
Content-Typeapplication/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

Offers of the project.

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

Orders of the project.

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

Invoices of the project.

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

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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)

Removes the task.

Responses

204 204 No Content

No body.

Cost Center 5 endpoints

Cost Centers group service requests for controlling (ServiceRequest.CostCenterId). A Project is a cost center with a budget and a job template – see the Project chapter.

Attributes
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: CostCenters(123L).
VersionintRow version, incremented on every update. Read-only.
NamestringName. Required.

Endpoints

MethodURLDescription
GET{{serverURL}}/CostCentersGet Cost Centers
GET{{serverURL}}/CostCenters(19001L)Retrieve a Cost Center
POST{{serverURL}}/CostCentersCreate a Cost Center
PUT{{serverURL}}/CostCenters(19001L)Update a Cost Center
DELETE{{serverURL}}/CostCenters(19001L)Delete a Cost Center

GET Get Cost Centers

GET {{serverURL}}/CostCenters

All cost centers (including the ones behind projects).

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#CostCenters",
  "value": [
    {
      "Id": "19001",
      "Version": 1,
      "Name": "Building A – 2026"
    }
  ]
}

GET Retrieve a Cost Center

GET {{serverURL}}/CostCenters(19001L)

Loads one cost center.

Headers

HeaderValue
ProperStatusCodestrue

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#CostCenters/@Element",
  "Id": "19001",
  "Version": 1,
  "Name": "Building A – 2026"
}

POST Create a Cost Center

POST {{serverURL}}/CostCenters

Creates a cost center. Name is required.

Headers

HeaderValue
Content-Typeapplication/json

Request body

{
  "Name": "Building A – 2026"
}

Responses

201 201 Created
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#CostCenters/@Element",
  "Id": "19001",
  "Version": 1,
  "Name": "Building A – 2026"
}

PUT Update a Cost Center

PUT {{serverURL}}/CostCenters(19001L)

Renames the cost center.

Headers

HeaderValue
Preferreturn-content
Content-Typeapplication/json

Request body

{
  "Id": 19001,
  "Name": "Building A – 2026/27"
}

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#CostCenters/@Element",
  "Id": "19001",
  "Version": 2,
  "Name": "Building A – 2026/27"
}

DELETE Delete a Cost Center

DELETE {{serverURL}}/CostCenters(19001L)

Deletes the cost center; jobs keep running without one.

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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Orders(123L).
VersionintRow version, incremented on every update. Read-only.
ExternalIdstringFree identifier for your own system (ERP number, foreign key, …).
NamestringTitle (generated from the supplier when omitted).
DescriptionstringFree text.
StatestringSee State values.
DateOfCreationdatetimeDate of creation (UTC). Read-only.
DateModifieddatetimeDate of the last modification (UTC). Read-only.
DueDateRangeStartdatetimeRequested delivery from.
DueDateRangeEnddatetimeRequested delivery until.
CustomerIdlongCustomer (for drop-shipping). Optional.
CustomerCompanyCustomer. Navigation.
DestinationServiceObjectDelivery address (service object / warehouse). Navigation.
ItemsItem[]Ordered positions – created from the open OrderBy stock movements of the supplier. Navigation.
TagsTag[]Tags. Navigation.
SupplierIdlongSupplier company (IsSupplier = true). Required on create.
WarehouseIdlongWarehouse the goods are ordered for. Optional – restricts the stock movements picked up.
State values
ValueMeaning
CreatedOpen order.
OrderPrintedOrder document generated / sent to the supplier.
ClosedGoods received, order completed.
OrderCancelledCancelled.

Endpoints

MethodURLDescription
GET{{serverURL}}/Orders?$expand=Items,Destination&$orderby=DateOfCreation descGet Orders
GET{{serverURL}}/Orders/$count?$filter=State eq 'Created'Count Orders
GET{{serverURL}}/Orders(1500001L)?$expand=Items,Tags,DestinationRetrieve an Order
POST{{serverURL}}/OrdersCreate an Order
PUT{{serverURL}}/Orders(1500001L)Update an Order (PUT)
PATCH{{serverURL}}/Orders(1500001L)Change Order State (PATCH)
DELETE{{serverURL}}/Orders(1500001L)Delete an Order
POST{{serverURL}}/Orders(1500001L)/$links/TagsLink a Tag to Order
DELETE{{serverURL}}/Orders(1500001L)/$links/Tags(6001L)Unlink a Tag from Order
POST{{serverURL}}/Orders(1500001L)/$links/DestinationSet the Destination of an Order
DELETE{{serverURL}}/Orders(1500001L)/$links/DestinationRemove the Destination of an Order

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'

Number of open orders.

Responses

200 200 OK
2

GET Retrieve an Order

GET {{serverURL}}/Orders(1500001L)?$expand=Items,Tags,Destination

Loads one order.

Headers

HeaderValue
ProperStatusCodestrue

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

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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 Set the Destination of an Order

POST {{serverURL}}/Orders(1500001L)/$links/Destination

Sets the delivery destination (warehouse or service object).

Headers

HeaderValue
Content-Typeapplication/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

Clears the destination.

Headers

HeaderValue
Content-Typeapplication/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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Warehouses(123L).
VersionintRow version, incremented on every update. Read-only.
NamestringWarehouse name. Required.
NotestringFree text.
CustomValuesCustomValue[]Custom field values: [{ "Meta": "<field name>", "Value": "<value>" }].
DateOfCreationdatetimeDate of creation (UTC). Read-only.
DateModifieddatetimeDate of the last modification (UTC). Read-only.
ExternalIdstringFree identifier for your own system (ERP number, foreign key, …).
LocationLocationAddress. See Company → Location attributes.
WarehouseManagerIdlongContact id of the responsible manager (read). On create/update the manager is passed as the object WarehouseManager: { "Id": … }.
WarehouseManagerContactManager contact. Required on create and update – send "WarehouseManager": { "Id": 3001 }; missing manager → 400 "WarehouseManager is mandatory you need to provide one". Navigation ($expand=WarehouseManager).
CompanyIdlongOwning company (own company or customer for consignment stock).
CompanyCompanyCompany. Navigation.
TagsTag[]Tags. Navigation.
ContactsContact[]Contacts. Navigation.
InventoryWarehouseInventoryItem[]Stock items. GET/POST Warehouses(id)/Inventory, PUT/DELETE Warehouses(id)/Inventory(itemId).
OrdersOrder[]Orders delivered to this warehouse. GET Warehouses(id)/Orders.
StockMovementsStockMovement[]Movements. GET/POST Warehouses(id)/StockMovements, PUT/DELETE …/StockMovements(id).
Inventory item attributes (Warehouses(id)/Inventory)
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: WarehouseInventoryItems(123L).
VersionintRow version, incremented on every update. Read-only.
ItemNumberstringArticle number.
NameOrNumberstringName. Required.
QuantityHoursdecimalCurrent stock quantity.
MinimumStockintReorder level – below it an OrderBy demand is created.
MaximumStockintTarget stock when reordering.
ItemTypeIdlongArticle (item type).
ItemTypeItemTypeArticle. Navigation.
PricedecimalValuation price.
CreatorIdlongCreator contact.
CreatorContactCreator. Navigation.
UnitIdlongUnit.
UnitItemUnitUnit. Navigation.

Endpoints

MethodURLDescription
GET{{serverURL}}/Warehouses?$expand=WarehouseManager,LocationGet Warehouses
GET{{serverURL}}/Warehouses(4500L)?$expand=Inventory/ItemType,WarehouseManagerRetrieve a Warehouse
POST{{serverURL}}/WarehousesCreate a Warehouse
PUT{{serverURL}}/Warehouses(4500L)Update a Warehouse (PUT)
PATCH{{serverURL}}/Warehouses(4500L)Update a Warehouse partially (PATCH)
DELETE{{serverURL}}/Warehouses(4500L)Delete a Warehouse
GET{{serverURL}}/Warehouses(4500L)/Inventory?$expand=ItemType,UnitGet Warehouse Inventory
POST{{serverURL}}/Warehouses(4500L)/InventoryCreate an Inventory Item
PUT{{serverURL}}/Warehouses(4500L)/Inventory(24001L)Update an Inventory Item
DELETE{{serverURL}}/Warehouses(4500L)/Inventory(24001L)Delete an Inventory Item
GET{{serverURL}}/Warehouses(4500L)/StockMovements?$filter=State eq 'Open'&$expand=ItemTypeGet Warehouse Stock Movements
POST{{serverURL}}/Warehouses(4500L)/StockMovementsCreate a Stock Movement in a Warehouse
PUT{{serverURL}}/Warehouses(4500L)/StockMovements(25001L)Update a Stock Movement in a Warehouse
DELETE{{serverURL}}/Warehouses(4500L)/StockMovements(25001L)Delete a Stock Movement in a Warehouse
GET{{serverURL}}/Warehouses(4500L)/Orders?$expand=ItemsGet Warehouse Orders
POST{{serverURL}}/Warehouses(4500L)/OrdersCreate an Order in a Warehouse (not supported)
PUT{{serverURL}}/Warehouses(4500L)/Orders(1500001L)Update an Order in a Warehouse
DELETE{{serverURL}}/Warehouses(4500L)/Orders(1500001L)Delete an Order in a Warehouse

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

HeaderValue
ProperStatusCodestrue

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

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: StockMovements(123L).
VersionintRow version, incremented on every update. Read-only.
AmountdecimalQuantity moved / demanded. Required.
AmountReceiveddecimalQuantity actually received (set on confirmation).
ExternalIdstringFree identifier for your own system (ERP number, foreign key, …).
ItemIdlongJob item that caused the movement (consumption).
ItemItemJob item. Navigation.
ItemTypeIdlongArticle. Required (unless ItemId is given).
ItemTypeItemTypeArticle. Navigation.
StockMovementTypestringSee StockMovementType values. Required.
StatestringSee State values. Default Open.
ServiceRequestIdlongJob the movement belongs to (consumption / return).
ServiceRequestServiceRequestJob. Navigation.
WarehouseIdlongWarehouse. Required.
WarehouseServiceObjectWarehouse (service object). Navigation.
DateOfCreationdatetimeDate of creation (UTC). Read-only.
DateModifieddatetimeDate of the last modification (UTC). Read-only.
TargetDatedatetimeRequested date.
CreatedByIdlongCreator contact.
CreatedByContactCreator. Navigation.
ConfirmedByIdlongContact who confirmed.
ConfirmedByContactConfirmer. Navigation.
DeliveryDatedatetimeActual delivery date.
SourceWarehouseIdlongSource warehouse for transfers.
StockMovementType values
ValueMeaning
OrderByDemand: article to be ordered from the supplier (collected by Orders).
ReturnByReturn to the warehouse.
FillUpRefill of a car stock / consumption on a job.
CorrectedManual stock correction.
State values
ValueMeaning
OpenCreated, not yet processed.
ConfirmedGoods received / movement confirmed (AmountReceived).
ClosedCompleted.
CanceledCancelled.

Endpoints

MethodURLDescription
GET{{serverURL}}/StockMovements?$filter=State eq 'Open' and StockMovementType eq 'OrderBy'&$expand=ItemType,WarehouseGet Stock Movements
GET{{serverURL}}/StockMovements?$filter=ServiceRequestId eq 1234567890LGet Stock Movements of a Service Request
GET{{serverURL}}/StockMovements(25001L)Retrieve a Stock Movement
POST{{serverURL}}/StockMovementsCreate a Stock Movement
PATCH{{serverURL}}/StockMovements(25001L)Confirm a Stock Movement (PATCH)
PUT{{serverURL}}/StockMovements(25001L)Update a Stock Movement (PUT)

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)

Loads one movement.

Headers

HeaderValue
ProperStatusCodestrue

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.

BodyTypeDescription
WarehouseIdlongRequired.
ItemTypeIdlongRequired. Article.
AmountdecimalRequired.
StockMovementTypestringRequired. OrderBy, ReturnBy, FillUp, Corrected.
StatestringDefault Open.
ServiceRequestId, TargetDate, SourceWarehouseId, ExternalIdOptional.

Headers

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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"
}

Tags 6 endpoints

Tags are coloured labels used to categorise and filter entities. A tag has a Type that decides which entity it can be attached to. Tags are attached with $links/Tags on the respective set (e.g. ServiceRequests(id)/$links/Tags).

Filtering on this set is done in memory – keep filters simple (Type eq 'ServiceRequest', Name eq '…').

Attributes
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: Tags(123L).
VersionintRow version, incremented on every update. Read-only.
NamestringLabel text. Required.
GrpNamestringOptional group name – tags of one group are shown together and act as a single-choice group in the portal.
ColorDefinitionstringColour as hex code including #, e.g. #1491ad.
Typestring (enum)Entity kind the tag is for – see Type values. Required.
IsHiddenboolHidden from pick lists (kept for existing assignments).
Type values
ValueMeaning
ServiceRequestJobs, offers, orders, customer requests, invoices, projects ($links/Tags).
CompanyCustomers.
ServiceObjectService objects / warehouses.
DocumentDocuments.
ReportReports.
TenantMulti-tenant grouping (internal).

Endpoints

MethodURLDescription
GET{{serverURL}}/Tags?$filter=Type eq 'ServiceRequest'Get Tags
GET{{serverURL}}/ServiceRequests(1234567890L)?$expand=Tags&$select=Id,TagsGet Tags of a Service Request
GET{{serverURL}}/Tags(6001L)Retrieve a Tag
POST{{serverURL}}/TagsCreate a Tag
PUT{{serverURL}}/Tags(6001L)Update a Tag
DELETE{{serverURL}}/Tags(6001L)Delete a Tag

GET Get Tags

GET {{serverURL}}/Tags?$filter=Type eq 'ServiceRequest'

Tags for jobs. Without the filter all tags are returned.

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Tags",
  "value": [
    {
      "Id": "6001",
      "Version": 1,
      "Name": "Repair",
      "GrpName": "Job type",
      "ColorDefinition": "#1491ad",
      "Type": "ServiceRequest",
      "IsHidden": false
    },
    {
      "Id": "6002",
      "Version": 1,
      "Name": "Maintenance",
      "GrpName": "Job type",
      "ColorDefinition": "#2e7d32",
      "Type": "ServiceRequest",
      "IsHidden": false
    }
  ]
}

GET Get Tags of a Service Request

GET {{serverURL}}/ServiceRequests(1234567890L)?$expand=Tags&$select=Id,Tags

Tags are read through the owning entity's Tags navigation.

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#ServiceRequests/@Element",
  "Id": "1234567890",
  "Tags": [
    {
      "Id": "6001",
      "Version": 1,
      "Name": "Repair",
      "GrpName": "Job type",
      "ColorDefinition": "#1491ad",
      "Type": "ServiceRequest",
      "IsHidden": false
    }
  ]
}

GET Retrieve a Tag

GET {{serverURL}}/Tags(6001L)

Loads one tag.

Headers

HeaderValue
ProperStatusCodestrue

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Tags/@Element",
  "Id": "6001",
  "Version": 1,
  "Name": "Repair",
  "GrpName": "Job type",
  "ColorDefinition": "#1491ad",
  "Type": "ServiceRequest",
  "IsHidden": false
}

POST Create a Tag

POST {{serverURL}}/Tags

Creates a tag. Name and Type are required; ColorDefinition must include the #.

Headers

HeaderValue
Content-Typeapplication/json

Request body

{
  "Name": "Repair",
  "GrpName": "Job type",
  "ColorDefinition": "#1491ad",
  "Type": "ServiceRequest"
}

Responses

201 201 Created
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Tags/@Element",
  "Id": "6001",
  "Version": 1,
  "Name": "Repair",
  "GrpName": "Job type",
  "ColorDefinition": "#1491ad",
  "Type": "ServiceRequest",
  "IsHidden": false
}

PUT Update a Tag

PUT {{serverURL}}/Tags(6001L)

Renames / recolours the tag. The body is required.

Headers

HeaderValue
Preferreturn-content
Content-Typeapplication/json

Request body

{
  "Id": 6001,
  "Name": "Repair (urgent)",
  "GrpName": "Job type",
  "ColorDefinition": "#d32f2f",
  "Type": "ServiceRequest",
  "IsHidden": false
}

Responses

200 200 OK
{
  "odata.metadata": "https://portal.mobilefieldreport.com/odata/$metadata#Tags/@Element",
  "Id": "6001",
  "Version": 2,
  "Name": "Repair (urgent)",
  "GrpName": "Job type",
  "ColorDefinition": "#d32f2f",
  "Type": "ServiceRequest",
  "IsHidden": false
}

DELETE Delete a Tag

DELETE {{serverURL}}/Tags(6001L)

Deletes the tag and removes it from all entities.

Responses

204 204 No Content

No body.

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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: WebHooks(123L).
VersionintRow version, incremented on every update. Read-only.
UserIdlongOwner of the webhook (the API user). Read-only.
WebHookTypestringEvent type – see WebHookType values. Required.
CallbackUrlstringHTTPS URL that receives the POST. Required.
ExternalIdstringYour description / identifier.
DateOfCreationdatetimeDate of creation (UTC). Read-only.
LastAttemptdatetimeLast delivery attempt. Read-only.
BrokenSincedatetimeSet when deliveries keep failing. Read-only.
WebHookType values
ValueMeaning
ServiceRequestStateChangedThe state of a job changed (released, closed, …).
NewServiceRequestA job was created.
NewAppointmentAn appointment was created / assigned.
AppointmentChangedAn appointment was modified (time, technician, state).
NewCompanyA customer was created.
NewServiceObjectA service object was created.
NewTimeEventA time recording was created.
NewReportA report was generated.
NewInvoiceAn invoice was generated.
NewPurchaseInvoiceDocumentA purchase invoice document was uploaded.
TagServiceRequestAdded / TagServiceRequestRemovedA tag was added to / removed from a job.
TagCompanyAdded / TagCompanyRemovedA tag was added to / removed from a company.
TagServiceObjectAdded / TagServiceObjectRemovedA tag was added to / removed from a service object.

Endpoints

MethodURLDescription
GET{{serverURL}}/WebHooksGet WebHooks
GET{{serverURL}}/WebHooks(18001L)Retrieve a WebHook
POST{{serverURL}}/WebHooksCreate a WebHook
PUT{{serverURL}}/WebHooks(18001L)Update a WebHook
DELETE{{serverURL}}/WebHooks(18001L)Delete a WebHook

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)

Loads one webhook.

Headers

HeaderValue
ProperStatusCodestrue

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

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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
AttributeTypeDescription
IdlongUnique identifier (Edm.Int64). Write it as Id in PUT bodies and with an L suffix in URLs: ReportDefinitions(123L).
VersionintRow version, incremented on every update. Read-only.
CodestringUnique code, generated by the server. Do not send on create.
HtmlTemplatestringHTML body template (Handlebars-style). May be sent Base64-encoded.
JsHelpersstringJavaScript helpers used by the template. May be sent Base64-encoded.
ConfigJsonstringDesigner configuration JSON (stored inside JsHelpers between // === Configuration === markers).
HtmlHeaderTemplatestringPage header HTML (when HasHeader). May be Base64-encoded.
HtmlFooterTemplatestringPage footer HTML (when HasFooter). May be Base64-encoded.
IsDefaultboolDefault definition for its type.
IsEnabledboolOffered to users.
VisibleNamestringDisplay name. Required.
DateModifiedstringLast modification. Read-only.
RequiredCustomValuesstringComma-separated custom value names the template needs.
RequiredStepTrackingIdsstringComma-separated step tracking ids the template needs.
RequiredTemplateIdlongStep list template the report requires on the job.
FileTypestringOutput type – see Report → FileType values (e.g. Pdf, PdfInvoice, HtmlToXlsx).
DataSourcestringData the template is rendered with (e.g. ServiceRequest, ServiceObject, Company, Appointment, …).
ReportingEnginestringCHROME (default), WKHTMLTOPDF, PHANTOMJS or HtmlToXlsx.
NotestringInternal note.
HasHeaderboolRender HtmlHeaderTemplate on every page.
HasFooterboolRender HtmlFooterTemplate on every page.
ServiceRequestExpandQueryStringstringAdditional $expand applied when loading the job for rendering.

Endpoints

MethodURLDescription
GET{{serverURL}}/ReportDefinitions?$select=Id,Code,VisibleName,FileType,DataSource,IsEnabled,IsDefaultGet Report Definitions
GET{{serverURL}}/ReportDefinitions(23001L)Retrieve a Report Definition
POST{{serverURL}}/ReportDefinitionsCreate a Report Definition
PUT{{serverURL}}/ReportDefinitions(23003L)Update a Report Definition
PATCH{{serverURL}}/ReportDefinitions(23003L)Enable / Disable a Report Definition (PATCH)
DELETE{{serverURL}}/ReportDefinitions(23003L)Delete a Report Definition

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

HeaderValue
ProperStatusCodestrue

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

HeaderValue
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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

HeaderValue
Preferreturn-content
Content-Typeapplication/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.