Skip to main content
Contacts APIs

createContractOdometer

Records an odometer reading against a contract.

This page contains content which will be released in the next deployment

Overview

Records an odometer reading against a contract.

This method requires the ContractMaintenance:Create permission to be associated with your role.

It performs the same function as the Odometer button on the Contracts / Maintenance screen. Each reading is saved as a maintenance record against the contract, and an audit record is written for it.

Declaration. Submitting a reading is treated as the declaration the Contracts / Maintenance screen asks of external users: that the date and odometer reading are accurate, true and correct.

  • The reading is recorded against the authenticated user, with the date and time, in the maintenance record and the audit trail.

  • To record it against the person who supplied the reading, send their user id in the Audit-User-Id header. This requires the Audit:UserIdOverride permission.

  • If your application lets a person enter readings, show them this declaration before submitting.

Permissions

The permission for this api is stored in [gb_api_permissions]permission as 'ContractMaintenance:Create'.

Only roles with a stored link to this permission in [gb_role_api_permissions] can run this api.

  • The permission is available to client roles with API access. To grant it, go to System / Roles, open your API role (for example, web_services), select the APIs tab and tick ContractMaintenance:Create.

  • A newly ticked permission can take up to 5 minutes to take effect.

HTTP Method

Use the HTTP Method 'POST' for consuming this web service.

URL Examples

https://api.demo.catch-e.com/fm/contract/{contract_id}/odometer https://api.{{environment}}.catch-e.com/fm/contract/{contract_id}/odometer https://api.test.catch-e.com/fm/contract/{contract_id}/odometer 

Input Fields (Header)

Key

Format

Notes

Mandatory

Audit-User-Id

string

(Optional) The user id of the person who supplied the reading. The reading is recorded against this user in the maintenance record and the audit trail. Requires the Audit:UserIdOverride permission (403 otherwise). It changes only who is recorded; access to the contract is still checked against the authenticated user.

No

Path Parameters

Key

Format

Notes

Mandatory

contract_id

integer

The contract to record the reading against. Must exist and be within the authenticated user's client restrictions.

Yes

Input Fields (JSON)

{ "odometer": 84250, "odometer_date": "2026-08-28", "description": "Service check-in reading", "override_warnings_flag": "no" } 

Key

Format

Notes

Mandatory

odometer

integer

The odometer reading in km. Must be a whole number greater than 0, sent as a JSON number (not text, so "84250" or "84,250" is rejected). Maximum 4294967295.

Yes

odometer_date

date (yyyy-mm-dd)

The date of the reading. Must be a valid date.

Yes

description

string

Up to 150 characters. If empty or omitted, the description of the FBT VMRS code is used.

No

override_warnings_flag

string

'yes' or 'no'. Send 'yes' to save a reading that is outside the expected range (see Out-of-Range Readings below). Omitted is treated as 'no'.

No

Any other field in the request body, including client_id and odometer_valid_flag, is rejected with a 422.

How the Reading Is Saved

  • The reading is saved as an odometer record marked as valid.

  • The client is taken from the contract.

  • The record is stamped with the posted date, and recorded against the authenticated user, or the Audit-User-Id user if one is supplied.

  • A reading can be added to a contract in any status.

Out-of-Range Readings

The reading is compared with the contract's estimated odometer at that date, using the tolerance configured for your system. If the contract has no earlier valid reading to estimate from, a range of 10,000 km either side is used instead.

  • Within the expected range: the reading is saved.

  • Outside the expected range, without override_warnings_flag = 'yes': the request returns a 422 with a warning, and nothing is saved.

  • Outside the expected range, with override_warnings_flag = 'yes': the reading is saved.

Duplicate Readings

A reading with the same contract, date and odometer value as an existing reading is rejected. This also applies when the same reading is sent more than once at the same moment: only one is saved.

Response Details

Success

201 - Created

Returns the full maintenance record created. The fields below are illustrative.

{ "maintenance_id": "1047380", "contract_id": "104895", "client_id": "100001", "odometer": 84250, "odometer_date": "2026-08-28", "odometer_valid_flag": "valid", "status_flag": "history-only", "posted_date": "2026-10-19", "description": "Service check-in reading", "_links": { "self": { "href": "https://api.catch-e.loc/fm/contract/104895/odometer" } } } 

Error Response Details

422 Unprocessable Entity

Validation Message

Comments

422 - contract_id - Contract not recognised!

The contract doesn't exist, or it is outside the authenticated user's client restrictions. Both cases return the same message.

422 - odometer_date - You must enter a valid date!

odometer_date is missing or isn't a valid date.

422 - odometer - You must enter a non-zero odometer reading!

odometer is missing or 0.

422 - odometer (invalid value)

odometer is negative, not a whole number, sent as text, or above 4294967295.

422 - A matching odometer reading already exists for this contract and date.

A reading with the same contract, date and odometer value already exists.

422 - Unrecognized fields

The body contains a field this method doesn't accept, for example client_id or odometer_valid_flag.

422 - odometer (warning)

The reading is outside the expected range and override_warnings_flag isn't 'yes'. Returned in warning_messages; re-send with override_warnings_flag = 'yes' to save it.

{ "validation_messages": { "contract_id": { "recordNotFound": "Contract not recognised!" } }, "type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html", "title": "Unprocessable Entity", "status": 422, "detail": "Failed Validation" } 
{ "validation_messages": { "odometer": { "isEmpty": "You must enter a non-zero odometer reading!" } }, "type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html", "title": "Unprocessable Entity", "status": 422, "detail": "Failed Validation" } 
{ "warning_messages": { "odometer": { "warningExceptionCode": "A textual description of the warning" } }, "type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html", "title": "Unprocessable Entity", "status": 422, "detail": "Failed Validation" } 

401 Unauthorized

Validation Message

Comments

401 Unauthorized

1. You have not authenticated before running this API or 2. The token_timeout of the current session has passed. You need to authenticate again.

{ "type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html", "title": "Unauthorized", "status": 401, "detail": "Unauthorized" } 

403 Forbidden

Validation Message

Comments

403 Forbidden

- No token was sent, or your role doesn't have the ContractMaintenance:Create permission. - Go to System Roles and enter your API role (for example, 'web_services'). - Navigate to the Roles / APIs tab to make sure ContractMaintenance:Create is checked. A newly ticked permission can take up to 5 minutes to take effect.

403 Forbidden

An Audit-User-Id header was sent but your role doesn't have the Audit:UserIdOverride permission.

{ "type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html", "title": "Forbidden", "status": 403, "detail": "Forbidden" } 

406 Not Acceptable

{ "type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html", "title": "Not Acceptable", "status": 406, "detail": "Not Acceptable" } 

415 Unsupported Media Type

{ "type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html", "title": "Unsupported Media Type", "status": 415, "detail": "Not Acceptable" } 

500 Internal Error

{ "type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html", "title": "string", "status": 599, "detail": "string" } 

default Unexpected Error

{ "type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html", "title": "string", "status": 599, "detail": "string" }