ERP connections API
Manage ERP connections (SoftOne Soft1, Entersoft Business Suite, SAP Business One, and SAP S/4HANA Cloud) programmatically. These endpoints need a sign-in token from POST /auth/login. API keys get 403, and so do driver sign-ins. The task guides are Connect SoftOne or Entersoft, Connect SAP Business One, Connect SAP S/4HANA Cloud, ERP sites and zones, and Visit notes in the ERP. Part of the documentation.
Roles and errors
Base URL: https://filodos.gr/filodos-dashboard/api/scoring. Each request acts on the organization of the sign-in. Another organization's connection id reads 404.
| Endpoint | Admin | Manager |
|---|---|---|
POST /erp/connections, PATCH /erp/connections/{id}, DELETE /erp/connections/{id} | Yes | No (403) |
All other /erp/* endpoints | Yes | Yes |
| Status | Meaning |
|---|---|
401 | No sign-in token, or the token expired. |
403 | The role cannot use the endpoint, or the credential is an API key. |
404 | Unknown connection or site id in your organization. |
422 | A bad value. The detail field tells the reason, for example radius_m must be 25-5000 or not workflow setting(s): app_id. |
502 | The ERP or the map server failed. The detail field tells the reason. |
GET/erp/vendors
Lists the four vendors (softone, entersoft, sap, s4) with their default settings, the connection keys (admin only), the workflow keys, the template placeholders, and the zone types. writeback_example is the proposed SAP activity or S/4HANA note; it is null for SoftOne and Entersoft.
curl https://filodos.gr/filodos-dashboard/api/scoring/erp/vendors \
-H "Authorization: Bearer eyJhbGciOi…"
[{"vendor": "softone", "label": "SoftOne (Soft1)",
"defaults": {"app_id": "", "sites": {"object": "CUSTOMER", …}, "radius_m": 150, …},
"connection_settings": ["app_id", "company", "branch", "module", "refid"],
"workflow_settings": ["sites", "zone_type", "radius_m", "link_devices",
"min_visit_seconds", "note_template", "visit_writeback"],
"template_fields": ["vehicle", "site_key", …], "zone_types": ["depot", "customer", "no-go"]},
{"vendor": "entersoft", …},
{"vendor": "sap", "label": "SAP Business One", "connection_settings": ["company_db"],
"writeback_example": {"entity": "Activities", "key_field": "ActivityCode", …}, …},
{"vendor": "s4", "label": "SAP S/4HANA Cloud", "connection_settings": ["client_id", "token_url"],
"writeback_example": {"entity": "A_BusinessPartnerNote", "key_field": "NoteID", …}, …}]
GET/erp/connections
Lists the connections of the organization, newest first. A row never holds a password. last_sync_status is ok, failed, or null (never synced).
curl https://filodos.gr/filodos-dashboard/api/scoring/erp/connections \
-H "Authorization: Bearer eyJhbGciOi…"
[{"id": 4, "vendor": "softone", "name": "Head office ERP",
"base_url": "https://12345.oncloud.gr/s1services", "username": "filodos-integration",
"settings": {"app_id": "2001", "sites": {…}, "zone_type": "customer", …},
"active": true, "last_sync_at": "2026-10-05T09:00:00+03:00",
"last_sync_status": "ok", "last_error": null, …}]
POST/erp/connections
Admin only. Stores one connection. Body: vendor, name (1–100 characters), base_url (https), username, password, optional subscription_password (Entersoft), and settings. The settings merge onto the vendor defaults. SoftOne needs app_id; Entersoft needs branch_id; SAP needs company_db, and its base_url is the Service Layer root (for example https://sap.example.gr:50000/b1s/v1); S/4HANA needs client_id and token_url, its base_url is the tenant API root, and its client secret is the password. The answer has no password.
curl -X POST https://filodos.gr/filodos-dashboard/api/scoring/erp/connections \
-H "Authorization: Bearer eyJhbGciOi…" \
-H 'Content-Type: application/json' \
-d '{"vendor": "softone", "name": "Head office ERP",
"base_url": "https://12345.oncloud.gr/s1services",
"username": "filodos-integration", "password": "…",
"settings": {"app_id": "2001"}}'
{"id": 4, "vendor": "softone", "name": "Head office ERP", "active": true, …}
PATCH/erp/connections/{id}
Admin only. Changes the connection properties: name, base_url, username, password, subscription_password, active, and settings with connection keys only. Connection keys: SoftOne app_id, company, branch, module, refid; Entersoft branch_id, lang_id, subscription_id; SAP company_db; S/4HANA client_id, token_url. They merge onto the stored settings. A workflow key reads 422. A new password keeps the stored subscription password.
curl -X PATCH https://filodos.gr/filodos-dashboard/api/scoring/erp/connections/4 \
-H "Authorization: Bearer eyJhbGciOi…" \
-H 'Content-Type: application/json' \
-d '{"settings": {"company": "2000"}, "active": false}'
PUT/erp/connections/{id}/workflow
Admins and managers. Replaces the workflow settings: sites, zone_type, radius_m (25–5000), link_devices, min_visit_seconds, note_template, and visit_writeback. A key that you leave out returns to its default. A connection key reads 422. visit_writeback is null (off), {"object", "data": {TABLE: {FIELD: template}}} for SoftOne, {"table_name", "table_id", "title"} for Entersoft, or {"entity", "key_field", "dedupe_field", "fields": {PROPERTY: template}} for SAP and S/4HANA. SAP and S/4HANA sites are {"entity", "filter", "fields"}. SAP and S/4HANA entity and property names must be plain names (letters, digits, _); other names read 422.
curl -X PUT https://filodos.gr/filodos-dashboard/api/scoring/erp/connections/4/workflow \
-H "Authorization: Bearer eyJhbGciOi…" \
-H 'Content-Type: application/json' \
-d '{"sites": {"object": "CUSTOMER", "filters": "CUSTOMER.ISACTIVE=1",
"fields": {"latitude": "CUSEXTRA.NUM01", "longitude": "CUSEXTRA.NUM02"}},
"zone_type": "customer", "radius_m": 150,
"visit_writeback": {"object": "SOACTION",
"data": {"SOACTION": {"TRDR": "{site_key}", "COMMENTS": "{text}"}}}}'
DELETE/erp/connections/{id}
Admin only. Deletes the connection with its site list and its queued notes. The zones stay on the map.
curl -X DELETE https://filodos.gr/filodos-dashboard/api/scoring/erp/connections/4 \
-H "Authorization: Bearer eyJhbGciOi…"
{"id": 4, "deleted": true}
POST/erp/connections/{id}/test
Logs in to the ERP and returns the session: the company and branch for SoftOne, the user and its sites for Entersoft, company_db, company_name, version, and session_timeout_min for SAP, and the token type with its lifetime in seconds for S/4HANA. A refused login or an unreachable ERP reads 502 with the reason.
curl -X POST https://filodos.gr/filodos-dashboard/api/scoring/erp/connections/4/test \
-H "Authorization: Bearer eyJhbGciOi…"
{"id": 4, "vendor": "softone", "ok": true,
"session": {"company": "1000", "company_name": "Μεταφορές Αθηνών ΑΕ",
"branch": "1000", "branch_name": "Αθήνα"}}
POST/erp/connections/{id}/sync
Runs one site sync now and returns the counts. A failure reads 502, and the connection records it in last_sync_status and last_error. An Entersoft connection without a Public Query reads 502 with set the Public Query.
curl -X POST https://filodos.gr/filodos-dashboard/api/scoring/erp/connections/4/sync \
-H "Authorization: Bearer eyJhbGciOi…"
{"id": 4, "created": 3, "updated": 0, "unchanged": 0, "quarantined": 1,
"orphaned": 0, "skipped_rows": 0, "duplicate_keys": 0,
"zones_written": 2, "device_links_added": 4}
POST/erp/connections/{id}/csv-sync
Syncs the sites of a CSV connection from the uploaded file text ({"content": "…"}) and returns the same counts as …/sync. A non-CSV connection, an empty or oversized file, or an unreadable file reads 422. A Traccar failure reads 502 and lands on the connection.
curl -X POST https://filodos.gr/filodos-dashboard/api/scoring/erp/connections/9/csv-sync \
-H "Authorization: Bearer [REDACTED]…" -H "Content-Type: application/json" \
-d '{"content": "key,name,latitude,longitude\n1,Central,37.9838,23.7275\n"}'
{"id": 9, "created": 1, "updated": 0, "unchanged": 0, "quarantined": 0,
"orphaned": 0, "skipped_rows": 0, "duplicate_keys": 0,
"zones_written": 1, "device_links_added": 2}
GET/erp/connections/{id}/sites?status=
Lists the sites of the connection. Optional status: synced (a zone is on the map), quarantined (no valid coordinates), or orphaned (gone from the ERP).
curl https://filodos.gr/filodos-dashboard/api/scoring/erp/connections/4/sites?status=quarantined \
-H "Authorization: Bearer eyJhbGciOi…"
[{"id": 9, "external_id": "3", "code": "C003", "name": "Περίπτερο Ομόνοιας",
"address": "Οδός 1, 10000 Αθήνα", "latitude": null, "longitude": null,
"manual_location": false, "status": "quarantined", "geofence_id": null, …}]
PUT/erp/connections/{id}/sites/{site_id}/location
Sets the location of one site by hand and writes its zone. Body: latitude and longitude. Out of range or 0, 0 reads 422. If the map server fails, the location stays stored, the answer is 502, and the next sync writes the zone.
curl -X PUT https://filodos.gr/filodos-dashboard/api/scoring/erp/connections/4/sites/9/location \
-H "Authorization: Bearer eyJhbGciOi…" \
-H 'Content-Type: application/json' \
-d '{"latitude": 37.9841, "longitude": 23.7281}'
{"id": 9, "status": "synced", "manual_location": true, "geofence_id": 902, …}
GET/erp/connections/{id}/writes?limit=
Lists the newest visit notes (default 50). status is pending, written, or failed; payload holds the template values and the note text; erp_record_id is the id of the ERP record or document.
curl https://filodos.gr/filodos-dashboard/api/scoring/erp/connections/4/writes?limit=20 \
-H "Authorization: Bearer eyJhbGciOi…"
[{"id": 12, "status": "written", "attempts": 1, "erp_record_id": "1000",
"payload": {"vehicle": "ΙΚΥ-1234", "site_name": "Σούπερ Μάρκετ Καλλιθέας",
"date": "05/10/2026", "arrived": "09:42", "departed": "10:05",
"text": "Filodos: το όχημα ΙΚΥ-1234 ήταν στο …"}, …}]