Create booking

Creates one or more new bookings in Sodtrack.

POST/api/integration/booking/v2

Request

cURL
curl -X POST "https://dev.integration.cl.sodtrack-shared.sodtrack.com/api/integration/booking/v2" \
  -H "Authorization: Bearer $SODTRACK_TOKEN" \
  -H "origin: <your-origin>"

Base URL: https://dev.integration.cl.sodtrack-shared.sodtrack.com · other environments

Headers

NameTypeDescription
originstring

Responses

Create booking
{
  "bookings": [
    {
      "id": 302,
      "quantity": 1,
      "variantId": 2,
      "variantSku": [
        "8472"
      ]
    }
  ]
}

Error responses for this endpoint follow the shared error reference.

Purpose

Creates one or more new bookings in Sodtrack.

This endpoint supports batch creation, allowing a single request to include multiple services in the data array.

When multiple service entries are provided, Sodtrack automatically determines whether they can be grouped under a single provider and appointment slot.

If grouping is not possible (due to scheduling, coverage, or provider constraints), individual ungrouped bookings will be created.

Bookings can be created in a specific project: you can send a project identifier (project), optionally with a shopping cart within that project (project.shoppingCart), or a root-level shopping cart id (shoppingCartId) for compatibility. When project is present, it takes precedence and the shopping cart is resolved from the project (see Project and shopping cart resolution in Business Rules).

Each service line can optionally include one or more products (data[].products) to associate physical items with the booking (for example, the appliance being installed or delivered). Product resolution adapts to your Sodtrack configuration and to the service variant type (see Product resolution in Business Rules).


Field Definitions

🧍 Customer

FieldTypeRequiredDescription
customerobjectCustomer or requester information.
customer.namestringCustomer's first name.
customer.lastNamestringCustomer's last name.
customer.identificationNumberstringNational ID or tax identification number.
customer.identificationNumberCountrystringISO 3166-1 alpha-2 country code for the identification number.
customer.phoneNumberstringContact phone number in international format.
customer.emailstringCustomer's email address.
customer.referencestringExternal reference of the customer.

If customer is new, one of email, reference or identification numbers should be provided, in order to generate a temporary email for that customer


🧍 Stakeholders

FieldTypeRequiredDescription
stakeholdersarray[object]Stakeholder who requested the booking. Only the first element is used and is applied to all created bookings.
stakeholders[].stakeholderIdstringLink to an existing Sodtrack stakeholder by id. When provided, other fields are not required.
stakeholders[].namestring✅ when creating newStakeholder's first name (required when creating a new stakeholder, i.e. when stakeholderId is omitted).
stakeholders[].lastNamestringStakeholder's last name.
stakeholders[].identificationNumberstringNational ID or tax identification number.
stakeholders[].identificationNumberCountrystringISO 3166-1 alpha-2 country code for the identification number.
stakeholders[].phoneNumberstringContact phone number in international format.
stakeholders[].emailstringStakeholder's email address.
stakeholders[].referencestringExternal reference of the stakeholder.

If stakeholder is new, one of email, reference or identification number should be provided.


🏠 Address

FieldTypeRequiredDescription
addressobjectPhysical service address (destination).
address.addressstringMain address or street. Omitted only if coordinates are provided; otherwise required for geocoding.
address.extraInfostringAdditional address details (e.g., apartment, suite number).
address.coordinateobjectOptional geographic coordinates of the service location.
address.coordinate.latnumberLatitude.
address.coordinate.lngnumberLongitude.
address.associateToCustomerbooleanWhether the address should be stored and associated to the customer for reuse. Defaults to true when omitted.

If coordinates are not provided, Sodtrack attempts to geocode the address automatically when geo-reference is part of your subscription.
If geocoding fails, the booking will be created without a map location and must be manually geolocated by an administrator before provider assignment.


🏠 Origin address

