API/Jobs

Creation

API endpoint for creating a new delivery job via an API key.

Dynamic and personnalized code snippets for this endpoint are available on the Logis main-app.

Endpoint

Creates a new job, optionally finding or creating the associated client and handling specific job addresses.

POST Endpoint
https://app.logisapp.ca/api/apikeys/add_order

Authentification

This endpoint requires authentification via a custom API header.

Required Header
LOGIS-API-KEY: YOUR_SECRET_API_KEY

Replace YOUR_SECRET_API_KEY with the actual secret key generated within the Logis application. The request will fail if this header is missing or invalid.

Furthermore, the API key used must have the "Allow Job Creation" permission enabled in the Logis settings.

Request Body

The endpoint expects a JSON payload in the request body with the following structure:

{
  "job": {
    "name": "Deliver urgent documents", // Required
    "deadline": "2025-12-31T17:00:00Z", // Required (ISO 8601 Format, UTC recommended)
    "notes": "Leave with reception if Mr. Smith is unavailable. Handle with care.", // Optional
    "item_count": 1, // Optional (Must be > 0 if provided)
    "do_notify_sms": true, // Optional (Defaults to client's preference, then true)
    "code_secure_deliveries": false // Optional (Defaults to client's preference -> company setting -> false)
  },
  "client": {
    // --- Provide EITHER id OR enough details for matching/creation ---
    "id": "client-uuid-if-known", // Optional: If provided, tries to find this specific client first.
    // --- Fields used for matching/creation if 'id' is omitted or not found ---
    "first_name": "John", // Required if creating
    "last_name": "Doe", // Required if creating
    "phone_number": "+1 555-123-4567", // Optional (Required format: '+1 XXX-XXX-XXXX')
    "email": "john.doe@example.com", // Optional
    "notes": "Preferred contact method: email.", // Optional (Client Notes)
    "do_notify_sms": true, // Optional (Client's general preference)
    "code_secure_deliveries": false // Optional (Client's general preference)
  },
  "address": { // Optional: Provide ONLY if the JOB address differs from the Client's default address OR if creating a client.
    "building_number": 123, // Required if 'address' section is present
    "street_name": "Main St", // Required if 'address' section is present
    "apt_number": "Suite 4B", // Optional
    "city": "Anytown", // Required if 'address' section is present
    "postal_code": "A1B 2C3", // Required if 'address' section is present
    "notes": "Side entrance, use buzzer code #1234." // Optional (Address-specific notes)
  }
}

Fields

Job Object (Required)

FieldTypeRequiredDescription
namestringYesA descriptive name for the job (e.g., "Package Delivery", "Document Pickup"). Max 100 chars.
deadlinestringYesThe date and time by which the job must be completed. Must be in ISO 8601 format (e.g., YYYY-MM-DDTHH:MM:SSZ or YYYY-MM-DDTHH:MM:SS+HH:MM). Cannot be past.
notesstringOptionalAdditional instructions or information relevant to the job itself. Max 1500 chars.
item_countintegerOptionalThe number of items involved in the job. If provided, must be greater than 0.
do_notify_smsbooleanOptionalOverrides client's SMS notification preference for this specific job. Defaults to client.do_notify_sms which itself defaults to true.
code_secure_deliveriesbooleanOptionalOverrides client's preference, requesting a secret code for delivery confirmation. Depends on company settings. Defaults to client → company → false.

Client Object (Required)

This section identifies the end client for the job. The system uses the following logic based on API key settings:

  1. ID Lookup: If id is provided, the system attempts to find an existing EndClient with that UUID belonging to the user associated with the API key.
  2. Auto-Matching: If id is not provided or the client isn't found, and the API key has client matching enabled, the system searches for an existing client matching the provided details.
  3. Auto-Creation: If no client is found via ID or matching, and the API key has client creation enabled, the system attempts to create a new EndClient using the provided details.
FieldTypeRequiredDescription
idstringOptional (UUID)Provide the existing EndClient UUID if known. If provided, other fields (first_name, last_name, phone, email) are mostly ignored unless creation is needed.
first_namestringYes (if creating)Client's first name. Required if id is not provided and auto-creation/matching is needed. Max 100 chars.
last_namestringYes (if creating)Client's last name. Required if id is not provided and auto-creation/matching is needed. Max 100 chars.
phone_numberstringYes (if creating/matching and email is missing)Client's phone number. Must be in format +1 XXX-XXX-XXXX. Used for matching if id is not provided.
emailstringYes (if creating/matching and phone is missing)Client's email address. Used for matching if id is not provided.
notesstringOptionalGeneral notes about the client. Max 1000 chars. Used only during client creation.
do_notify_smsbooleanOptionalClient's general preference for receiving SMS notifications for jobs. Defaults to true. Used only during client creation.
code_secure_deliveriesbooleanOptionalClient's preference for requiring secure delivery codes. Defaults based on the adding user's company setting, then false. Used only during client creation.

To ensure data consistency, it is recommended to send as much data as possible if matching.

Address Object (Optional if not creating client)

