Odoo Field Service Management documentation
A guide to Odoo Field Service Management: installing the module, configuring dispatch, offers, tracking, timesheets, van stock and invoicing, and building, publishing and using the technician app.
Documents version 1.0.0Updated Oct 29, 2026
Start here
In plain words: This package gives you a complete field service system for Odoo Community: an Odoo module (
taqnix_fsm) for the office, and the Flutter source code of the iPhone and Android app your technicians use on the road, even without a network. The office plans and dispatches the jobs, follows the technicians on a map, and invoices the work; the technician accepts a job, drives to the customer, works with a timer, scans the parts used, takes photos, collects the signature and sends the invoice from the phone.Tip: You do not need Odoo Enterprise: the module uses only the free apps Project, Timesheets, Inventory and Invoicing, and OpenStreetMap for the maps (no paid map key).
What is in the package
| Item | What it is |
|---|---|
taqnix_fsm.zip | The Odoo 19 module: orders, dispatch, offers, live map, geofence, timer and timesheets, van stock, signature and photos, billing, push notifications, the API of the app, Arabic translation, automated tests. |
flutter-app-source.zip | The Flutter project of the technician app (Android and iOS): offline database, sync engine, background location, barcode scanner, signature pad, photos, invoice. With a setup script, its own README and tests. |
documentation/ | This guide in English (index.html) and Arabic (index-ar.html), with PDFs, and API.md for developers. |
licensing/ | The licence (OPL-1: one purchase = one company and one app brand, updates included). |
preview-images/ | Screenshots of the app and of the Odoo screens. |
changelog.txt | History of the versions. |
How it works
| Part | Where it runs | What it does |
|---|---|---|
| Odoo module | Your Odoo server | Keeps orders, technicians, time, parts, photos, signatures and invoices; decides who is offered a job; answers the app on /api/fsm/v1/.... |
| Dispatch map | The browser of the dispatcher | Shows technicians and jobs on OpenStreetMap, refreshes by itself, draws the route of the day. |
| Technician app | The phones of your technicians | Works from a local database (SQLite). Everything the technician does is stored on the phone first and sent when there is a network. |
| Firebase (optional) | Delivers push notifications: new job, job offered, job changed or cancelled. |
In plain words: A job goes through these steps: New → Assigned → On the way → (Arrived) → In progress → (On hold) → Completed. Every step is stamped with the GPS position and the time of the phone, and these stamps cannot be edited afterwards. At the end Odoo books the timesheet, moves the parts out of the stock of the van, and prepares the invoice.
What you need
| Item | Details |
|---|---|
| Odoo | 19.0 Community or Enterprise. The apps Project, Timesheets, Inventory, Invoicing and Contacts geolocation are installed automatically with the module. |
| Python libraries | PyJWT and requests (push notifications). pip install PyJWT requests if your Odoo does not have them. |
| PDF engine | wkhtmltopdf as for any Odoo (service report and invoice PDF). |
| Address | A public https address for your Odoo: the phones must reach it. A self-signed certificate does not work on phones. |
| Outgoing email | An outgoing mail server in Odoo (Settings → Technical → Outgoing Mail Servers) to email invoices and reports. |
| A computer to build the app | A Mac for iPhone and Android (Windows or Linux can build Android only), about 30 GB free. |
| Developer tools | Flutter 3.41 or newer, Android Studio and Xcode (current versions) with CocoaPods. |
| Store accounts | Google Play Console (one-time fee) and Apple Developer Program (yearly fee). You can also distribute to your own staff without the public stores (internal testing, TestFlight, Apple Business Manager). |
| Optional | A free Firebase project for push notifications. |
Install the Odoo module
- Unzip the package. Inside is
taqnix_fsm.zip; unzip it to get the foldertaqnix_fsm. - Copy the folder into one of the
addons_pathfolders of your Odoo server and restart Odoo. - Log in as an administrator, activate Developer mode, open Apps and press Update Apps List.
- Remove the “Apps” filter, search Field Service Management and press Install.
# or from the command line ./odoo-bin -c odoo.conf -d YOUR_DATABASE -i taqnix_fsm --stop-after-init
In plain words: After the installation a new app Field Service appears in the main menu. The installation also creates a Field Service project (for the timesheets), the products Field service labor, Callout fee and Travel, six service types, skills, checklists, hold reasons and the mail templates. You can change or delete all of them.
Important: Take a backup before installing on a production database, as for any module.
First setup in 10 minutes
- Open Field Service → Configuration → Settings and walk through the sections (chapter 8). The defaults already fit most companies.
- Check the labor product and its price in Invoicing (Settings, chapter 8) and the callout and travel products.
- Create the technicians (chapter 7): an Odoo user, an employee for the timesheets, skills, a van stock location.
- Put the parts in the vans: a normal Inventory adjustment or transfer into the location of each van.
- Edit the service types to match your services: duration, price, checklist, proof required (chapter 9).
- Create the first order (chapter 10), dispatch it and try it in the app (chapters 13 and 14).
Tip: The defaults are neutral enough for HVAC, plumbing, electrical, IT, appliance repair, security and facility services. Chapter 8 ends with a table of recipes by industry.
Technicians, dispatchers and managers
In plain words: There are three groups in Settings → Users → Field Service:
| Group | Can | Uses |
|---|---|---|
| Technician | Sign in to the mobile app, see their jobs and the jobs offered to them, do the work. In Odoo they see only their own orders. | The phone |
| Dispatcher | Create, assign and cancel orders, use the map, create and send invoices, see all orders, technicians and tracking. | Odoo in the browser |
| Manager | Everything of the dispatcher plus the settings, service types, checklists, devices and the right to complete an order without the required proof. | Odoo in the browser |
In plain words: To add a technician, open Field Service → Technicians → Technicians and press New: choose the Odoo user (create it first in Settings → Users; it needs no other access right), the employee that receives the timesheets, the teams, the skills, the hourly billing rate (optional) and the van stock location. Press Create van location to create a location under the stock of your warehouse. The technician receives the group Technician automatically.
Tip: The Odoo login and password of the user are the ones used in the app. Give technicians a strong password; Sign out all devices on the technician form revokes every phone at once.
The settings, section by section
In plain words: Field Service → Configuration → Settings holds every rule of the company. Each block below says what it does and when to change it. Settings are per company.
| Setting | What it does |
|---|---|
| Default dispatch | Assigned to a technician: the dispatcher picks one. Open to the team: every technician of the team (with the skills needed) sees the job and the first to accept gets it. Offered to nearby technicians: only technicians within the radius of the job, from their last position, nearest first. Can be changed per order. |
| Offer radius, technicians offered, expiry, rounds | How far, how many, how long an offer lasts (minutes) and how many rounds are tried. If nobody accepts, the radius is doubled (optional) and the job is offered again; after the last round the dispatcher gets a to-do. |
| Technicians can decline / give back a job | A technician may refuse an assigned job, or give it back before the work starts. It returns to the dispatcher (or to the offer). |
| Technicians can create orders | For walk-in customers and extra work found on site: the technician creates an order from the phone, assigned to themselves. |
| Setting | What it does |
|---|---|
| Customer signature | An order cannot be completed without the signature (can be overridden per service type). |
| Photos before / after | At least one photo of each kind is required. |
| Checklist | Items marked required on the checklist must be ticked. |
| Time to correct a completed order | The technician can still add notes, parts and photos for this many hours after completing. |
| Setting | What it does |
|---|---|
| Location tracking | Off; Only while a job is under way (from On the way until Completed); During working hours (also when idle, so you can offer jobs to the nearest technician). |
| Battery friendly sampling | Interval while moving (default 30 s) and while still (300 s), minimum distance between points (25 m), and the battery level under which the app samples less. |
| Arrival detection (geofence) | Radius around the job (default 150 m) and the time the technician must stay inside (seconds). Then: Ask the technician (push + a prompt in the app), Mark as arrived, or Mark as arrived and start the work (starts the timer). |
| Privacy | The text shown in the app before it asks for the location permission, and how many days the location points are kept (default 30). |
| Setting | What it does |
|---|---|
| Timesheets | On completion the worked time (without the pauses that stop the timer) is booked on the employee of the technician, on the task of the order. One line per order or one per work interval; optional rounding up (for example 15 minutes). |
| Project task per order | Every order gets a task in the Field Service project, for timesheet reports and the Project app. |
| Warn when a technician has no employee | The dispatcher gets a to-do when a timesheet could not be booked. |
| Setting | What it does |
|---|---|
| When parts are used | Validate the stock moves: when the order is completed a transfer from the van to the customer is created and validated. Create the transfer to validate later: the transfer waits for a storekeeper. Do not move stock: only billing. |
| Parent of the van locations | New van locations are created below this location. |
| Allow parts the van does not have / any product | Strict mode: the technician can only use what is in the van. |
| Prices in the app | Show the prices to the technician and, separately, let them change them. |
| Setting | What it does |
|---|---|
| Default billing | Time and materials, Fixed price or Materials only; the labor product and whether the hourly rate of the technician is used (chapter 15). |
| Duration based billing | Bill time in blocks (default 15 min), a minimum billable time (default 60 min) and minutes covered by the callout fee. |
| Callout and travel | A fee per visit and a fee per kilometre beyond a free distance, measured from the recorded positions between On the way and Arrived. |
| Invoice creation | Manually, or automatically when the order is completed, optionally confirmed and emailed too. |
| Invoicing from the app | What the technician may do on the phone: create the draft invoice, confirm it, email it to the customer. |
| Setting | What it does |
|---|---|
| Push notifications | To the technician: job assigned or changed, job offered, job cancelled. |
| Emails to the customer | A message when the technician is on the way; the service report (PDF) when the work is completed. |
| Firebase | The identifiers of your Firebase project and the service account JSON (chapter 17). |
| Industry | Suggested settings |
|---|---|
| HVAC and refrigeration | Service types: Repair (time and materials) and Preventive maintenance (fixed price with included minutes). Van stock strict, photo after required, checklist required, geofence prompt. |
| Plumbing and emergency repair | Default dispatch nearby, offer radius 15-25 km, tracking during working hours, callout fee and travel fee, geofence auto-arrived, no required photos. |
| Electrical | Checklist with a safety item (required), hold reason Safety issue, signature required, photos before and after. |
| IT and network | No parts or few; time billing in blocks of 15 minutes, minimum 30; tracking on job only; signature required. |
| Appliance repair | Time and materials, van stock, Warranty visit service type with materials only; photos before and after. |
| Security and CCTV installation | Fixed price per installation, photos after required, checklist with serial numbers noted. |
| Facility services and cleaning | Fixed price, checklist required, signature of the site manager, tracking on job only. |
| Medical and lab equipment | Signature always required, checklist required, Manager can complete without proof only for managers. |
Service types, skills, checklists and hold reasons
In plain words: These lists describe your business. They live in Field Service → Configuration and are copied into every order, so changing them never alters old orders.
| List | What to know |
|---|---|
| Service types | Planned duration (used for the calendar), skills needed, a checklist, whether the signature and the photos are required (as in the settings, yes or no), billing mode, price, included minutes, hourly rate and callout fee. The app shows them with their color. |
| Skills | Attached to technicians and service types. With skills on the order only the qualified technicians are offered the job and ranked first in the assignment wizard. |
| Checklists | Templates of tasks; items marked required must be done before completion when the setting is on. The technician ticks them in the app and can add a note. |
| Hold reasons | Offered when a technician pauses a job (waiting for parts, customer not available, break...). Stops the timer decides whether the pause counts as worked time; Needs a note forces a comment. |
Create and dispatch orders
In plain words: Field Service → Dispatch → Orders shows the orders as a board by status, a list, a calendar by technician, and pivot and graph reports.
- Press New and choose the customer. The service address, phone and the coordinates are taken from the customer; press Find to geolocate an address with OpenStreetMap, or open the Map tab and click the exact place.
- Choose the service type (it fills the duration, skills and checklist), the scheduled start, the priority, and write the description and the instructions for the technician (gate code, who to ask for, dangers).
- Choose how to dispatch: pick a technician, or leave it open to the team or to nearby technicians.
- Press Dispatch. A direct order becomes Assigned and the technician gets a push notification; an open order becomes Offered to the technicians that qualify.
In plain words: The Assign... button opens the assignment wizard: it lists the technicians with the skills first, then by distance to the job, with their number of open orders, and lets you assign directly or turn the order into an offer.
| You want to | Do this |
|---|---|
| Give the job to somebody else | Change the Technician field or use Assign...; the first technician is told the job was removed, the new one is notified. |
| Cancel | Press Cancel; the technician is told. Set to new brings it back. |
| See who did what and where | The History tab lists every step with the time of the phone, the GPS position, the distance from the job and the source (app, Odoo, arrival detection). |
| Duplicate a recurring job | Use the standard Odoo Duplicate action; recurring contracts are not included (chapter 20). |
Offers: any technician can accept a job
In plain words: When the dispatch is Open to the team or Offered to nearby technicians, the job is sent as an offer to the technicians that qualify (team, skills, and for nearby: within the radius of their last known position). They get a push notification and see it in the Offers list of the app with the distance. The first one to press Accept gets the job; the others are told it was taken, and a late answer is refused.
| Step | What happens |
|---|---|
| Offer | Technicians busy with a job are skipped unless nobody else qualifies. Up to technicians offered at most are chosen, nearest first. |
| Expiry | After an offer expires after minutes, the offer is renewed with a larger radius (if widen is on). |
| Escalation | After the last round the job is not offered any more and the team leader (or the dispatchers) gets a to-do: Nobody accepted the job. |
| Decline | A technician can decline an offer (it disappears from their list) or an assigned job (it returns to the dispatcher). |
The dispatch map and live location
In plain words: Field Service → Dispatch → Map shows technicians and orders on OpenStreetMap. Technicians are round badges with their initials and a status dot (green online, orange not seen for a while, grey offline), orders are pins colored by status with a red ring for urgent jobs. The map refreshes by itself every 30 seconds.
| Do | How |
|---|---|
| Filter | By team, only open orders, show or hide orders and technicians. |
| Follow a technician | Click the name, press Today's route (the line is built from the location points of the last 8 hours). |
| Assign from the map | The list To dispatch shows the orders waiting; click one and press Assign. |
| Location history | Reporting → Location history lists the points (time, accuracy, speed, battery, network). |
In plain words: What the app sends: latitude, longitude, accuracy, speed, heading, altitude, battery level, charging, network type and the time of the phone. Points are stored on the phone when there is no network and sent in batches (up to 500) when it returns; duplicates are ignored. The server also uses each point to detect the arrival.
Tip: Map tiles come from the public OpenStreetMap servers, which have a fair-use policy. For many dispatchers, enter the URL of your own or a paid tile provider in Settings → Dispatch map.
What the technician does
In plain words: The app is built around the job under way. On the Today list the technician sees the jobs, the next one first, with the customer, address, time, service and distance.
| Step | In the app | In Odoo |
|---|---|---|
| Accept | Accept or decline an offer. | The order is assigned to the technician; the other technicians are told. |
| On my way | One tap, with the navigation button (opens the maps app). | State On the way; position and time are recorded; tracking starts; optional email to the customer. |
| Arrived | A prompt appears when the phone is inside the radius, or the technician taps Arrived. | State Arrived, with the distance from the customer address. |
| Start work | Starts the timer. | A work interval starts. |
| Hold / resume | Choose the reason (waiting for parts...), add a note. | The timer pauses; the pause is recorded with its reason. |
| Parts | Search or scan the barcode, set the quantity. | Lines on the order; the stock is moved on completion. |
| Photos | Before and after photos from the camera or gallery. | Photos on the order, compressed on the phone. |
| Checklist and notes | Tick the items, write what was done. | Saved on the order. |
| Signature | The customer signs on the screen. | Image, name, time and position. |
| Complete | Checks that everything required is there. | Timesheet, stock transfer, optional invoice and report email. |
Parts, barcode, photos and signature
In plain words: The parts come from the van stock: the Inventory location of the technician. In the app, Add part opens a search by name, code or barcode, or the scanner (barcodes and QR codes). The catalog and the van quantities are stored on the phone, so searching and scanning work offline.
| Rule | Detail |
|---|---|
| Stock | On completion a transfer Field service consumption from the van to the customer location is created and validated (or left to validate, see the settings). Late additions after completion are moved at once. |
| Out of stock | By default a technician may add a part the van does not have (the stock goes negative); turn it off in the settings for strict control. |
| Billable | Each line has Billable; a part that is not billable is still taken out of the stock. |
| Locked lines | Once the stock moved, the line cannot change or be deleted; add another line to correct. |
Time, timesheets and invoices
In plain words: The timer runs while the order is In progress. A pause stops it unless its reason says otherwise (for example Waiting on site (paid time)). The Time tab lists every interval.
In plain words: The invoice is a normal customer invoice (
account.move) created from the order, as a draft. What it contains depends on the billing mode:| Mode | Labor line | Other lines |
|---|---|---|
| Time and materials | Worked time (minus the minutes covered by the callout fee), rounded up to the block (15 min) and not less than the minimum (60 min), at the hourly rate. | Billable parts; callout fee; travel beyond the free kilometres. |
| Fixed price | One line with the price of the order or service type; time beyond the included minutes is added as extra time at the hourly rate. | As above. |
| Materials only | None. | Billable parts (and fees if set). |
In plain words: The hourly rate is the first that exists: the rate of the service type, the rate of the technician (if the setting is on), the price of the labor product. Example: 79 minutes of work, blocks of 15, minimum 60, rate 85 → 90 minutes → 127.50; two filters at 18 → 36; callout 45 → 208.50 before tax.
- In Odoo press Create invoice on a completed order (or find it in Billing → To invoice), check the draft and confirm it as usual.
- Send invoice confirms it if needed and emails it to the invoice contact of the customer with the PDF; you can also do it from the app.
- Service report prints the PDF with the checklist, parts, photos and signature; it is emailed to the customer automatically if the setting is on.
Important: The email goes through the outgoing mail server of Odoo. If it is not configured, or the server refuses the message, Odoo shows the error and does not mark the invoice as sent.
The mobile app in short
In plain words: The app is written in Flutter: one code base for Android and iOS, in English and Arabic (right to left). It keeps working without a network.
| Area | What it does |
|---|---|
| Sign in | Server address, Odoo login and password. The token is kept in the secure storage of the phone. |
| Jobs | Today and upcoming jobs, offers, completed jobs; details, navigation, call the customer. |
| Active job | Timer, status buttons, hold reasons, parts, scanner, photos, signature, notes, checklist, invoice. |
| Map | The jobs and the position of the technician on OpenStreetMap. |
| Tracking | Background location, buffered offline, with battery friendly sampling; the privacy text and the permission steps. |
| Sync | Outbox of actions, retries, conflict messages and a screen of problems to resolve. |
| Settings | Language, appearance, sync now, sync issues, tracking diagnostics, clear local data, sign out (and, in debug builds only, an offline simulation switch). |
In plain words: Offline first. Everything the technician does is written to the local database and to an outbox; the screens read only the local database, so the app is as fast and usable offline as online. When a network is available, the app sends the outbox in order, each action with a unique ID (a retry can never apply it twice), then downloads what changed. The rules: the server decides assignment and cancellation; the phone decides what happened in the field (times, parts, photos, signature, notes, checklist); a pending action of the phone is never overwritten by older server data.
| Situation | Result |
|---|---|
| The dispatcher cancelled the job while the technician was offline | The actions come back as conflict: order closed and are listed in the sync issues; the job shows Cancelled. |
| Two technicians accept the same offer | The first request wins; the other gets already taken. |
| A technician starts a job that was reassigned | Not assigned: refused and listed. |
| The phone clock is wrong | The time of the phone is kept, but never earlier than the previous step of the same order. |
| No stock in the van (strict mode) | The part is refused with insufficient stock. |
Build and publish the app
In plain words: Skip this chapter if you only want to test:
flutter run works on a simulator or a connected phone.- Install Flutter (3.41 or newer), Android Studio, and on a Mac Xcode with CocoaPods; run
flutter doctorand fix what it reports. - Unzip
flutter-app-source.zipin a folder without spaces. - Run the setup script with your Odoo address and your own package name:
dart run tools/setup.dart --url https://odoo.example.com --package com.yourcompany.fieldservice. It writes the address and the identifiers into the project; add--name "Your Company Service",--color "#0f766e"and--icon your-icon-1024.pngto set the app name, the brand color and the icon (the script is safe to run again). - Run
flutter pub get, thenflutter runto try it, signing in with a technician of your Odoo.
cd flutter-app dart run tools/setup.dart --url https://odoo.example.com --package com.yourcompany.fieldservice flutter pub get flutter run --dart-define=SITE_URL=https://odoo.example.com
| Target | Command | Then |
|---|---|---|
| Android (Google Play) | flutter build appbundle --release | Upload the .aab in the Play Console. Create the signing key once and keep it safe. |
| Android (internal, no store) | flutter build apk --release | Send the .apk to your technicians (allow installation from this source). |
| iPhone (App Store, TestFlight) | flutter build ipa --release | Upload with Xcode or Transporter; create the App ID with the capabilities Push Notifications and Background Modes (location updates). |
Important: Both stores ask to justify the background location: use the sentence The app records the position of the technician during working hours and while a job is under way to dispatch jobs, navigate and prove arrival, and publish a privacy policy. The app shows its own explanation before it asks the permission.
In plain words: Push notifications (Firebase): 1) create a Firebase project; 2) add an Android app and an iOS app with your package names; 3) in Project settings → Cloud Messaging upload your APNs key for iOS; 4) in Odoo Settings → Notifications enter the project ID, the API key and the app IDs, and paste the content of a service account JSON (Project settings → Service accounts → Generate new private key). The app reads the identifiers from your server when it signs in, so the source code contains no key.
Day to day for the dispatcher
| Task | Where |
|---|---|
| Morning check | Dispatch → To dispatch (new orders) and the map (who is online). |
| Overdue | Filter Late in the orders (not started after the scheduled time). |
| Offers nobody took | Filter Offered, nobody took it, or the to-do in your Activities. |
| Complete or fix an order | Open it; managers can Complete without proof when a signature could not be collected. |
| Invoices | Billing → To invoice, then Invoices. |
| Parts consumed | Billing → Parts used lists the transfers from the vans. |
| Message a technician | Technicians → Send a notification sends a push message to chosen technicians. |
| Analysis | Reporting → Analysis: orders and worked hours by service, technician and status. |
Security and privacy
| Topic | How it is handled |
|---|---|
| Access | The app signs in with the Odoo login; internal users with the group Technician only. Record rules: a technician sees only their own orders and the orders offered to them. Accounts with two-factor authentication cannot sign in to the app. |
| Tokens | A random token per device, only its hash is stored in Odoo, devices unused for 180 days are forgotten. Devices lists them; a technician can be signed out everywhere. Odoo's own protection slows down repeated wrong passwords (a cooldown after five failures). |
| Orders are protected | Every action of the app is checked on the server: the order must be assigned to the user, the state machine must allow the move, and the proof rules apply. |
| History cannot be changed | The events (state, time, GPS) cannot be edited or deleted, not even by a manager. |
| Location | Collected only while the setting says so, with a privacy text and the system permission; points older than the retention (30 days by default) are deleted every day. Customers do not see the technician's position. |
| Secrets | The Firebase service account is readable only by Odoo administrators. The app contains only public identifiers. |
Tip: Tell your technicians what is collected and when. In some countries employee location tracking requires a written notice or consent: use the privacy text of the settings and your own policy.
Good to know
| Limit | Detail |
|---|---|
| Recurring maintenance contracts | Not included. Duplicate orders or use Odoo scheduled actions. |
| Route optimisation | Not included. The map and the assignment wizard help to choose by distance; navigation opens the maps app of the phone. |
| Lot and serial numbers | The app adds parts by quantity; serial numbers can be noted in the checklist or the notes. |
| Customer portal | Not included. The customer receives emails (on the way, service report, invoice). |
| Background location on phones | Android and iOS may stop apps to save the battery. Ask technicians to allow always location and disable battery optimisation for the app; the buffer keeps the points until the phone reconnects. |
| Odoo version | Built and tested on Odoo 19.0. Other versions need an adaptation of the views and some methods. |
| Maps | Public OpenStreetMap tiles are for moderate use; configure another tile server for heavy use. |
For developers
In plain words: Skip this chapter if you only use the product. The complete contract of the app API is in
documentation/API.md.# is the server reachable?
curl https://odoo.example.com/api/fsm/v1/ping
# {"ok": true, "api_version": 1, "server_time": "2026-10-26T08:00:00Z"}
# sign in (returns a token and the configuration)
curl -X POST https://odoo.example.com/api/fsm/v1/auth/login -H 'Content-Type: application/json' \
-d '{"login": "sara@example.com", "password": "...", "device": {"id": "abc", "platform": "android"}}'
# send buffered location points
curl -X POST https://odoo.example.com/api/fsm/v1/tracking/batch -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"points": [{"uuid": "1", "lat": 25.2, "lng": 55.27, "speed": 8.3, "heading": 90, "battery": 80, "network": "cellular", "recorded_at": "2026-10-26T08:00:00Z"}]}'
# push the queued actions and pull the changes
curl -X POST https://odoo.example.com/api/fsm/v1/sync -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"cursor": null, "ops": [{"uuid": "9d1c...", "type": "transition", "order_id": 12, "device_time": "2026-10-26T08:01:00Z", "payload": {"to": "en_route", "lat": 25.2, "lng": 55.27}}]}'| Area | Endpoints under /api/fsm/v1 |
|---|---|
| Session | GET /ping, /config, /auth/me; POST /auth/login, /auth/logout, /auth/push-token |
| Sync | POST /sync (operations: transition, claim, decline, material_set, photo_add, signature_set, notes_set, checklist_set, order_create, invoice) |
| Tracking | POST /tracking/batch (also /api/fsm/tracking/batch) |
| Data | GET /jobs/available, /orders/<id>, /catalog/products, /catalog/lookup?barcode=, /van-stock, /customers |
| Files | GET /photos/<id>, /orders/<id>/signature, /orders/<id>/invoice.pdf, /orders/<id>/report.pdf |
In plain words: Calls send
Authorization: Bearer <token> and optionally Accept-Language. Every operation of /sync has a unique uuid and is answered applied, duplicate, rejected or conflict with a code. The module has 130+ automated tests (--test-tags /taqnix_fsm) and the app has unit tests (flutter test).Troubleshooting
| Problem | What to do |
|---|---|
| The app cannot connect | Open https://your-odoo/api/fsm/v1/ping on the phone: it must answer {"ok": true}. Check https, the certificate, the address without a trailing slash and that the module is installed on that database (the right one if you have several: add --db-filter or the dbfilter setting). |
| Sign-in says the account is not a technician | Add the user in Technicians (it gets the group automatically). |
| The technician sees no jobs | The order must be Assigned to that user (not New). Open the order and press Dispatch. |
| No offers appear | Check the team and the skills, the radius and that the technician has a recent location (tracking on) for nearby offers. |
| The map is empty or white | The browser must reach the tile server; set the tile URL in the settings. |
| No timesheet | The technician needs an employee and the project of the settings; see the to-do created for the dispatcher. |
| Parts are not moved | Check the setting When parts are used and that the products are storable; look at Billing → Parts used. |
| The invoice is not emailed | Set up the outgoing mail server in Odoo and check the customer email. |
| No push notifications | Check the Firebase identifiers and the service account in the settings, the APNs key for iPhone, and that the technician allowed notifications. Technicians → Send a notification tells you when nobody could be reached. |
| Location stops in the background | Allow location always and remove battery optimisation for the app on the phone. |
Support
Installation help and bug fixes are included for 6 months, with lifetime updates. Contact us through the marketplace page where you bought the module or write to support@taqnix.com with your Odoo version and a screenshot.