FieldTypeRequiredDescription
originAddressobjectOrigin address where the booking starts (e.g. pick-up, depot).
originAddress.addressstringOrigin address or street.
originAddress.extraInfostringAdditional address details (e.g., apartment, suite number).
originAddress.coordinateobjectOptional geographic coordinates of the origin location.
originAddress.coordinate.latnumberLatitude.
originAddress.coordinate.lngnumberLongitude.
originAddress.associateToCustomerbooleanWhether the origin address should be stored and associated to the customer. Defaults to false when omitted.

If coordinates are not provided, Sodtrack attempts to geocode the address automatically when geo-reference is part of your subscription.
If geocoding fails, the booking will be created without a map location and must be manually geolocated by an administrator before provider assignment.


🧩 Booking Data

FieldTypeRequiredDescription
dataarray[object]One or more service items to be booked. Each element represents a booking unit.
data[].variantobjectDefines the main service variant.
data[].variant.typestringType of variant identifier: "variantId" or "variantSku".
data[].variant.valuestringIdentifier corresponding to the selected variant.
data[].variant.quantitynumberQuantity of the main variant requested.
data[].variant.pricenumberPrice paid by the customer (for integrations that include pricing).
data[].variant.costnumberCost paid to the provider.
data[].addonsarray[object]Optional list of additional variants (add-ons).
data[].addons[].typestring✅ when addon sentAdd-on identifier type: "addonId" or "addonReference".
data[].addons[].valuestring✅ when addon sentAdd-on identifier value.
data[].addons[].quantitynumber✅ when addon sentQuantity of the add-on.
data[].addons[].pricenumberPrice charged to the customer for the add-on.
data[].addons[].costnumberCost paid to the provider for the add-on.
data[].productsarray[object]Optional list of physical products to associate with the booking. See Product resolution in Business Rules.
data[].products[].typestring✅ when product sentProduct identifier type: "productSku" or "productId".
data[].products[].valuestring✅ when product sentProduct identifier value: the SKU string, or the product id as a string when type is "productId".
data[].products[].quantitynumber✅ when product sentQuantity of the product. Integer between 1 and 30.
data[].products[].serialNumberstringSerial number of a specific product unit. Applies only to variants linked to products, and only when quantity is 1.
data[].products[].deliveryDatestring (ISO 8601)Promised delivery date for the product. Interpreted in your instance's timezone.
data[].transportobjectOptional transport-related charges.
data[].transport.pricenumberPrice charged to the customer.
data[].transport.costnumberCost allocated to the provider.
data[].dynamicFormsarray[object]Optional form data collected as part of the booking (if configured in Sodtrack).
data[].dynamicForms[].formReferencestring✅ when form sentForm reference identifier.
data[].dynamicForms[].valuesobject✅ when form sentKey-value map of submitted field data.

When multiple items are included in the data array (length > 1), Sodtrack automatically determines whether they can be grouped under a single booking (same provider/date).

If grouping is not possible, individual bookings are created for each service item.


🕒 Date Assignment

FieldTypeRequiredDescription
dateAssignmentobjectDefines how the booking date is determined. See Date assignment in Business Rules.
dateAssignment.typestring✅ when object sentOne of: "direct", "user_scheduling", "userScheduling", "onDemand", "providerScheduling".
dateAssignment.datestring (ISO 8601)Date and time for the booking. Required for scheduling when type is "direct".
dateAssignment.timeRangeobjectTime range within the day (used with type = "direct" when applicable).
dateAssignment.timeRange.typestring✅ when timeRange sent"timeRangeId" or "timeRangeIndex".
dateAssignment.timeRange.valuenumber✅ when timeRange sentIdentifier or index of the time range.

👷 Provider Assignment

FieldTypeRequiredDescription
providerAssignmentobjectDefines how the provider or technician is assigned. See Booking or bundle scheduling logic in Business Rules.
providerAssignment.typestring✅ when object sent"automatic" or "direct".
providerAssignment.providerobjectRequired when type is "direct". Specifies the provider when manually assigned.
providerAssignment.provider.typestring✅ when provider sent"providerId" or "providerReference".
providerAssignment.provider.valuestring✅ when provider sentID or external reference of the provider.

