Create booking
Creates one or more new bookings in Sodtrack.
/api/integration/booking/v2Request
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
| Name | Type | Description |
|---|---|---|
origin | string | — |
Responses
{
"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
| Field | Type | Required | Description |
|---|---|---|---|
customer | object | ✅ | Customer or requester information. |
customer.name | string | ✅ | Customer's first name. |
customer.lastName | string | ❌ | Customer's last name. |
customer.identificationNumber | string | ❌ | National ID or tax identification number. |
customer.identificationNumberCountry | string | ❌ | ISO 3166-1 alpha-2 country code for the identification number. |
customer.phoneNumber | string | ❌ | Contact phone number in international format. |
customer.email | string | ❌ | Customer's email address. |
customer.reference | string | ❌ | External 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
| Field | Type | Required | Description |
|---|---|---|---|
stakeholders | array[object] | ❌ | Stakeholder who requested the booking. Only the first element is used and is applied to all created bookings. |
stakeholders[].stakeholderId | string | ❌ | Link to an existing Sodtrack stakeholder by id. When provided, other fields are not required. |
stakeholders[].name | string | ✅ when creating new | Stakeholder's first name (required when creating a new stakeholder, i.e. when stakeholderId is omitted). |
stakeholders[].lastName | string | ❌ | Stakeholder's last name. |
stakeholders[].identificationNumber | string | ❌ | National ID or tax identification number. |
stakeholders[].identificationNumberCountry | string | ❌ | ISO 3166-1 alpha-2 country code for the identification number. |
stakeholders[].phoneNumber | string | ❌ | Contact phone number in international format. |
stakeholders[].email | string | ❌ | Stakeholder's email address. |
stakeholders[].reference | string | ❌ | External reference of the stakeholder. |
If stakeholder is new, one of email, reference or identification number should be provided.
🏠 Address
| Field | Type | Required | Description |
|---|---|---|---|
address | object | ✅ | Physical service address (destination). |
address.address | string | ❌ | Main address or street. Omitted only if coordinates are provided; otherwise required for geocoding. |
address.extraInfo | string | ❌ | Additional address details (e.g., apartment, suite number). |
address.coordinate | object | ❌ | Optional geographic coordinates of the service location. |
address.coordinate.lat | number | ❌ | Latitude. |
address.coordinate.lng | number | ❌ | Longitude. |
address.associateToCustomer | boolean | ❌ | Whether 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
| Field | Type | Required | Description |
|---|---|---|---|
originAddress | object | ❌ | Origin address where the booking starts (e.g. pick-up, depot). |
originAddress.address | string | ❌ | Origin address or street. |
originAddress.extraInfo | string | ❌ | Additional address details (e.g., apartment, suite number). |
originAddress.coordinate | object | ❌ | Optional geographic coordinates of the origin location. |
originAddress.coordinate.lat | number | ❌ | Latitude. |
originAddress.coordinate.lng | number | ❌ | Longitude. |
originAddress.associateToCustomer | boolean | ❌ | Whether 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
| Field | Type | Required | Description |
|---|---|---|---|
data | array[object] | ✅ | One or more service items to be booked. Each element represents a booking unit. |
data[].variant | object | ✅ | Defines the main service variant. |
data[].variant.type | string | ✅ | Type of variant identifier: "variantId" or "variantSku". |
data[].variant.value | string | ✅ | Identifier corresponding to the selected variant. |
data[].variant.quantity | number | ✅ | Quantity of the main variant requested. |
data[].variant.price | number | ❌ | Price paid by the customer (for integrations that include pricing). |
data[].variant.cost | number | ❌ | Cost paid to the provider. |
data[].addons | array[object] | ❌ | Optional list of additional variants (add-ons). |
data[].addons[].type | string | ✅ when addon sent | Add-on identifier type: "addonId" or "addonReference". |
data[].addons[].value | string | ✅ when addon sent | Add-on identifier value. |
data[].addons[].quantity | number | ✅ when addon sent | Quantity of the add-on. |
data[].addons[].price | number | ❌ | Price charged to the customer for the add-on. |
data[].addons[].cost | number | ❌ | Cost paid to the provider for the add-on. |
data[].products | array[object] | ❌ | Optional list of physical products to associate with the booking. See Product resolution in Business Rules. |
data[].products[].type | string | ✅ when product sent | Product identifier type: "productSku" or "productId". |
data[].products[].value | string | ✅ when product sent | Product identifier value: the SKU string, or the product id as a string when type is "productId". |
data[].products[].quantity | number | ✅ when product sent | Quantity of the product. Integer between 1 and 30. |
data[].products[].serialNumber | string | ❌ | Serial number of a specific product unit. Applies only to variants linked to products, and only when quantity is 1. |
data[].products[].deliveryDate | string (ISO 8601) | ❌ | Promised delivery date for the product. Interpreted in your instance's timezone. |
data[].transport | object | ❌ | Optional transport-related charges. |
data[].transport.price | number | ❌ | Price charged to the customer. |
data[].transport.cost | number | ❌ | Cost allocated to the provider. |
data[].dynamicForms | array[object] | ❌ | Optional form data collected as part of the booking (if configured in Sodtrack). |
data[].dynamicForms[].formReference | string | ✅ when form sent | Form reference identifier. |
data[].dynamicForms[].values | object | ✅ when form sent | Key-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
| Field | Type | Required | Description |
|---|---|---|---|
dateAssignment | object | ❌ | Defines how the booking date is determined. See Date assignment in Business Rules. |
dateAssignment.type | string | ✅ when object sent | One of: "direct", "user_scheduling", "userScheduling", "onDemand", "providerScheduling". |
dateAssignment.date | string (ISO 8601) | ❌ | Date and time for the booking. Required for scheduling when type is "direct". |
dateAssignment.timeRange | object | ❌ | Time range within the day (used with type = "direct" when applicable). |
dateAssignment.timeRange.type | string | ✅ when timeRange sent | "timeRangeId" or "timeRangeIndex". |
dateAssignment.timeRange.value | number | ✅ when timeRange sent | Identifier or index of the time range. |
👷 Provider Assignment
| Field | Type | Required | Description |
|---|---|---|---|
providerAssignment | object | ❌ | Defines how the provider or technician is assigned. See Booking or bundle scheduling logic in Business Rules. |
providerAssignment.type | string | ✅ when object sent | "automatic" or "direct". |
providerAssignment.provider | object | ❌ | Required when type is "direct". Specifies the provider when manually assigned. |
providerAssignment.provider.type | string | ✅ when provider sent | "providerId" or "providerReference". |
providerAssignment.provider.value | string | ✅ when provider sent | ID 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.
| Field | Type | Required | Description |
|---|---|---|---|
saleChannel | object | ✅ | Identifies the channel by reference or by internal id. See nested fields below. |
saleChannel.type | string | ✅ when saleChannel sent | One of: "reference" (lookup by channel reference, e.g. E001) or "id" (lookup by Sodtrack numeric id). |
saleChannel.value | string | ✅ when saleChannel sent | Value 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)
| Field | Type | Required | Description |
|---|---|---|---|
project | object | ❌ | Project 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.type | string | ✅ when project sent | Type of project identifier: "projectId" or "projectReference". |
project.value | string | ✅ when project sent | Internal Sodtrack project ID, or external reference of the project. |
project.shoppingCart | object | ❌ | Optional. 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.type | string | ✅ when shoppingCart sent | How the cart is identified: "shoppingCartId" or "shoppingCartReference". |
project.shoppingCart.value | string | ✅ when shoppingCart sent | Shopping cart ID (numeric as string) or external reference of the cart within the project. |
🧾 Additional Metadata
| Field | Type | Required | Description |
|---|---|---|---|
reference | string | ❌ | External system reference (e.g., order ID). |
createPaymentTransaction | boolean | ❌ | If true, creates a payment transaction for each created booking. |
useStrictCoverageValidationMode | boolean | ❌ | true: all-or-nothing validation (default). false: best-effort mode; only valid bookings are created. See Coverage Validation Behavior. |
Example Request (with project)
{
"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)
{
"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)
{
"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)
{
"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)
{
"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
{
"bookings": [
{
"id": 10452,
"quantity": 2,
"variantSku": ["install_curtains_sku"],
"variantId": 321
}
]
}
Response Fields
| Field | Type | Description |
|---|---|---|
bookings | array[object] | List of created bookings. |
bookings[].id | number | Unique Sodtrack booking ID. |
bookings[].quantity | number | Quantity of services booked. |
bookings[].variantSku | array[string] | List of variant SKUs associated with the booking. |
bookings[].variantId | number | Internal variant identifier. |
Error Responses
| HTTP Status | Error | Description |
|---|---|---|
400 Bad Request | InvalidParameters | One or more required fields are missing or invalid. |
400 Bad Request | INVALID_SALES_CHANNEL | The given saleChannel was not found (in strict mode). |
401 Unauthorized | — | Authentication token missing or expired. |
403 Forbidden | — | The API key or origin is not authorized. |
404 Not Found | — | A referenced variant, provider, project, or channel could not be found. |
500 Internal Server Error | — | Unexpected 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(withoutproject.shoppingCart): Send a project identifier (projectIdorprojectReference). 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.projectwithproject.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.dateis required when scheduling is performed (ISO 8601). Optionally,timeRangecan be sent to specify a time slot within the day bytimeRangeIdortimeRangeIndex. Ifdateis 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.userSchedulingis the preferred value;dateandtimeRangeare not used for scheduling when this type is set.onDemand: The service is on-demand; date assignment is handled accordingly by the platform.dateandtimeRangeare 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.dateandtimeRangeare 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
addressattribute of the provided address equals the existing address's address. - The provided
coordinatesare 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:
associateToCustomerdefaults to true when omitted. - Origin address:
associateToCustomerdefaults 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
addresshas 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. serialNumbermay be provided to link a specific unit, and only whenquantityis1. SendingserialNumberwithquantitygreater than1is rejected with400 Bad Request.- When
quantityis greater than1, Sodtrack creates one booking per unit. - The same
serialNumbercannot be repeated within a single line'sproducts.
Resolution outcomes
| Scenario | Behavior |
|---|---|
| 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 found | The specific product unit is linked to the booking. |
serialNumber provided but not found | The booking is created without the unit; a note is added so the unit can be linked later. |
Invalid deliveryDate | The 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:
providerAssignmentis missing.providerAssignmentwas provided but date/provider assignment fails (e.g. no availability for the given technician).- The destination
addressis not geo-referenced (no coordinates after resolution). originAddressis 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:
- Whether the required addresses were successfully resolved with coordinates.
- 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 Mode | Best Effort Mode |
|---|---|---|
| ❌ No | Bookings are created without coverage validation | Bookings are created without coverage validation |
| ✅ Yes | If any validation fails, nothing is created | Only valid bookings are created |
Stakeholder
- Optional
stakeholdersarray; only the first element is used and is applied to all created bookings. - Link existing: If
stakeholderIdis 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
stakeholderIdis 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).