DOCUMENTATION

Client integration guide

Connect a booking website, CRM, or scheduling system to the business API. Your integration runs on your server and uses a scoped API key; never ship that key in a public webpage or mobile bundle. Endpoint reference.

1. Obtain access

Ask a business administrator to create an API key with only the needed scopes and supply the business UUID through a secure channel. Store the key as a server-side secret. All examples below use placeholders; replace IDs with records from your own business.

export ROUTE_API='https://route-api.okok.space'
export ROUTE_BUSINESS_ID='11111111-1111-4111-8111-111111111111'
# Set ROUTE_API_KEY securely in your process environment.
curl "$ROUTE_API/api/v1/businesses/$ROUTE_BUSINESS_ID/orders?view=planning" \
  --header "Authorization: Bearer $ROUTE_API_KEY"
Workflow API-key scopes
Read/create/update orders orders.read, orders.write
Warehouses, vehicles, and map resources resources.read, resources.write
Custom-field schemas settings.read, settings.write
Driver accounts and membership actions accounts.manage
Read/run/edit/publish planning planning.read, planning.run, planning.edit, planning.publish as needed
Availability and reservation confirmation availability.query, reservations.confirm
Evidence evidence.read, evidence.manage
Webhook subscriptions integrations.manage
Graph scenarios scenarios.read, scenarios.write

An operational action may require multiple scopes; for example coverage proposals need access to resources and orders. Each reference page lists its context. Account login, verification, and business ownership are not client-key provisioning shortcuts.

2. Create an order for later planning

POST an order with type, location, duration, and a complete time window. Add custom values only for fields defined by the business’s current schema.

curl --request POST "$ROUTE_API/api/v1/businesses/$ROUTE_BUSINESS_ID/orders" \
  --header "Authorization: Bearer $ROUTE_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{"id":"job-1001","type":"task","location":{"latitude":52.2297,"longitude":21.0122},"duration_seconds":1800,"window_start":"2026-11-02T09:00:00Z","window_end":"2026-11-02T12:00:00Z","custom_fields":{}}'

The order begins Created and unplanned. Omit id to generate one; a duplicate ID in this business returns 409. This direct flow is independent of reservation-based booking. Do not create an order first when using the reservation-confirmation flow below.

3. Check customer-selected appointment windows

POST /api/v1/businesses/{id}/availability with the search bounds, location, service duration, and candidate windows:

{
  "start": "2026-11-02T08:00:00Z",
  "end": "2026-11-02T16:00:00Z",
  "location": {"latitude": 52.2297, "longitude": 21.0122},
  "duration_seconds": 1800,
  "candidate_windows": [
    {"start": "2026-11-02T09:00:00Z", "end": "2026-11-02T10:00:00Z"},
    {"start": "2026-11-02T13:00:00Z", "end": "2026-11-02T14:00:00Z"}
  ],
  "schedule_lock": false,
  "assignment_lock": false
}

The response returns those windows in the same order, with available and a reservation_id for an available choice. Full service must fit inside the window, with feasible travel and fleet constraints. Unavailable choices do not have a usable reservation ID. The system considers eligible vans across this business; service zones are future scope.

The two locks control whether existing planned times/order and vehicle/driver assignments may be rearranged. Both default false. Querying alternatives does not publish or save changed routes.

To discover windows instead, omit candidate_windows and send gap_seconds. Returned window length is service duration plus gap. A gap of zero makes the window as long as the service itself.

4. Confirm exactly one choice

POST /api/v1/businesses/{id}/reservations/{offer}/confirm using the selected reservation ID and remaining order details:

{"id":"booking-1002","custom_fields":{}}

Successful confirmation atomically creates and schedules one order. It consumes the selected offer and invalidates the other alternatives for that request; conflicting offers from other customers cannot both confirm against the same capacity. Other nonconflicting capacity may remain available, including another vehicle at the same clock time.

Treat an offer as a temporary alternative, not a guaranteed customer booking. Several customers may see the same slot until one confirms. Offers expire no later than 24 hours after issuance and earlier when their window passes or conflicting capacity is confirmed. Handle 409 by requesting fresh availability. A failed order creation leaves still-valid offers available until their normal expiry.

Confirmation books capacity immediately, but resulting route changes remain in planning mode until publication. Your client can choose whether it reads planning data or only published data; make that choice visible to your own operators.

5. Run planning and publish

POST /api/v1/businesses/{id}/planning/preview:

{
  "vehicle_ids": ["van-01"],
  "date_start": "2026-11-02",
  "date_end": "2026-11-02",
  "include_planned": false,
  "schedule_lock": false,
  "assignment_lock": false
}

The 202 response contains job_id. Poll /planning/jobs/{job} in the same business. Use current vehicle/driver/warehouse and working-hour setup. A failed run without a usable result preserves the prior planning version.

Read /plans?view=planning, review warnings and revisions, then POST /plans/publish:

{
  "plan_ids": ["plan-01"],
  "expected_revision": [{"id":"plan-01","revision":1}],
  "acknowledge_warnings": false
}

Use actual returned revisions. A 409 requires refreshing and resolving the conflict. Set warning acknowledgement only after an operator reviewed the indicated violations. Publication sends changes to drivers. Published-version receipt is different from task completion.

6. Receive events safely

Create a webhook subscription with a destination HTTPS URL, event names, an active flag, and a private shared secret. Subscribing to * receives all supported business event types. Read the event journal with /events for reconciliation and actual event names rather than inventing event types.

Your receiver should verify the X-Route-Signature, durably store the event, return a 2xx response, and process asynchronously. Deliveries can repeat; deduplicate using the event ID. The event envelope includes planning/published state so your client can select the appropriate view. Retry delivery is bounded; monitor your receiver and use the journal to reconcile missed events.

The signature header is t=TIMESTAMP,v1=HEX_DIGEST. The digest is HMAC-SHA256 over the timestamp, a dot, and the exact raw request-body bytes using your webhook secret. Verify with a constant-time comparison and your receiver’s timestamp tolerance. Do not reserialize JSON before checking the digest. See webhook implementation notes for a complete verifier.

7. Changes and deleted history

Use supported record-status/search filters to retrieve deleted records; deletion is soft deletion. An order made unplanned by an accepted hours change immediately releases its reserved capacity, even if drivers still see an older published route. Administrators must resolve such conflicts; the integration must not silently cancel driver work or assume automatic replanning occurred.

Keep order IDs, selected business, reservation IDs, plan revisions, and webhook event IDs in your client’s audit trail. Do not log bearer tokens, customer signatures, raw evidence images, or activation codes.