📣 Sales channel

Identifies which sales / integration channel the bookings belong to. The channel must exist and be configured in Sodtrack.

FieldTypeRequiredDescription
saleChannelobjectIdentifies the channel by reference or by internal id. See nested fields below.
saleChannel.typestring✅ when saleChannel sentOne of: "reference" (lookup by channel reference, e.g. E001) or "id" (lookup by Sodtrack numeric id).
saleChannel.valuestring✅ when saleChannel sentValue for the chosen type: the channel reference string, or the channel id as a string (e.g. "1"). For type: "id", the value must be a positive integer as string (decimals are rejected).

📁 Project (optional)

FieldTypeRequiredDescription
projectobjectProject where the bookings will be created. When provided, Sodtrack resolves the project and then the shopping cart (see Project and shopping cart resolution). Takes precedence over root-level shoppingCartId when both are sent.
project.typestring✅ when project sentType of project identifier: "projectId" or "projectReference".
project.valuestring✅ when project sentInternal Sodtrack project ID, or external reference of the project.
project.shoppingCartobjectOptional. Target a specific shopping cart within the project (by ID or reference). When omitted, the latest shopping cart of the project is used, or a new one is created.
project.shoppingCart.typestring✅ when shoppingCart sentHow the cart is identified: "shoppingCartId" or "shoppingCartReference".
project.shoppingCart.valuestring✅ when shoppingCart sentShopping cart ID (numeric as string) or external reference of the cart within the project.

🧾 Additional Metadata

FieldTypeRequiredDescription
referencestringExternal system reference (e.g., order ID).
createPaymentTransactionbooleanIf true, creates a payment transaction for each created booking.
useStrictCoverageValidationModebooleantrue: all-or-nothing validation (default). false: best-effort mode; only valid bookings are created. See Coverage Validation Behavior.

Example Request (with project)

json
{
  "customer": {
    "name": "María",
    "lastName": "García",
    "identificationNumber": "12345678-9",
    "identificationNumberCountry": "CL",
    "phoneNumber": "+56912345678",
    "email": "maria.garcia@example.com"
  },
  "address": {
    "address": "Av. Providencia 1234, Santiago",
    "extraInfo": "Depto 501",
    "coordinate": {
      "lat": -33.43324794409109,
      "lng": -70.58645659063548
    }
  },
  "data": [
    {
      "variant": {
        "type": "variantSku",
        "value": "install_curtains_sku",
        "quantity": 2,
        "price": 150000,
        "cost": 80000
      }
    }
  ],
  "dateAssignment": {
    "type": "direct",
    "date": "2025-03-15T09:00:00.000Z"
  },
  "providerAssignment": {
    "type": "direct",
    "provider": {
      "type": "providerId",
      "value": "42"
    }
  },
  "reference": "ORD-2025-001",
  "saleChannel": {
    "type": "id",
    "value": "1"
  },
  "project": {
    "type": "projectReference",
    "value": "PROJ-EXT-100"
  },
  "useStrictCoverageValidationMode": true
}

Example Request (with project and specific shopping cart)

json
{
  "customer": { "name": "María", "lastName": "García", "email": "maria@example.com" },
  "address": { "address": "Av. Providencia 1234, Santiago", "coordinate": { "lat": -33.43, "lng": -70.58 } },
  "data": [{ "variant": { "type": "variantSku", "value": "install_curtains_sku", "quantity": 1 } }],
  "saleChannel": {
    "type": "id",
    "value": "1"
  },
  "project": {
    "type": "projectReference",
    "value": "PROJ-EXT-100",
    "shoppingCart": {
      "type": "shoppingCartReference",
      "value": "STAGE-ORDER-2025-001"
    }
  }
}

When no cart exists in the project with reference STAGE-ORDER-2025-001, Sodtrack creates a new shopping cart with that reference and attaches the bookings to it.

Example Request (minimal)