This object is used if a client needs to be created (a client must have an associated address). If a client is found or matched, this object will only be used if it differs from the client's default address, thus overriding this specific job's delivery address.

You can send this job with every request for safety purposes.

FieldTypeRequired (if address object present)Description
building_numberintegerYesThe street number of the address.
street_namestringYesThe name of the street. Max 250 chars.
apt_numberstringOptionalApartment, suite, unit number, etc. Max 50 chars.
citystringYesThe city name. Max 100 chars.
postal_codestringYesThe postal or zip code. Max 20 chars.
notesstringOptionalSpecific notes for this address (e.g., gate code, delivery instructions). Max 1000 chars.

Success Response

{
  "job": {
    "id": "job-uuid-generated-by-server",
    "name": "Deliver urgent documents",
    "notes": "Leave with reception if Mr. Smith is unavailable. Handle with care.",
    "item_count": 1,
    "client": "client-uuid-resolved-or-created",
    "deadline": "2025-12-31T17:00:00Z",
    "original_deadline": "2025-12-31T17:00:00Z", // Set automatically
    "started_at": null,
    "completed_at": null,
    "created_at": "2025-04-09T12:30:00Z", // Server timestamp
    "status": "CREATED", // Initial status
    "route": null,
    "order": null,
    "rating_delivery": null,
    "rating_job": null,
    "rating_comment": null,
    "do_notify_sms": true,
    "code_secure_deliveries": false,
    // secret_delivery_code is excluded from serializer
    "delivery_code_retrieved": false,
    "delivery_proof": null,
    "address": "address-uuid-used-for-job", // ID of the address used
    "address_detail": { // Nested address object
      "id": "address-uuid-used-for-job",
      "building_number": 123,
      "street_name": "Main St",
      "apt_number": "Suite 4B",
      "city": "Anytown",
      "postal_code": "A1B 2C3",
      "notes": "Side entrance, use buzzer code #1234.",
      "latitude": 45.12345,
      "longitude": -73.98765,
      "added_by": "store-owner-user-uuid"
    }
  },
  "client": {
    "id": "client-uuid-resolved-or-created",
    "first_name": "John",
    "last_name": "Doe",
    "phone_number": "+1 555-123-4567",
    "email": "john.doe@example.com",
    "created_at": "2025-04-09T12:29:00Z", // If newly created
    "is_active": true,
    "notes": "Preferred contact method: email.",
    "do_notify_sms": true,
    "added_by": "store-owner-user-uuid",
    "code_secure_deliveries": false,
    "address": "client-default-address-uuid",
    "address_detail": {
      "id": "client-default-address-uuid",
      // ... client's default address fields ...
    }
  }
}

Upon creation an SMS will be sent to the client's phone number with a link to track their order on Logis' public tracking page

If possible, it is recommended to store and associate the passed client uuid for further orders by this client, to guarantee data consistency.

Error Responses

Status CodeError Code / ReasonDescription
400 Bad RequestMissing Sections (job, client)The top-level job or client object was missing from the request body.
400 Bad RequestInvalid Data (e.g., invalid deadline)Data within the job, client, or address objects failed validation (e.g., past deadline, bad format).
400 Bad RequestInvalid Address (address creation failed)Geocoding or validation failed for the provided address object.
401 UnauthorizedMissing LOGIS-API-KEY headerThe required API key header was not included.
403 ForbiddenInvalid/Inactive LOGIS-API-KEYThe provided API key is not valid or is inactive.
403 ForbiddenPermission Denied (allow_job_creation)The API key used does not have permission to create jobs.
404 Not FoundClient ID Not FoundA client.id was provided, but no matching client was found for the API key's user.
412 Precondition FailedClient Not Found & Auto-Create OffNo client id provided, no matching client found, and auto_create_clients is disabled for the API key.

Code Example

import 'package:http/http.dart' as http;
class LogisService {
  static String baseUrl = 'https://app.logisapp.ca/api/';
  static String fullUrl = '${baseUrl}apikeys/';
  static Future<List<dynamic>> registerOrder(Map<String, dynamic> sentData) async {
    
    final response = await http.post(
      Uri.parse('${fullUrl}add_order'),
      headers: {
        'Content-Type' : 'application/json',
        'LOGIS-API-KEY' : SECRET_KEY,
      },
      body: json.encode(sentData),
    );
 
    Map<String, dynamic> body = json.decode(respone.body);
 
    if (response.statusCode == 201){
      Map<String, dynamic> jobData = body['job']; // The delivery job as it was created.
      Map<String, dynamic> clientData = body['client']; // Each delivery job has an associated client. Tip: use the ID sent for consistency!
      
      // Parse the data here, for example, assuming you have a Job and Client class:
 
      Job job = Job.fromJson(jobData);
      Client client = Client.fromJson(clientData);
 
      return [job, client]; // And use them in your front end, or store them in your database!
    }
 
    debugPrint('LogisService API error: ${body['error']}'); // Log the error for easy bugfixing.
    throw Exception(body['error']);
    
  }
}

On this page