json
{
  "customer": {
    "name": "Juan Pérez"
  },
  "address": {
    "address": "Calle Principal 100, Ciudad"
  },
  "data": [
    {
      "variant": {
        "type": "variantId",
        "value": "321",
        "quantity": 1
      }
    }
  ],
  "saleChannel": {
    "type": "id",
    "value": "1"
  },
}

Example Request (minimal with saleChannel by reference)

json
{
  "customer": {
    "name": "Juan Pérez"
  },
  "address": {
    "address": "Calle Principal 100, Ciudad"
  },
  "data": [
    {
      "variant": {
        "type": "variantId",
        "value": "321",
        "quantity": 1
      }
    }
  ],
  "saleChannel": {
    "type": "reference",
    "value": "ref1"
  },
}

Example Request (with products)

json
{
  "customer": {
    "name": "María",
    "lastName": "García",
    "email": "maria.garcia@example.com"
  },
  "address": {
    "address": "Av. Providencia 1234, Santiago"
  },
  "data": [
    {
      "variant": {
        "type": "variantSku",
        "value": "install_appliance_sku",
        "quantity": 1
      },
      "products": [
        {
          "type": "productSku",
          "value": "WASHER-XYZ-500",
          "quantity": 1,
          "serialNumber": "SN-998877",
          "deliveryDate": "2026-03-15"
        }
      ]
    }
  ],
  "saleChannel": {
    "type": "id",
    "value": "1"
  }
}

Response Example

json
{
  "bookings": [
    {
      "id": 10452,
      "quantity": 2,
      "variantSku": ["install_curtains_sku"],
      "variantId": 321
    }
  ]
}

Response Fields

FieldTypeDescription
bookingsarray[object]List of created bookings.
bookings[].idnumberUnique Sodtrack booking ID.
bookings[].quantitynumberQuantity of services booked.
bookings[].variantSkuarray[string]List of variant SKUs associated with the booking.
bookings[].variantIdnumberInternal variant identifier.

Error Responses

HTTP StatusErrorDescription
400 Bad RequestInvalidParametersOne or more required fields are missing or invalid.
400 Bad RequestINVALID_SALES_CHANNELThe given saleChannel was not found (in strict mode).
401 UnauthorizedAuthentication token missing or expired.
403 ForbiddenThe API key or origin is not authorized.
404 Not FoundA referenced variant, provider, project, or channel could not be found.
500 Internal Server ErrorUnexpected server error. Contact Sodtrack support.

Business Rules & Constraints

Project and shopping cart resolution

You can target a project and optionally a shopping cart within it, or use a root-level shopping cart id for compatibility.

  • project (without project.shoppingCart): Send a project identifier (projectId or projectReference). Sodtrack resolves the project and then uses the latest shopping cart linked to that project. If the project has no shopping cart, a new shopping cart is created for that project and the bookings are attached to it.
  • project with project.shoppingCart: In addition to the project, you can target a specific cart within that project:
    • type = "shoppingCartId": Sodtrack looks up the shopping cart by project and cart ID. If no cart is found with that ID in the project, it falls back to the latest shopping cart of the project.
    • type = "shoppingCartReference": Sodtrack looks up the shopping cart by project and cart reference. If no cart is found with that reference, it creates a new shopping cart for the project with the given reference (and uses it for the bookings). The new cart’s stage name is derived from the project name and the reference.

When project is not sent, Sodtrack creates the bookings without attaching them to a project; further behavior depends on your configuration.


Date assignment

When dateAssignment is sent, type determines how the booking date is handled. Scheduling (assigning date and provider) only runs when both dateAssignment and providerAssignment are present and the system can complete the assignment (see Booking or bundle scheduling logic).

  • direct: The booking is scheduled to a specific date and time. date is required when scheduling is performed (ISO 8601). Optionally, timeRange can be sent to specify a time slot within the day by timeRangeId or timeRangeIndex. If date is missing when the system attempts to schedule, the scheduling step is skipped and the information is stored in a note on the booking.
  • userScheduling: The user will choose the date later (e.g. via web or app). No immediate date is assigned. userScheduling is the preferred value; date and timeRange are not used for scheduling when this type is set.
  • onDemand: The service is on-demand; date assignment is handled accordingly by the platform. date and timeRange are not used for direct scheduling.
  • providerScheduling: The provider will determine or propose the date to the client. No immediate date is assigned from the request. date and timeRange are not used for direct scheduling.

When date definition cannot be completed (e.g. address not geo-referenced, or provider assignment missing/failed), Sodtrack still creates the bookings and stores the scheduling information in a note so it is not lost.


Address resolution process

If no valid coordinates are available for address, and for originAddress when provided, bookings remain unassigned until manually updated.

Provided addresses go through a resolution process to determine coordinates depending on the associateToCustomer value and whether the geo-reference intent is part of your subscription.

When geo-reference intent is not part of your subscription:

The system does not call the partner geocoding API. Addresses are used as provided; coordinates remain unchanged. Bookings that require coverage validation follow the non-georeferenced flow (see Strict mode / Best effort mode).

When geo-reference intent is part of your subscription:

If no coordinates are provided for the address, the system uses the address attribute of the provided address object and requests a match with coordinates from a partner API.

  • If exactly one match is returned, the system uses those coordinates for all subsequent validation steps, including the associateToCustomer = true step.
  • If no match is returned or the partner API errors, the address remains without coordinates; resolution does not retry and the request continues with the unresolved address.

When associateToCustomer = true:

If the provided customer already exists, the platform attempts to find an existing address for that customer and reuse it. Address matching requires exact match of extraInfo (after normalization: trim, null/undefined treated as empty) and at least one of the following:

  • The address attribute of the provided address equals the existing address's address.
  • The provided coordinates are within a 3 meter radius of the existing address's coordinates.

If a matching existing address is found, its coordinates and address fields are used for coverage and validations. If not, the address is created or updated as provided (and optionally geocoded when geo-reference intent is enabled).

Defaults for address association:

  • Destination address: associateToCustomer defaults to true when omitted.
  • Origin address: associateToCustomer defaults to false when omitted.

Booking bundling logic

When the bundling capability is part of your subscription and multiple bookings are created in a single request, Sodtrack validates and creates a single bundle when possible. Bundling is all-or-nothing: the criteria must be satisfied for all created bookings in the request for a bundle to be created.

Bundling validation rules:

  • The provided address has coordinates after the address resolution process.
  • At least one technician is correctly configured to execute all bookings at that address.

If bundle creation fails (e.g. validation or provider constraints) bookings are still created and returned, and scheduling or note creation still runs.


Product resolution

Each service line (data[]) can include a products array to associate physical products with the booking. How each product is resolved depends on your Sodtrack configuration and on the service variant type.

Where products are resolved

  • When the product module is part of your subscription: products are resolved against the product module (inventory) by SKU or product id.
  • Otherwise: products are resolved against your Sodtrack product catalog by SKU or product id.

Variants that track individual units

Some service variants are configured to track individual product units (units identified by a serial number). For these variants:

  • The product module must be part of your subscription; otherwise the request is rejected with 400 Bad Request.
  • serialNumber may be provided to link a specific unit, and only when quantity is 1. Sending serialNumber with quantity greater than 1 is rejected with 400 Bad Request.
  • When quantity is greater than 1, Sodtrack creates one booking per unit.
  • The same serialNumber cannot be repeated within a single line's products.

Resolution outcomes

ScenarioBehavior
Product found (variant without unit tracking)The product is attached to the booking, together with its deliveryDate when provided.
Product not found (variant without unit tracking)The booking is still created; a note with the product details is added for manual handling.
Product not found (unit-tracking variant)The request is rejected with 400 Bad Request.
serialNumber provided and foundThe specific product unit is linked to the booking.
serialNumber provided but not foundThe booking is created without the unit; a note is added so the unit can be linked later.
Invalid deliveryDateThe request is rejected with 400 Bad Request.

Note creation for unresolved products is independent of useStrictCoverageValidationMode: for variants without unit tracking, an unresolved product never aborts the request; the booking is created and the product information is preserved in a note.

Delivery date

deliveryDate is optional. When provided, it is interpreted using your Sodtrack instance's timezone and stored as the product's promised delivery date. An unparseable date rejects the request with 400 Bad Request.


Booking or bundle scheduling logic

Scheduling a booking (or the head of a bundle) requires both dateAssignment and providerAssignment in the request when the system is able to assign date and provider (see below).

When the date definition for a booking or bundle cannot be completed or fails, and dateAssignment was provided, Sodtrack creates a note on that booking with the scheduling information so it is not lost. This happens when:

  • providerAssignment is missing.
  • providerAssignment was provided but date/provider assignment fails (e.g. no availability for the given technician).
  • The destination address is not geo-referenced (no coordinates after resolution).
  • originAddress is provided and is not geo-referenced (no coordinates after resolution).

In all of the above cases, bookings are already created; only the assignment step is skipped and replaced by the note.


Coverage Validation Behavior

The behavior of the booking creation flow depends on two factors:

  1. Whether the required addresses were successfully resolved with coordinates.
  2. The configured mode (useStrictCoverageValidationMode).

1. When Coordinates Are NOT Resolved

If a required address (destination and/or origin, depending on the variant rules) is not resolved with coordinates:

  • Coverage validations are not executed.
  • Bookings are still created.
  • These bookings are expected to be managed later through the web administrator.

This behavior is the same in both Strict and Best Effort modes.
The selected mode does not affect this scenario.

Bookings created without address coordinates will require manual resolution and add operational overhead for each case.


2. When Coordinates ARE Resolved

If the required addresses are successfully resolved with coordinates, full validation is executed (variant existence, operation areas, coverage by destination/origin when required, addons, etc.).

At this point, the behavior depends on the selected mode.


Strict Mode

useStrictCoverageValidationMode: true (default)

  • All-or-nothing behavior.
  • If any validation fails (for example, no coverage for a georeferenced address):
    • No bookings are created.
    • The request returns a 400 error.
  • No partial creation is allowed.

This mode guarantees that:

  • All requested variants exist.
  • All variants have an operation area.
  • Georeferenced addresses have coverage when required.
  • Addons are valid, applicable and have coverage.

If any of these conditions fail, the entire request is rejected.

This mode mirrors the creation through the administrator web UI, preventing the creation of bookings that could not be satisfied with the current state of configurations.


Best Effort Mode

useStrictCoverageValidationMode: false

  • Partial success is allowed.
  • Validation and coverage checks are executed, but failures do not abort the entire request.

When coordinates are resolved:

  • If a variant does not exist → it is skipped.
  • If a variant has no operation area → it is skipped.
  • If a variant has no coverage → that booking may be skipped.
  • If an addon does not exist or has no coverage → it is not added to the booking.
  • The process continues with all other valid lines.

Only successfully created bookings are returned in the response.

This mode allows the consumer to create as many valid bookings and their addons as possible, even if there is no coverage and operational overhead will be needed to handle some cases.


Conceptual Summary

Coordinates Resolved?Strict ModeBest Effort Mode
❌ NoBookings are created without coverage validationBookings are created without coverage validation
✅ YesIf any validation fails, nothing is createdOnly valid bookings are created

Stakeholder

  • Optional stakeholders array; only the first element is used and is applied to all created bookings.
  • Link existing: If stakeholderId is provided, Sodtrack resolves it. If the stakeholder is not found, an error is logged and no stakeholder is set on the bookings; the request is not aborted (strict and best effort).
  • Create new: If stakeholderId is omitted but identifying data (e.g. name) is provided, a new stakeholder is created and its ID is used for all created bookings.

Data and format

  • Dynamic form data is stored and linked to each booking for later retrieval.
  • All timestamps follow the ISO 8601 format (UTC).