MENU navbar-image

Introduction

Welcome to the Shift Collect API - A RESTful API for managing locker bookings and account access.

This API allows you to manage bookings for lockers at various sites, switch between account contexts, and manage your API tokens.

This API uses Bearer token authentication. Generate API tokens using the POST /v1/tokens/generate endpoint (requires appropriate permissions) and then include the token in the Authorization header as: Bearer {your-token}.

As you scroll, you'll see code examples for working with the API in different programming languages in the dark area to the right (or as part of the content on mobile). You can switch the language used with the tabs at the top right (or from the nav menu at the top left on mobile).

Authenticating requests

To authenticate requests, include an Authorization header with the value "Bearer {YOUR_API_TOKEN}".

All authenticated endpoints are marked with a requires authentication badge in the documentation below.

Generate API tokens using the POST /v1/auth/token endpoint. See the Authentication section below for more information.

Accounts

Get the current account context.

requires authentication

Returns detailed information about the currently active account, including reverse flow strategies, locker assignment strategy, service products, users, and settings.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/account" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/account"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/account';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/account'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200):


{
    "data": {
        "id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
        "name": "Acme Corp",
        "description": "A leading logistics company",
        "website": "https://acme.example.com",
        "phone": "+44 20 1234 5678",
        "email": "[email protected]",
        "address": "123 Business Street, London, SW1A 1AA",
        "is_active": true,
        "created_at": "2025-01-01T00:00:00.000000Z",
        "updated_at": "2025-01-01T00:00:00.000000Z",
        "reverse_flow_strategies": [
            {
                "id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
                "name": "return_to_sender",
                "description": "Return to Sender",
                "is_active": true,
                "is_default": true
            },
            {
                "id": "01ARZ3NDEKTSV4RRFFQ69G5FAY",
                "name": "dispose_of_item",
                "description": "Dispose of Item",
                "is_active": true,
                "is_default": false
            }
        ],
        "locker_assignment_strategy": {
            "id": "01ARZ3NDEKTSV4RRFFQ69G5FAZ",
            "name": "Just-in-time Assignment",
            "description": "Assign lockers on day of delivery",
            "is_active": true
        },
        "service_products": [
            {
                "id": "01ARZ3NDEKTSV4RRFFQ69G5FAZ",
                "name": "DC to Locker",
                "description": "Direct delivery from despatch centre to locker",
                "requires_collection": true,
                "requires_delivery": true,
                "requires_locker": true,
                "requires_sorting_hub": false,
                "is_active": true,
                "is_default": true
            }
        ],
        "users": [
            {
                "id": "01ARZ3NDEKTSV4RRFFQ69G5FBA",
                "name": "John Doe",
                "created_at": "2025-01-01T00:00:00.000000Z",
                "last_accessed_at": "2025-01-15T10:30:00.000000Z",
                "is_active": true,
                "role": "owner"
            }
        ],
        "settings": [
            {
                "name": "default_currency",
                "description": "Default currency for pricing",
                "type": "string",
                "value": "GBP"
            },
            {
                "name": "vat_rate",
                "description": "VAT rate as decimal (e.g., 0.20 for 20%)",
                "type": "decimal",
                "value": 0.2
            },
            {
                "name": "sla_min_days",
                "description": "Minimum SLA days for delivery",
                "type": "integer",
                "value": 2
            },
            {
                "name": "reverse_flow_allow_consumer_reschedule",
                "description": "Allow consumers to reschedule reverse flow deliveries",
                "type": "boolean",
                "value": true
            },
            {
                "name": "reverse_flow_alternative_address",
                "description": "Alternative address for reverse flow returns",
                "type": "address",
                "value": {
                    "line_1": "123 Return Street",
                    "line_2": null,
                    "line_3": null,
                    "city": "London",
                    "postcode": "SW1A 1AA",
                    "country": "United Kingdom"
                }
            }
        ]
    }
}
 

Example response (400):


{
    "message": "No account context set"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Request      

GET v1/account

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Authentication

Generate API token from credentials.

requires authentication

Authenticates a user with email and password and returns an API token. This is useful for programmatic access without needing to login via the SPA first. Requires Admin or Owner role in the specified account.

Example request:
curl --request POST \
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/auth/token" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"email\": \"[email protected]\",
    \"password\": \"password123\",
    \"account_id\": \"01ARZ3NDEKTSV4RRFFQ69G5FAW\",
    \"token_name\": \"Production API Token\",
    \"expires_at\": \"2025-12-31T23:59:59Z\"
}"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/auth/token"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "email": "[email protected]",
    "password": "password123",
    "account_id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
    "token_name": "Production API Token",
    "expires_at": "2025-12-31T23:59:59Z"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/auth/token';
$response = $client->post(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'json' => [
            'email' => '[email protected]',
            'password' => 'password123',
            'account_id' => '01ARZ3NDEKTSV4RRFFQ69G5FAW',
            'token_name' => 'Production API Token',
            'expires_at' => '2025-12-31T23:59:59Z',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/auth/token'
payload = {
    "email": "[email protected]",
    "password": "password123",
    "account_id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
    "token_name": "Production API Token",
    "expires_at": "2025-12-31T23:59:59Z"
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('POST', url, headers=headers, json=payload)
response.json()

Example response (200):


{
    "token": "1|abcdefghijklmnopqrstuvwxyz1234567890",
    "token_name": "Production API Token",
    "account_id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
    "user": {
        "id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
        "name": "John Doe",
        "email": "[email protected]"
    },
    "abilities": [
        "*"
    ],
    "expires_at": "2025-12-31T23:59:59.000000Z",
    "created_at": "2025-01-01T00:00:00.000000Z",
    "message": "API token generated successfully"
}
 

Example response (403):


{
    "message": "This action is unauthorised. Only admins and owners can generate API tokens."
}
 

Example response (403):


{
    "message": "User does not belong to the specified account."
}
 

Example response (422):


{
    "message": "The given data was invalid.",
    "errors": {
        "email": [
            "The email field is required."
        ],
        "password": [
            "The password field is required."
        ],
        "account_id": [
            "The account id field is required."
        ],
        "expires_at": [
            "The expires at must be a date after now."
        ]
    }
}
 

Example response (422):


{
    "message": "The given data was invalid.",
    "errors": {
        "email": [
            "These credentials do not match our records."
        ]
    }
}
 

Request      

POST v1/auth/token

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Body Parameters

email   string     

User email address Example: [email protected]

password   string     

User password Example: password123

account_id   string     

Account ID (ULID) for which to generate the token Example: 01ARZ3NDEKTSV4RRFFQ69G5FAW

token_name   string  optional    

Name for the token (optional, defaults to "API Token") Example: Production API Token

expires_at   string  optional    

Expiration date and time (ISO 8601). Must be in the future Example: 2025-12-31T23:59:59Z

Availability

Get available locker collection slots for a site.

requires authentication

Returns date-grouped customer collection slots for the given locker site, starting after the next collection from the given despatch centre plus the account's minimum calendar-day lead time. Days with no bookable slots are omitted. Capacity considers active non-leased lockers minus soft reservations for each timeslot and date. A specific locker is not chosen.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/availability?site_id=01ARZ3NDEKTSV4RRFFQ69G5FAA&despatch_centre_id=01ARZ3NDEKTSV4RRFFQ69G5FAB" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/availability"
);

const params = {
    "site_id": "01ARZ3NDEKTSV4RRFFQ69G5FAA",
    "despatch_centre_id": "01ARZ3NDEKTSV4RRFFQ69G5FAB",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/availability';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'site_id' => '01ARZ3NDEKTSV4RRFFQ69G5FAA',
            'despatch_centre_id' => '01ARZ3NDEKTSV4RRFFQ69G5FAB',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/availability'
params = {
  'site_id': '01ARZ3NDEKTSV4RRFFQ69G5FAA',
  'despatch_centre_id': '01ARZ3NDEKTSV4RRFFQ69G5FAB',
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200):


{
    "data": [
        {
            "date": "2026-08-23",
            "slots": [
                {
                    "site_collection_timeslot_id": "01ARZ3NDEKTSV4RRFFQ69G5FAC",
                    "slot_key": "AM",
                    "sequence_order": 1,
                    "customer_collection_window": {
                        "starts_at": "2026-08-23T07:00:00+01:00",
                        "ends_at": "2026-08-23T12:00:00+01:00"
                    }
                }
            ]
        }
    ]
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (404):


{
    "message": "Site not found"
}
 

Example response (422):


{
    "message": "The given data was invalid.",
    "errors": {
        "despatch_centre_id": [
            "The selected despatch centre does not belong to this account."
        ]
    }
}
 

Request      

GET v1/availability

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

site_id   string     

Locker site ID Example: 01ARZ3NDEKTSV4RRFFQ69G5FAA

despatch_centre_id   string     

Collection despatch centre ID (same as collection.despatch_centre_id when creating a booking) Example: 01ARZ3NDEKTSV4RRFFQ69G5FAB

Booking Item Sizes

List effective parcel size presets for the authenticated account.

requires authentication

Returns merged global defaults and account-specific overrides for the requested service product (or all catalogued service products when omitted).

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/booking-item-sizes?service_product_id=architecto" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/booking-item-sizes"
);

const params = {
    "service_product_id": "architecto",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/booking-item-sizes';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'service_product_id' => 'architecto',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/booking-item-sizes'
params = {
  'service_product_id': 'architecto',
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200):


{
    "data": [
        {
            "id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
            "code": "small",
            "label": "Small",
            "service_product_id": "01ARZ3NDEKTSV4RRFFQ69G5FAY",
            "max_height_cm": 50,
            "max_width_cm": 90,
            "max_depth_cm": 150,
            "max_weight_kg": 25,
            "max_value_gbp": 10000
        }
    ]
}
 

Request      

GET v1/booking-item-sizes

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

service_product_id   string  optional    

Filter by service product ULID Example: architecto

Booking Tracking

Track a booking by ID (authenticated endpoint).

requires authentication

Allows authenticated accounts to track their bookings.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/architecto/tracking" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/architecto/tracking"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/architecto/tracking';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/architecto/tracking'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200):


{
    "reference_id": "BK65A3F2E1",
    "package_info": {
        "tracking_number": "BK65A3F2E1",
        "status": "confirmed",
        "locker_assignments": [
            {
                "locker_id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
                "locker_name": "A1-01",
                "cabinet": {
                    "id": "01ARZ3NDEKTSV4RRFFQ69G5FAU",
                    "name": "Cabinet A1",
                    "status": "active"
                },
                "starts_at": "2025-01-15T09:00:00.000000Z",
                "ends_at": "2025-01-20T17:00:00.000000Z"
            }
        ],
        "items_count": 3,
        "items": [
            {
                "name": "Item 1",
                "quantity": 1
            }
        ]
    },
    "events": [],
    "last_updated": "2025-01-15T09:00:00.000000Z"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (404):


{
    "message": "Booking not found"
}
 

Request      

GET v1/bookings/{id}/tracking

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the booking. Example: architecto

Bookings

Display a listing of bookings.

requires authentication

Returns a paginated list of bookings for the current account context. You can filter by status. When we have more detail about why the booking is in its current state, each booking includes status_reason_id, status_reason, and status_reason_label; the same fields appear on each status_history entry where they were recorded.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings?status=confirmed&per_page=20&page=1" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings"
);

const params = {
    "status": "confirmed",
    "per_page": "20",
    "page": "1",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'status' => 'confirmed',
            'per_page' => '20',
            'page' => '1',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings'
params = {
  'status': 'confirmed',
  'per_page': '20',
  'page': '1',
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200):


{
    "data": [
        {
            "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
            "reference_id": "SC689PUY74F",
            "service_product_id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
            "service_product": "DC to Locker",
            "status_id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
            "status": "confirmed",
            "status_reason_id": null,
            "status_reason": null,
            "status_reason_label": null,
            "site_id": "01ARZ3NDEKTSV4RRFFQ69G5FAS",
            "site": {
                "id": "01ARZ3NDEKTSV4RRFFQ69G5FAS",
                "name": "Example Locker Site",
                "city": "London",
                "postcode": "N1 1AA"
            },
            "status_history": [
                {
                    "id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
                    "status": "confirmed",
                    "label": "Confirmed",
                    "description": "Booking has been confirmed",
                    "status_reason_id": null,
                    "status_reason": null,
                    "status_reason_label": null,
                    "status_changed_at": "2025-01-01T00:00:00.000000Z"
                }
            ],
            "items": [
                {
                    "id": "01ARZ3NDEKTSV4RRFFQ69G5FAB",
                    "name": "Box of documents",
                    "description": "Important business documents",
                    "quantity": 1,
                    "size": {
                        "code": "large",
                        "label": "Large",
                        "is_override": false
                    },
                    "weight": 30,
                    "height": 50,
                    "width": 90,
                    "depth": 170,
                    "value": 10000,
                    "volume": 765000,
                    "created_at": "2025-01-01T00:00:00.000000Z",
                    "updated_at": "2025-01-01T00:00:00.000000Z"
                }
            ],
            "collections": [],
            "labels": [
                {
                    "id": "01ARZ3NDEKTSV4RRFFQ69G5FAD",
                    "zpl_available": true,
                    "pdf_available": true,
                    "png_available": false,
                    "zpl": "https://api.shiftcollect.com/v1/labels/1234567890/zpl",
                    "pdf": "https://api.shiftcollect.com/v1/labels/1234567890/pdf",
                    "png": "https://api.shiftcollect.com/v1/labels/1234567890/png"
                }
            ],
            "locker_reservation_window": null,
            "locker_assignments": null,
            "authorisations": null,
            "contacts": [
                {
                    "id": "01ARZ3NDEKTSV4RRFFQ69G5FAC",
                    "name": "Jane Doe",
                    "email": "[email protected]",
                    "phone": "+447700900123"
                }
            ],
            "returns": null,
            "created_at": "2025-01-01T00:00:00.000000Z",
            "updated_at": "2025-01-01T00:00:00.000000Z",
            "created_by": "01ARZ3NDEKTSV4RRFFQ69G5FAY"
        }
    ],
    "pagination": {
        "current_page": 1,
        "per_page": 15,
        "total": 100,
        "last_page": 7,
        "from": 1,
        "to": 15,
        "has_more_pages": true
    },
    "links": {
        "first": "http://example.com/api/v1/bookings?page=1",
        "last": "http://example.com/api/v1/bookings?page=7",
        "prev": null,
        "next": "http://example.com/api/v1/bookings?page=2"
    }
}
 

Example response (400):


{
    "message": "No account context set"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Request      

GET v1/bookings

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

status   string  optional    

Filter bookings by status Example: confirmed

per_page   integer  optional    

Number of items per page (max 100) Example: 20

page   integer  optional    

Page number Example: 1

Store a newly created booking.

requires authentication

Creates a new booking associated with the current account context and the authenticated user. The booking will be processed according to the specified service product.

Parcel sizes on booking items

For service products with a size catalogue (see GET /v1/booking-item-sizes), each entry in items can be described in three ways:

  1. Size shortcut — send size (small, large, xlarge, or all_sizes). Any omitted height, width, depth, weight, or value are set from that tier’s catalogue maximums before the booking is saved.
  2. Explicit dimensions — send height, width, depth, and weight (centimetres and kilograms). We assign the smallest tier that fits. width and depth are rotation-invariant (you may swap them; matching sorts all three edges).
  3. Size plus dimensions — send both; dimensions must fit within the declared size tier.

If there is no catalogue for the chosen service product, each item still requires height, width, depth, and weight as today.

Invalid or unknown size values, dimensions that exceed the tier, or parcels too large for any tier return 422 validation errors on the relevant items.* fields.

Example request:
curl --request POST \
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"service_product_id\": \"01ARZ3NDEKTSV4RRFFQ69G5FAX\",
    \"reference_id\": \"ORD-12345\",
    \"collection\": {
        \"site_id\": \"01ARZ3NDEKTSV4RRFFQ69G5FAY\",
        \"despatch_centre_id\": \"01ARZ3NDEKTSV4RRFFQ69G5FAY\",
        \"address\": {
            \"recipient\": \"John Smith\",
            \"line_1\": \"123 Main Street\",
            \"line_2\": \"Flat 3\",
            \"line_3\": \"Building A\",
            \"city\": \"Plymouth\",
            \"postcode\": \"SW1A 1AA\",
            \"country\": \"United Kingdom\",
            \"phone\": \"+44 1234 567890\",
            \"email\": \"[email protected]\",
            \"special_instructions\": \"Leave at side gate\",
            \"latitude\": -89,
            \"longitude\": -179
        },
        \"t_earliest_collection\": \"2025-01-15T09:00:00Z\",
        \"t_latest_collection\": \"2025-01-15T17:00:00Z\"
    },
    \"delivery\": {
        \"site_id\": \"01ARZ3NDEKTSV4RRFFQ69G5FAZ\",
        \"despatch_centre_id\": \"01ARZ3NDEKTSV4RRFFQ69G5FAZ\",
        \"address\": {
            \"recipient\": \"John Smith\",
            \"line_1\": \"123 Main Street\",
            \"line_2\": \"Flat 3\",
            \"line_3\": \"Building A\",
            \"city\": \"Plymouth\",
            \"postcode\": \"SW1A 1AA\",
            \"country\": \"United Kingdom\",
            \"phone\": \"+44 1234 567890\",
            \"email\": \"[email protected]\",
            \"special_instructions\": \"Leave at side gate\",
            \"latitude\": -90,
            \"longitude\": -179
        },
        \"fallback_address\": {
            \"recipient\": \"m\",
            \"line_1\": \"12 High Street\",
            \"line_2\": \"i\",
            \"line_3\": \"y\",
            \"city\": \"v\",
            \"postcode\": \"PL15 8AA\",
            \"country\": \"d\",
            \"phone\": \"l\",
            \"email\": \"[email protected]\",
            \"special_instructions\": \"h\",
            \"latitude\": -90,
            \"longitude\": -180
        },
        \"site_collection_timeslot_id\": \"01ARZ3NDEKTSV4RRFFQ69G5FAC\",
        \"customer_collection_date\": \"2026-08-23\"
    },
    \"items\": [
        {
            \"name\": \"Standard parcel\",
            \"description\": \"Customer order #12345\",
            \"quantity\": 1,
            \"size\": \"large\",
            \"weight\": 30,
            \"height\": 50,
            \"width\": 90,
            \"depth\": 170,
            \"value\": 10000,
            \"delivery_access\": \"curbside\",
            \"delivery_options\": [
                \"installation\"
            ]
        }
    ],
    \"authorisation_group_ids\": [
        \"01ARZ3NDEKTSV4RRFFQ69G5FAY\"
    ],
    \"locker_user_ids\": [
        \"01ARZ3NDEKTSV4RRFFQ69G5FAZ\"
    ],
    \"contacts\": [
        {
            \"name\": \"John Doe\",
            \"email\": \"[email protected]\",
            \"phone\": \"+447700900123\"
        }
    ]
}"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "service_product_id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
    "reference_id": "ORD-12345",
    "collection": {
        "site_id": "01ARZ3NDEKTSV4RRFFQ69G5FAY",
        "despatch_centre_id": "01ARZ3NDEKTSV4RRFFQ69G5FAY",
        "address": {
            "recipient": "John Smith",
            "line_1": "123 Main Street",
            "line_2": "Flat 3",
            "line_3": "Building A",
            "city": "Plymouth",
            "postcode": "SW1A 1AA",
            "country": "United Kingdom",
            "phone": "+44 1234 567890",
            "email": "[email protected]",
            "special_instructions": "Leave at side gate",
            "latitude": -89,
            "longitude": -179
        },
        "t_earliest_collection": "2025-01-15T09:00:00Z",
        "t_latest_collection": "2025-01-15T17:00:00Z"
    },
    "delivery": {
        "site_id": "01ARZ3NDEKTSV4RRFFQ69G5FAZ",
        "despatch_centre_id": "01ARZ3NDEKTSV4RRFFQ69G5FAZ",
        "address": {
            "recipient": "John Smith",
            "line_1": "123 Main Street",
            "line_2": "Flat 3",
            "line_3": "Building A",
            "city": "Plymouth",
            "postcode": "SW1A 1AA",
            "country": "United Kingdom",
            "phone": "+44 1234 567890",
            "email": "[email protected]",
            "special_instructions": "Leave at side gate",
            "latitude": -90,
            "longitude": -179
        },
        "fallback_address": {
            "recipient": "m",
            "line_1": "12 High Street",
            "line_2": "i",
            "line_3": "y",
            "city": "v",
            "postcode": "PL15 8AA",
            "country": "d",
            "phone": "l",
            "email": "[email protected]",
            "special_instructions": "h",
            "latitude": -90,
            "longitude": -180
        },
        "site_collection_timeslot_id": "01ARZ3NDEKTSV4RRFFQ69G5FAC",
        "customer_collection_date": "2026-08-23"
    },
    "items": [
        {
            "name": "Standard parcel",
            "description": "Customer order #12345",
            "quantity": 1,
            "size": "large",
            "weight": 30,
            "height": 50,
            "width": 90,
            "depth": 170,
            "value": 10000,
            "delivery_access": "curbside",
            "delivery_options": [
                "installation"
            ]
        }
    ],
    "authorisation_group_ids": [
        "01ARZ3NDEKTSV4RRFFQ69G5FAY"
    ],
    "locker_user_ids": [
        "01ARZ3NDEKTSV4RRFFQ69G5FAZ"
    ],
    "contacts": [
        {
            "name": "John Doe",
            "email": "[email protected]",
            "phone": "+447700900123"
        }
    ]
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings';
$response = $client->post(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'json' => [
            'service_product_id' => '01ARZ3NDEKTSV4RRFFQ69G5FAX',
            'reference_id' => 'ORD-12345',
            'collection' => [
                'site_id' => '01ARZ3NDEKTSV4RRFFQ69G5FAY',
                'despatch_centre_id' => '01ARZ3NDEKTSV4RRFFQ69G5FAY',
                'address' => [
                    'recipient' => 'John Smith',
                    'line_1' => '123 Main Street',
                    'line_2' => 'Flat 3',
                    'line_3' => 'Building A',
                    'city' => 'Plymouth',
                    'postcode' => 'SW1A 1AA',
                    'country' => 'United Kingdom',
                    'phone' => '+44 1234 567890',
                    'email' => '[email protected]',
                    'special_instructions' => 'Leave at side gate',
                    'latitude' => -89,
                    'longitude' => -179,
                ],
                't_earliest_collection' => '2025-01-15T09:00:00Z',
                't_latest_collection' => '2025-01-15T17:00:00Z',
            ],
            'delivery' => [
                'site_id' => '01ARZ3NDEKTSV4RRFFQ69G5FAZ',
                'despatch_centre_id' => '01ARZ3NDEKTSV4RRFFQ69G5FAZ',
                'address' => [
                    'recipient' => 'John Smith',
                    'line_1' => '123 Main Street',
                    'line_2' => 'Flat 3',
                    'line_3' => 'Building A',
                    'city' => 'Plymouth',
                    'postcode' => 'SW1A 1AA',
                    'country' => 'United Kingdom',
                    'phone' => '+44 1234 567890',
                    'email' => '[email protected]',
                    'special_instructions' => 'Leave at side gate',
                    'latitude' => -90,
                    'longitude' => -179,
                ],
                'fallback_address' => [
                    'recipient' => 'm',
                    'line_1' => '12 High Street',
                    'line_2' => 'i',
                    'line_3' => 'y',
                    'city' => 'v',
                    'postcode' => 'PL15 8AA',
                    'country' => 'd',
                    'phone' => 'l',
                    'email' => '[email protected]',
                    'special_instructions' => 'h',
                    'latitude' => -90,
                    'longitude' => -180,
                ],
                'site_collection_timeslot_id' => '01ARZ3NDEKTSV4RRFFQ69G5FAC',
                'customer_collection_date' => '2026-08-23',
            ],
            'items' => [
                [
                    'name' => 'Standard parcel',
                    'description' => 'Customer order #12345',
                    'quantity' => 1,
                    'size' => 'large',
                    'weight' => 30,
                    'height' => 50,
                    'width' => 90,
                    'depth' => 170,
                    'value' => 10000,
                    'delivery_access' => 'curbside',
                    'delivery_options' => [
                        'installation',
                    ],
                ],
            ],
            'authorisation_group_ids' => [
                '01ARZ3NDEKTSV4RRFFQ69G5FAY',
            ],
            'locker_user_ids' => [
                '01ARZ3NDEKTSV4RRFFQ69G5FAZ',
            ],
            'contacts' => [
                [
                    'name' => 'John Doe',
                    'email' => '[email protected]',
                    'phone' => '+447700900123',
                ],
            ],
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings'
payload = {
    "service_product_id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
    "reference_id": "ORD-12345",
    "collection": {
        "site_id": "01ARZ3NDEKTSV4RRFFQ69G5FAY",
        "despatch_centre_id": "01ARZ3NDEKTSV4RRFFQ69G5FAY",
        "address": {
            "recipient": "John Smith",
            "line_1": "123 Main Street",
            "line_2": "Flat 3",
            "line_3": "Building A",
            "city": "Plymouth",
            "postcode": "SW1A 1AA",
            "country": "United Kingdom",
            "phone": "+44 1234 567890",
            "email": "[email protected]",
            "special_instructions": "Leave at side gate",
            "latitude": -89,
            "longitude": -179
        },
        "t_earliest_collection": "2025-01-15T09:00:00Z",
        "t_latest_collection": "2025-01-15T17:00:00Z"
    },
    "delivery": {
        "site_id": "01ARZ3NDEKTSV4RRFFQ69G5FAZ",
        "despatch_centre_id": "01ARZ3NDEKTSV4RRFFQ69G5FAZ",
        "address": {
            "recipient": "John Smith",
            "line_1": "123 Main Street",
            "line_2": "Flat 3",
            "line_3": "Building A",
            "city": "Plymouth",
            "postcode": "SW1A 1AA",
            "country": "United Kingdom",
            "phone": "+44 1234 567890",
            "email": "[email protected]",
            "special_instructions": "Leave at side gate",
            "latitude": -90,
            "longitude": -179
        },
        "fallback_address": {
            "recipient": "m",
            "line_1": "12 High Street",
            "line_2": "i",
            "line_3": "y",
            "city": "v",
            "postcode": "PL15 8AA",
            "country": "d",
            "phone": "l",
            "email": "[email protected]",
            "special_instructions": "h",
            "latitude": -90,
            "longitude": -180
        },
        "site_collection_timeslot_id": "01ARZ3NDEKTSV4RRFFQ69G5FAC",
        "customer_collection_date": "2026-08-23"
    },
    "items": [
        {
            "name": "Standard parcel",
            "description": "Customer order #12345",
            "quantity": 1,
            "size": "large",
            "weight": 30,
            "height": 50,
            "width": 90,
            "depth": 170,
            "value": 10000,
            "delivery_access": "curbside",
            "delivery_options": [
                "installation"
            ]
        }
    ],
    "authorisation_group_ids": [
        "01ARZ3NDEKTSV4RRFFQ69G5FAY"
    ],
    "locker_user_ids": [
        "01ARZ3NDEKTSV4RRFFQ69G5FAZ"
    ],
    "contacts": [
        {
            "name": "John Doe",
            "email": "[email protected]",
            "phone": "+447700900123"
        }
    ]
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('POST', url, headers=headers, json=payload)
response.json()

Example response (201):


{
    "message": "Booking created successfully",
    "booking_id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
    "reference_id": "BK-2025-001",
    "service": "sorted_home_delivery",
    "label_ids": [
        "1111111119",
        "1111111120"
    ]
}
 

Example response (400):


{
    "message": "No account context set"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (422):


{
    "message": "The given data was invalid.",
    "errors": {
        "delivery": [
            "The delivery field is required."
        ],
        "collection.address_id": [
            "The collection address id field is required when collection is present."
        ],
        "delivery.customer_collection_date": [
            "The pickup date is before the minimum collection-to-locker lead time."
        ]
    }
}
 

Example response (422, Validation failed (including invalid `size` or dimensions that do not fit any tier).):


{
    "message": "The given data was invalid.",
    "errors": {
        "items.0.size": [
            "The selected size is not available for this service product."
        ],
        "items.0.height": [
            "The item dimensions and weight exceed the maximum allowed parcel size for this service product."
        ]
    }
}
 

Request      

POST v1/bookings

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Body Parameters

service_product_id   string  optional    

Service product identifier. Accepts either the service product ULID or exact name. If not provided, the account's default service will be used. Must match an existing stored value. Example: 01ARZ3NDEKTSV4RRFFQ69G5FAX

reference_id   string  optional    

Optional custom reference ID for the booking. Must be unique within the account. If not provided, a reference ID will be auto-generated. Must not be greater than 255 characters. Example: ORD-12345

collection   object  optional    

Collection details (required if service requires collection). Must contain exactly one of: site_id, despatch_centre_id, or address.

site_id   string  optional    

The site ID from where the booking will be collected (if collecting from a locker site). This field is required when none of collection.despatch_centre_id and collection.address are present. Must match an existing stored value. Example: 01ARZ3NDEKTSV4RRFFQ69G5FAY

despatch_centre_id   string  optional    

The despatch centre ID from where the booking will be collected. This field is required when none of collection.site_id and collection.address are present. Must match an existing stored value. Example: 01ARZ3NDEKTSV4RRFFQ69G5FAY

address   object  optional    

Inline address object for collection (if not using site_id or despatch_centre_id). This field is required when none of collection.site_id and collection.despatch_centre_id are present.

recipient   string  optional    

Recipient name. Must not be greater than 255 characters. Example: John Smith

line_1   string  optional    

Address line 1. This field is required when collection.address is present. Must not be greater than 255 characters. Example: 123 Main Street

line_2   string  optional    

Address line 2. Must not be greater than 255 characters. Example: Flat 3

line_3   string  optional    

Address line 3. Must not be greater than 255 characters. Example: Building A

city   string  optional    

City. Must not be greater than 255 characters. Example: Plymouth

postcode   string  optional    

Postcode. This field is required when collection.address is present. Must not be greater than 20 characters. Example: SW1A 1AA

country   string  optional    

Country. Must not be greater than 255 characters. Example: United Kingdom

phone   string  optional    

Phone number. Must not be greater than 50 characters. Example: +44 1234 567890

email   string  optional    

Email address. Must be a valid email address. Must not be greater than 255 characters. Example: [email protected]

special_instructions   string  optional    

Special delivery instructions. Must not be greater than 1000 characters. Example: Leave at side gate

latitude   number  optional    

Must be between -90 and 90. Example: -89

longitude   number  optional    

Must be between -180 and 180. Example: -179

t_earliest_collection   string  optional    

Earliest collection time (ISO 8601 datetime). Must be a valid date. Must be a date after now. Example: 2025-01-15T09:00:00Z

t_latest_collection   string  optional    

Latest collection time (ISO 8601 datetime). Must be a valid date. Must be a date after collection.t_earliest_collection. Example: 2025-01-15T17:00:00Z

delivery   object  optional    

Delivery details (required if service product requires delivery). Must contain exactly one of: site_id, despatch_centre_id, or address.

site_id   string  optional    

The site ID to where items will be delivered (if to a locker site). This field is required when none of delivery.despatch_centre_id and delivery.address are present. Must match an existing stored value. Example: 01ARZ3NDEKTSV4RRFFQ69G5FAZ

despatch_centre_id   string  optional    

The despatch centre ID to where items will be delivered. This field is required when none of delivery.site_id and delivery.address are present. Must match an existing stored value. Example: 01ARZ3NDEKTSV4RRFFQ69G5FAZ

address   object  optional    

Inline address object for delivery (if not using site_id or despatch_centre_id). This field is required when none of delivery.site_id and delivery.despatch_centre_id are present.

recipient   string  optional    

Recipient name. Must not be greater than 255 characters. Example: John Smith

line_1   string  optional    

Address line 1. This field is required when delivery.address is present. Must not be greater than 255 characters. Example: 123 Main Street

line_2   string  optional    

Address line 2. Must not be greater than 255 characters. Example: Flat 3

line_3   string  optional    

Address line 3. Must not be greater than 255 characters. Example: Building A

city   string  optional    

City. Must not be greater than 255 characters. Example: Plymouth

postcode   string  optional    

Postcode. This field is required when delivery.address is present. Must not be greater than 20 characters. Example: SW1A 1AA

country   string  optional    

Country. Must not be greater than 255 characters. Example: United Kingdom

phone   string  optional    

Phone number. Must not be greater than 50 characters. Example: +44 1234 567890

email   string  optional    

Email address. Must be a valid email address. Must not be greater than 255 characters. Example: [email protected]

special_instructions   string  optional    

Special delivery instructions. Must not be greater than 1000 characters. Example: Leave at side gate

latitude   number  optional    

Must be between -90 and 90. Example: -90

longitude   number  optional    

Must be between -180 and 180. Example: -179

fallback_address   object  optional    

Optional home/fallback address used for FREE_UPGRADE overflow when locker delivery cannot be allocated. Not used as the live destination while delivery.site_id (or another destination type) is set.

recipient   string  optional    

Must not be greater than 255 characters. Example: m

line_1   string  optional    

Fallback address line 1. This field is required when delivery.fallback_address is present. Must not be greater than 255 characters. Example: 12 High Street

line_2   string  optional    

Must not be greater than 255 characters. Example: i

line_3   string  optional    

Must not be greater than 255 characters. Example: y

city   string  optional    

Must not be greater than 255 characters. Example: v

postcode   string  optional    

Fallback address postcode. This field is required when delivery.fallback_address is present. Must not be greater than 20 characters. Example: PL15 8AA

country   string  optional    

Must not be greater than 255 characters. Example: d

phone   string  optional    

Must not be greater than 50 characters. Example: l

email   string  optional    

Must be a valid email address. Must not be greater than 255 characters. Example: [email protected]

special_instructions   string  optional    

Must not be greater than 1000 characters. Example: h

latitude   number  optional    

Must be between -90 and 90. Example: -90

longitude   number  optional    

Must be between -180 and 180. Example: -180

site_collection_timeslot_id   string  optional    

Required when delivery.site_id is set. Timeslot from GET /v1/availability. Example: 01ARZ3NDEKTSV4RRFFQ69G5FAC

customer_collection_date   string  optional    

Required when delivery.site_id is set. Customer collection date (Y-m-d) for the chosen timeslot. Example: 2026-08-23

contacts   object[]  optional    

Array of contacts to notify about tracking events and booking updates.

name   string  optional    

Contact name. Must not be greater than 255 characters. Example: John Doe

email   string  optional    

Contact email. This field is required when contacts.*.phone is not present. Must be a valid email address. Example: [email protected]

phone   string  optional    

Contact phone. Must be in international format (e.g. +447700900123). This field is required when contacts.*.email is not present. Must not be greater than 16 characters. Example: +447700900123

items   object[]     

Packages on the booking. Each object requires name and quantity. Use size and/or physical dimensions as described in the endpoint introduction.

name   string  optional    

Display name for the package. This field is required when items is present. Must not be greater than 255 characters. Example: Standard parcel

description   string  optional    

Optional description. Max 1000 characters. Must not be greater than 1000 characters. Example: Customer order #12345

quantity   integer  optional    

Number of identical physical packages represented by this line. Must be >= 1. This field is required when items is present. Must be at least 1. Example: 1

size   string  optional    

Parcel tier: small, large, xlarge, or all_sizes. Available codes depend on the service product — use GET /v1/booking-item-sizes. When provided, omitted dimensions and weight may be back-filled from the catalogue. Example: large

weight   number  optional    

Weight in kilograms. Required per item when size is not used and no catalogue exists; optional when size is used (back-filled if omitted). Example: 30

height   number  optional    

Height in centimetres. Required per item when size is not used and no catalogue exists; optional when size is used (back-filled if omitted). Example: 50

width   number  optional    

Width in centimetres. Interchangeable with depth for tier matching. Example: 90

depth   number  optional    

Depth in centimetres (longest horizontal edge in commercial terms). Interchangeable with width for tier matching. Example: 170

value   number  optional    

Declared value in GBP. Back-filled to the tier maximum when size is used and value is omitted. Example: 10000

delivery_access   string  optional    

Home delivery only. curbside (default) or room_of_choice. Example: curbside

delivery_options   string[]  optional    

Home delivery add-ons: installation, remove_packaging, remove_old_appliance. installation and remove_packaging require room_of_choice.

authorisation_group_ids   string[]  optional    

Authorisation group ID. Must match an existing stored value.

locker_user_ids   string[]  optional    

Locker user ID. Must match an existing stored value.

Display the specified booking.

requires authentication

Returns full details for one booking in your current account context. When available, status_reason_id, status_reason, and status_reason_label describe why the booking has its current overall status; each past step in status_history can include the same three fields where they were recorded.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200):


{
    "data": {
        "id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
        "reference_id": "SC689PUY74F",
        "service_product_id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
        "service_product": "DC to Locker",
        "status_id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
        "status": "confirmed",
        "status_reason_id": null,
        "status_reason": null,
        "status_reason_label": null,
        "site_id": "01ARZ3NDEKTSV4RRFFQ69G5FAS",
        "site": {
            "id": "01ARZ3NDEKTSV4RRFFQ69G5FAS",
            "name": "Example Locker Site",
            "city": "London",
            "postcode": "N1 1AA"
        },
        "status_history": [
            {
                "id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
                "status": "confirmed",
                "label": "Confirmed",
                "description": "Booking has been confirmed",
                "status_reason_id": null,
                "status_reason": null,
                "status_reason_label": null,
                "status_changed_at": "2025-01-01T00:00:00.000000Z"
            }
        ],
        "items": [
            {
                "id": "01ARZ3NDEKTSV4RRFFQ69G5FAB",
                "name": "Box of documents",
                "description": "Important business documents",
                "quantity": 1,
                "size": {
                    "code": "large",
                    "label": "Large",
                    "is_override": false
                },
                "weight": 30,
                "height": 50,
                "width": 90,
                "depth": 170,
                "value": 10000,
                "volume": 765000,
                "created_at": "2025-01-01T00:00:00.000000Z",
                "updated_at": "2025-01-01T00:00:00.000000Z"
            }
        ],
        "collections": [],
        "labels": [
            {
                "id": "01ARZ3NDEKTSV4RRFFQ69G5FAD",
                "zpl_available": true,
                "pdf_available": true,
                "png_available": false
            }
        ],
        "locker_reservation_window": null,
        "locker_assignments": null,
        "authorisations": null,
        "contacts": [
            {
                "id": "01ARZ3NDEKTSV4RRFFQ69G5FAC",
                "name": "Jane Doe",
                "email": "[email protected]",
                "phone": "+447700900123"
            }
        ],
        "returns": null,
        "created_at": "2025-01-01T00:00:00.000000Z",
        "updated_at": "2025-01-01T00:00:00.000000Z",
        "created_by": "01ARZ3NDEKTSV4RRFFQ69G5FAY"
    }
}
 

Example response (400):


{
    "message": "No account context set"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (404):


{
    "message": "Booking not found"
}
 

Request      

GET v1/bookings/{id}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the booking Example: 01ARZ3NDEKTSV4RRFFQ69G5FAV

Cancel the specified booking (DELETE).

requires authentication

Cancels a booking, removing it from active status. The booking must belong to the current account context. Only bookings with status Pending or Confirmed can be cancelled.

An optional cancellation reason may be provided in status_reason to explain why the booking was cancelled. Accepted values are cancelled_by_customer and cancelled_by_client.

Example request:
curl --request DELETE \
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"status_reason\": \"cancelled_by_customer\"
}"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "status_reason": "cancelled_by_customer"
};

fetch(url, {
    method: "DELETE",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV';
$response = $client->delete(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'json' => [
            'status_reason' => 'cancelled_by_customer',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV'
payload = {
    "status_reason": "cancelled_by_customer"
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('DELETE', url, headers=headers, json=payload)
response.json()

Example response (200):


{
    "message": "Booking cancelled",
    "booking_id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
    "reference_id": "BK-2025-001",
    "status": "cancelled",
    "status_reason_id": "01ARZ3NDEKTSV4RRFFQ69G5FAY",
    "status_reason": "cancelled_by_customer",
    "status_reason_label": "Cancelled by Customer"
}
 

Example response (400):


{
    "message": "No account context set"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (404):


{
    "message": "Booking not found"
}
 

Example response (422):


{
    "message": "Booking cannot be cancelled. Only bookings with Pending or Confirmed status can be cancelled. Current status: Completed."
}
 

Example response (422):


{
    "message": "The cancellation reason is not recognised. Accepted values: cancelled_by_customer, cancelled_by_client.",
    "errors": {
        "status_reason": [
            "The cancellation reason is not recognised. Accepted values: cancelled_by_customer, cancelled_by_client."
        ]
    }
}
 

Request      

DELETE v1/bookings/{id}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the booking to cancel Example: 01ARZ3NDEKTSV4RRFFQ69G5FAV

Body Parameters

status_reason   string  optional    

Optional reason for the cancellation. Accepted values: cancelled_by_customer (Cancelled by Customer), cancelled_by_client (Cancelled by Client), no_site_capacity (No Site Capacity). Example: cancelled_by_customer

Cancel the specified booking (POST shortcut).

requires authentication

Shortcut for cancelling a booking. Same behaviour as DELETE /v1/bookings/{id}. Only bookings with status Pending or Confirmed can be cancelled.

An optional cancellation reason may be provided in status_reason to explain why the booking was cancelled. Accepted values are cancelled_by_customer and cancelled_by_client.

Example request:
curl --request POST \
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/cancel" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"status_reason\": \"cancelled_by_customer\"
}"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/cancel"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "status_reason": "cancelled_by_customer"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/cancel';
$response = $client->post(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'json' => [
            'status_reason' => 'cancelled_by_customer',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/cancel'
payload = {
    "status_reason": "cancelled_by_customer"
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('POST', url, headers=headers, json=payload)
response.json()

Example response (200):


{
    "message": "Booking cancelled",
    "booking_id": "01ARZ3NDEKTSV4RRFFQ69G5FAV",
    "reference_id": "BK-2025-001",
    "status": "cancelled",
    "status_reason_id": "01ARZ3NDEKTSV4RRFFQ69G5FAY",
    "status_reason": "cancelled_by_customer",
    "status_reason_label": "Cancelled by Customer"
}
 

Example response (400):


{
    "message": "No account context set"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (404):


{
    "message": "Booking not found"
}
 

Example response (422):


{
    "message": "Booking cannot be cancelled. Only bookings with Pending or Confirmed status can be cancelled. Current status: Completed."
}
 

Example response (422):


{
    "message": "The cancellation reason is not recognised. Accepted values: cancelled_by_customer, cancelled_by_client.",
    "errors": {
        "status_reason": [
            "The cancellation reason is not recognised. Accepted values: cancelled_by_customer, cancelled_by_client."
        ]
    }
}
 

Request      

POST v1/bookings/{id}/cancel

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the booking to cancel Example: 01ARZ3NDEKTSV4RRFFQ69G5FAV

Body Parameters

status_reason   string  optional    

Optional reason for the cancellation. Accepted values: cancelled_by_customer (Cancelled by Customer), cancelled_by_client (Cancelled by Client), no_site_capacity (No Site Capacity). Example: cancelled_by_customer

Send booking confirmation to customer.

requires authentication

Sends booking confirmation notification via email and SMS. This includes any access codes if the booking has locker assignments.

Example request:
curl --request POST \
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/send-booking-confirmation" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/send-booking-confirmation"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/send-booking-confirmation';
$response = $client->post(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/send-booking-confirmation'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('POST', url, headers=headers)
response.json()

Example response (200):


{
    "message": "Booking confirmation notification queued successfully",
    "recipients": [
        {
            "email": "[email protected]",
            "phone": "+44 1234 567890"
        }
    ]
}
 

Example response (400):


{
    "message": "No customer contact information available"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (404):


{
    "message": "Booking not found"
}
 

Request      

POST v1/bookings/{id}/send-booking-confirmation

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the booking Example: 01ARZ3NDEKTSV4RRFFQ69G5FAV

Send booking reminder email.

requires authentication

Sends a reminder email before the booking starts with all access codes.

Example request:
curl --request POST \
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/send-reminder" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/send-reminder"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/send-reminder';
$response = $client->post(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/send-reminder'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('POST', url, headers=headers)
response.json()

Example response (200):


{
    "message": "Reminder notification queued successfully",
    "recipients": [
        {
            "email": "[email protected]",
            "phone": "+44 1234 567890"
        }
    ]
}
 

Example response (400):


{
    "message": "No customer contact information available"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (404):


{
    "message": "Booking not found"
}
 

Request      

POST v1/bookings/{id}/send-reminder

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the booking Example: 01ARZ3NDEKTSV4RRFFQ69G5FAV

Send expiry reminder email.

requires authentication

Sends a reminder email before the booking expires.

Example request:
curl --request POST \
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/send-expiry-reminder" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/send-expiry-reminder"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/send-expiry-reminder';
$response = $client->post(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/send-expiry-reminder'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('POST', url, headers=headers)
response.json()

Example response (200):


{
    "message": "Expiry reminder notification queued successfully",
    "recipients": [
        {
            "email": "[email protected]",
            "phone": "+44 1234 567890"
        }
    ]
}
 

Example response (400):


{
    "message": "No customer contact information available"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (404):


{
    "message": "Booking not found"
}
 

Request      

POST v1/bookings/{id}/send-expiry-reminder

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the booking Example: 01ARZ3NDEKTSV4RRFFQ69G5FAV

Send cancellation notice email.

requires authentication

Sends a cancellation notice when a booking is cancelled.

Example request:
curl --request POST \
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/send-cancellation-notice" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"cancellation_reason\": \"Customer request\"
}"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/send-cancellation-notice"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "cancellation_reason": "Customer request"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/send-cancellation-notice';
$response = $client->post(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'json' => [
            'cancellation_reason' => 'Customer request',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/send-cancellation-notice'
payload = {
    "cancellation_reason": "Customer request"
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('POST', url, headers=headers, json=payload)
response.json()

Example response (200):


{
    "message": "Cancellation notice queued successfully",
    "recipients": [
        {
            "email": "[email protected]",
            "phone": "+44 1234 567890"
        }
    ]
}
 

Example response (400):


{
    "message": "No customer contact information available"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (404):


{
    "message": "Booking not found"
}
 

Request      

POST v1/bookings/{id}/send-cancellation-notice

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the booking Example: 01ARZ3NDEKTSV4RRFFQ69G5FAV

Body Parameters

cancellation_reason   string  optional    

Reason for cancellation Example: Customer request

Get labels by booking ID.

requires authentication

Returns concatenated label data for all labels in a booking. Currently only ZPL concatenation is supported.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/labels" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"format\": \"architecto\"
}"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/labels"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "format": "architecto"
};

fetch(url, {
    method: "GET",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/labels';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'json' => [
            'format' => 'architecto',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/labels'
payload = {
    "format": "architecto"
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, json=payload)
response.json()

Request      

GET v1/bookings/{id}/labels

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the booking Example: 01ARZ3NDEKTSV4RRFFQ69G5FAV

Body Parameters

format   string  optional    

Example: architecto

Must be one of:
  • zpl
  • pdf
  • png

Add or update booking authorisations.

requires authentication

Adds or extends authorisation groups and locker users for an existing booking. The booking must belong to the current account context.

Example request:
curl --request POST \
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/authorisation" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"authorisation_group_ids\": [
        \"01ARZ3NDEKTSV4RRFFQ69G5FAY\"
    ],
    \"locker_user_ids\": [
        \"01ARZ3NDEKTSV4RRFFQ69G5FAZ\"
    ]
}"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/authorisation"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "authorisation_group_ids": [
        "01ARZ3NDEKTSV4RRFFQ69G5FAY"
    ],
    "locker_user_ids": [
        "01ARZ3NDEKTSV4RRFFQ69G5FAZ"
    ]
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/authorisation';
$response = $client->post(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'json' => [
            'authorisation_group_ids' => [
                '01ARZ3NDEKTSV4RRFFQ69G5FAY',
            ],
            'locker_user_ids' => [
                '01ARZ3NDEKTSV4RRFFQ69G5FAZ',
            ],
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/authorisation'
payload = {
    "authorisation_group_ids": [
        "01ARZ3NDEKTSV4RRFFQ69G5FAY"
    ],
    "locker_user_ids": [
        "01ARZ3NDEKTSV4RRFFQ69G5FAZ"
    ]
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('POST', url, headers=headers, json=payload)
response.json()

Example response (200):


{
    "message": "Authorisations updated"
}
 

Example response (400):


{
    "message": "No account context set"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (404):


{
    "message": "Booking not found"
}
 

Example response (422):


{
    "message": "The given data was invalid.",
    "errors": {
        "authorisation_group_ids.0": [
            "The selected authorisation group ids.0 is invalid."
        ]
    }
}
 

Request      

POST v1/bookings/{id}/authorisation

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the booking Example: 01ARZ3NDEKTSV4RRFFQ69G5FAV

Body Parameters

authorisation_group_ids   string[]  optional    

Array of authorisation group IDs to add

locker_user_ids   string[]  optional    

Array of locker user IDs to add

Generate lock codes for booking lockers.

requires authentication

Generates access codes for all lockers associated with a booking. The booking must belong to the current account context.

Example request:
curl --request POST \
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/generate-codes" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/generate-codes"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/generate-codes';
$response = $client->post(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/bookings/01ARZ3NDEKTSV4RRFFQ69G5FAV/generate-codes'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('POST', url, headers=headers)
response.json()

Example response (200):


{
    "message": "Lock codes generated",
    "codes": [
        {
            "locker_id": "01ARZ3NDEKTSV4RRFFQ69G5FAC",
            "code": "1234"
        }
    ]
}
 

Example response (400):


{
    "message": "No account context set"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (404):


{
    "message": "Booking not found"
}
 

Request      

POST v1/bookings/{id}/generate-codes

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the booking Example: 01ARZ3NDEKTSV4RRFFQ69G5FAV

Cabinets

Display a listing of cabinets.

requires authentication

Returns a list of cabinets with optional filtering by status or location.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/cabinets?status=active&latitude=51.5074&longitude=-0.1278&radius=10" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/cabinets"
);

const params = {
    "status": "active",
    "latitude": "51.5074",
    "longitude": "-0.1278",
    "radius": "10",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/cabinets';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'status' => 'active',
            'latitude' => '51.5074',
            'longitude' => '-0.1278',
            'radius' => '10',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/cabinets'
params = {
  'status': 'active',
  'latitude': '51.5074',
  'longitude': '-0.1278',
  'radius': '10',
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200):


{
    "data": [
        {
            "id": "01ARZ3NDEKTSV4RRFFQ69G5FAA",
            "name": "Cabinet A1",
            "status": "active",
            "total_active_lockers": 10,
            "total_available_lockers": 5,
            "active_locker_ids": [
                "01ARZ3NDEKTSV4RRFFQ69G5FC1",
                "01ARZ3NDEKTSV4RRFFQ69G5FC2"
            ]
        }
    ]
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Request      

GET v1/cabinets

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

status   string  optional    

Filter by cabinet status name Example: active

latitude   number  optional    

Latitude for location-based search (must include longitude and radius) Example: 51.5074

longitude   number  optional    

Longitude for location-based search (must include latitude and radius) Example: -0.1278

radius   number  optional    

Radius in kilometers for location-based search (must include latitude and longitude) Example: 10

Display the specified cabinet.

requires authentication

Returns detailed information about a specific cabinet.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/cabinets/01ARZ3NDEKTSV4RRFFQ69G5FAA" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/cabinets/01ARZ3NDEKTSV4RRFFQ69G5FAA"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/cabinets/01ARZ3NDEKTSV4RRFFQ69G5FAA';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/cabinets/01ARZ3NDEKTSV4RRFFQ69G5FAA'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200):


{
    "data": {
        "id": "01ARZ3NDEKTSV4RRFFQ69G5FAA",
        "name": "Cabinet A1",
        "status": "active",
        "total_active_lockers": 10,
        "total_available_lockers": 5,
        "active_locker_ids": [
            "01ARZ3NDEKTSV4RRFFQ69G5FC1",
            "01ARZ3NDEKTSV4RRFFQ69G5FC2"
        ]
    }
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (404):


{
    "message": "Cabinet not found"
}
 

Request      

GET v1/cabinets/{id}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the cabinet Example: 01ARZ3NDEKTSV4RRFFQ69G5FAA

Collection Schedules

Display a listing of collection schedules for a despatch centre.

requires authentication

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/despatch-centres/01ARZ3NDEKTSV4RRFFQ69G5FAW/collection-schedules" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/despatch-centres/01ARZ3NDEKTSV4RRFFQ69G5FAW/collection-schedules"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/despatch-centres/01ARZ3NDEKTSV4RRFFQ69G5FAW/collection-schedules';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/despatch-centres/01ARZ3NDEKTSV4RRFFQ69G5FAW/collection-schedules'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200):


{
    "data": [
        {
            "id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
            "despatch_centre_id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
            "name": "Weekday Morning Collection",
            "description": "Standard weekday collection window",
            "collection_start_time": "08:00:00",
            "collection_end_time": "10:00:00",
            "days_of_week": [
                0,
                1,
                2,
                3,
                4
            ],
            "is_active": true
        }
    ]
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (404):


{
    "message": "Despatch centre not found or does not belong to your account"
}
 

Request      

GET v1/despatch-centres/{despatchCentreId}/collection-schedules

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

despatchCentreId   string     

The ID of the despatch centre Example: 01ARZ3NDEKTSV4RRFFQ69G5FAW

Display the specified collection schedule.

requires authentication

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/despatch-centres/01ARZ3NDEKTSV4RRFFQ69G5FAW/collection-schedules/01ARZ3NDEKTSV4RRFFQ69G5FAX" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/despatch-centres/01ARZ3NDEKTSV4RRFFQ69G5FAW/collection-schedules/01ARZ3NDEKTSV4RRFFQ69G5FAX"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/despatch-centres/01ARZ3NDEKTSV4RRFFQ69G5FAW/collection-schedules/01ARZ3NDEKTSV4RRFFQ69G5FAX';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/despatch-centres/01ARZ3NDEKTSV4RRFFQ69G5FAW/collection-schedules/01ARZ3NDEKTSV4RRFFQ69G5FAX'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200):


{
    "data": {
        "id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
        "despatch_centre_id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
        "name": "Weekday Morning Collection",
        "description": "Standard weekday collection window",
        "collection_start_time": "08:00:00",
        "collection_end_time": "10:00:00",
        "days_of_week": [
            0,
            1,
            2,
            3,
            4
        ],
        "effective_from": "2025-01-01T00:00:00Z",
        "effective_until": null,
        "is_active": true
    }
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (404):


{
    "message": "Collection schedule not found"
}
 

Request      

GET v1/despatch-centres/{despatchCentreId}/collection-schedules/{collectionScheduleId}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

despatchCentreId   string     

The ID of the despatch centre Example: 01ARZ3NDEKTSV4RRFFQ69G5FAW

collectionScheduleId   string     

The ID of the collection schedule Example: 01ARZ3NDEKTSV4RRFFQ69G5FAX

Despatch Centres

Display a listing of despatch centres.

requires authentication

Returns a paginated list of despatch centres for the current account.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/despatch-centres?per_page=20&page=1" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/despatch-centres"
);

const params = {
    "per_page": "20",
    "page": "1",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/despatch-centres';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'per_page' => '20',
            'page' => '1',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/despatch-centres'
params = {
  'per_page': '20',
  'page': '1',
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200):


{
    "data": [
        {
            "id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
            "account_id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
            "name": "Main Warehouse",
            "description": "Primary despatch centre",
            "address_id": "01ARZ3NDEKTSV4RRFFQ69G5FAY",
            "address": {
                "id": "01ARZ3NDEKTSV4RRFFQ69G5FAY",
                "line_1": "123 Industrial Way",
                "line_2": null,
                "city": "London",
                "postcode": "SW1A 1AA",
                "latitude": 51.5074,
                "longitude": -0.1278
            },
            "access_instructions": "Enter through main gate",
            "special_instructions": null,
            "contact_phone": "+44 20 1234 5678",
            "contact_email": "[email protected]",
            "is_active": true
        }
    ],
    "pagination": {
        "current_page": 1,
        "per_page": 50,
        "total": 10,
        "last_page": 1
    }
}
 

Example response (400):


{
    "message": "No account context set"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Request      

GET v1/despatch-centres

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

per_page   integer  optional    

Number of items per page (max 100) Example: 20

page   integer  optional    

Page number Example: 1

Display the specified despatch centre.

requires authentication

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/despatch-centres/01ARZ3NDEKTSV4RRFFQ69G5FAW" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/despatch-centres/01ARZ3NDEKTSV4RRFFQ69G5FAW"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/despatch-centres/01ARZ3NDEKTSV4RRFFQ69G5FAW';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/despatch-centres/01ARZ3NDEKTSV4RRFFQ69G5FAW'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200):


{
    "data": {
        "id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
        "account_id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
        "name": "Main Warehouse",
        "description": "Primary despatch centre",
        "address_id": "01ARZ3NDEKTSV4RRFFQ69G5FAY",
        "address": {
            "id": "01ARZ3NDEKTSV4RRFFQ69G5FAY",
            "line_1": "123 Industrial Way",
            "line_2": null,
            "city": "London",
            "postcode": "SW1A 1AA",
            "latitude": 51.5074,
            "longitude": -0.1278
        },
        "access_instructions": "Enter through main gate",
        "is_active": true
    }
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (404):


{
    "message": "Despatch centre not found"
}
 

Request      

GET v1/despatch-centres/{id}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the despatch centre Example: 01ARZ3NDEKTSV4RRFFQ69G5FAW

Labels

Get ZPL label data by label ID.

requires authentication

Returns the ZPL (Zebra Programming Language) data for a specific label. The label must belong to a booking in the current account context.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/labels/1111111119/zpl" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/labels/1111111119/zpl"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/labels/1111111119/zpl';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/labels/1111111119/zpl'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200):


{
    "label": "^XA^FO50,50^FDTest ZPL Label^FS^XZ"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (404):


{
    "message": "Label not found"
}
 

Example response (404):


{
    "message": "ZPL data not available for this label"
}
 

Request      

GET v1/labels/{id}/zpl

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the label Example: 1111111119

Get PDF label data by label ID.

requires authentication

Returns the PDF binary data for a specific label. The label must belong to a booking in the current account context.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/labels/1111111119/pdf" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/labels/1111111119/pdf"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/labels/1111111119/pdf';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/labels/1111111119/pdf'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200, PDF binary data with Content-Type: application/pdf):



 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (404):


{
    "message": "Label not found"
}
 

Example response (404):


{
    "message": "PDF data not available for this label"
}
 

Request      

GET v1/labels/{id}/pdf

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the label Example: 1111111119

Get PNG label data by label ID.

requires authentication

Returns the PNG binary data for a specific label. The label must belong to a booking in the current account context.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/labels/1111111119/png" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/labels/1111111119/png"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/labels/1111111119/png';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/labels/1111111119/png'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200, PNG binary data with Content-Type: image/png):



 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (404):


{
    "message": "Label not found"
}
 

Example response (404):


{
    "message": "PNG data not available for this label"
}
 

Request      

GET v1/labels/{id}/png

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the label Example: 1111111119

Other

POST v1/integrations/fillout/responses

requires authentication

Example request:
curl --request POST \
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/integrations/fillout/responses" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"formId\": \"b\",
    \"formName\": \"n\",
    \"submission\": {
        \"submissionId\": \"b\",
        \"submissionTime\": \"2026-10-16T19:41:39\",
        \"lastUpdatedAt\": \"2026-10-16T19:41:39\"
    }
}"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/integrations/fillout/responses"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "formId": "b",
    "formName": "n",
    "submission": {
        "submissionId": "b",
        "submissionTime": "2026-10-16T19:41:39",
        "lastUpdatedAt": "2026-10-16T19:41:39"
    }
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/integrations/fillout/responses';
$response = $client->post(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'json' => [
            'formId' => 'b',
            'formName' => 'n',
            'submission' => [
                'submissionId' => 'b',
                'submissionTime' => '2026-10-16T19:41:39',
                'lastUpdatedAt' => '2026-10-16T19:41:39',
            ],
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/integrations/fillout/responses'
payload = {
    "formId": "b",
    "formName": "n",
    "submission": {
        "submissionId": "b",
        "submissionTime": "2026-10-16T19:41:39",
        "lastUpdatedAt": "2026-10-16T19:41:39"
    }
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('POST', url, headers=headers, json=payload)
response.json()

Request      

POST v1/integrations/fillout/responses

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Body Parameters

formId   string     

Must not be greater than 255 characters. Example: b

formName   string  optional    

Must not be greater than 255 characters. Example: n

submission   object     
submissionId   string  optional    

Must not be greater than 255 characters. Example: b

submissionTime   string  optional    

Must be a valid date. Example: 2026-10-16T19:41:39

lastUpdatedAt   string  optional    

Must be a valid date. Example: 2026-10-16T19:41:39

questions   object  optional    
urlParameters   object  optional    

GET v1/rates

requires authentication

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/rates" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"date\": \"2026-10-16T19:41:39\"
}"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/rates"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "date": "2026-10-16T19:41:39"
};

fetch(url, {
    method: "GET",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/rates';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'json' => [
            'date' => '2026-10-16T19:41:39',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/rates'
payload = {
    "date": "2026-10-16T19:41:39"
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, json=payload)
response.json()

Request      

GET v1/rates

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Body Parameters

date   string  optional    

Must be a valid date. Example: 2026-10-16T19:41:39

Reverse Flows

Display a listing of reverse flow strategies.

requires authentication

Returns a paginated list of reverse flow strategies available to the current account context. Reverse flow strategies define how items should be handled when they cannot be delivered or collected from lockers.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/reverse-flows?per_page=20&page=1" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/reverse-flows"
);

const params = {
    "per_page": "20",
    "page": "1",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/reverse-flows';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'per_page' => '20',
            'page' => '1',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/reverse-flows'
params = {
  'per_page': '20',
  'page': '1',
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200):


{
    "data": [
        {
            "id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
            "name": "return_to_sender",
            "description": "Return to Sender",
            "is_active": true,
            "is_default": true
        },
        {
            "id": "01ARZ3NDEKTSV4RRFFQ69G5FAY",
            "name": "dispose_of_item",
            "description": "Dispose of Item",
            "is_active": true,
            "is_default": false
        }
    ],
    "pagination": {
        "current_page": 1,
        "per_page": 20,
        "total": 2,
        "last_page": 1,
        "from": 1,
        "to": 2,
        "has_more_pages": false
    },
    "links": {
        "first": "http://example.com/api/v1/reverse-flows?page=1",
        "last": "http://example.com/api/v1/reverse-flows?page=1",
        "prev": null,
        "next": null
    }
}
 

Example response (400):


{
    "message": "No account context set"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Request      

GET v1/reverse-flows

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

per_page   integer  optional    

Number of items per page (max 100) Example: 20

page   integer  optional    

Page number Example: 1

Service Products

Display a listing of service products.

requires authentication

Returns a paginated list of service products available to the current account context. Service products define the types of booking services that can be used.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/service-products?per_page=20&page=1" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/service-products"
);

const params = {
    "per_page": "20",
    "page": "1",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/service-products';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'per_page' => '20',
            'page' => '1',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/service-products'
params = {
  'per_page': '20',
  'page': '1',
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200):


{
    "data": [
        {
            "id": "01ARZ3NDEKTSV4RRFFQ69G5FAZ",
            "name": "direct_locker_delivery",
            "description": "Bookings are collected from a despatch centre and delivered directly to a locker",
            "requires_collection": true,
            "requires_delivery": true,
            "requires_locker": true,
            "requires_sorting_hub": false,
            "is_active": true,
            "is_default": true
        },
        {
            "id": "01ARZ3NDEKTSV4RRFFQ69G5FAY",
            "name": "sorted_locker_delivery",
            "description": "Bookings are collected from a despatch centre, taken to our sort centre and then delivered to a locker optimally",
            "requires_collection": true,
            "requires_delivery": true,
            "requires_locker": true,
            "requires_sorting_hub": true,
            "is_active": true,
            "is_default": false
        }
    ],
    "pagination": {
        "current_page": 1,
        "per_page": 20,
        "total": 2,
        "last_page": 1,
        "from": 1,
        "to": 2,
        "has_more_pages": false
    },
    "links": {
        "first": "http://example.com/api/v1/service-products?page=1",
        "last": "http://example.com/api/v1/service-products?page=1",
        "prev": null,
        "next": null
    }
}
 

Example response (400):


{
    "message": "No account context set"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Request      

GET v1/service-products

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

per_page   integer  optional    

Number of items per page (max 100) Example: 20

page   integer  optional    

Page number Example: 1

Serviceability

List all serviceable postcode prefixes.

requires authentication

Returns a unique list of postcode prefixes mapped to active zones.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/serviceable-postcodes" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/serviceable-postcodes"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/serviceable-postcodes';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/serviceable-postcodes'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200):


{
    "data": [
        "E1",
        "N1",
        "SW1",
        "SE1"
    ]
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Request      

GET v1/serviceable-postcodes

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Sites

Display a listing of sites with search and pagination.

requires authentication

Returns a paginated list of active sites. Supports location-based filtering to find sites within a specified radius of coordinates.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/sites?latitude=51.5074&longitude=-0.1278&radius=10&postcode=SW1A+1AA&per_page=20&page=1" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/sites"
);

const params = {
    "latitude": "51.5074",
    "longitude": "-0.1278",
    "radius": "10",
    "postcode": "SW1A 1AA",
    "per_page": "20",
    "page": "1",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/sites';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'latitude' => '51.5074',
            'longitude' => '-0.1278',
            'radius' => '10',
            'postcode' => 'SW1A 1AA',
            'per_page' => '20',
            'page' => '1',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/sites'
params = {
  'latitude': '51.5074',
  'longitude': '-0.1278',
  'radius': '10',
  'postcode': 'SW1A 1AA',
  'per_page': '20',
  'page': '1',
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200):


{
    "data": [
        {
            "id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
            "name": "Downtown Location",
            "address": {
                "recipient": null,
                "line_1": "123 Main St",
                "line_2": null,
                "line_3": "Greater London",
                "city": "London",
                "postcode": "SW1A 1AA",
                "country": "United Kingdom",
                "contact_phone": null,
                "contact_email": null,
                "special_instructions": null,
                "latitude": 51.5074,
                "longitude": -0.1278
            },
            "latitude": 51.5074,
            "longitude": -0.1278,
            "access_instructions": "Enter through main entrance",
            "height_restriction": 2.5,
            "is_active": true,
            "distance": {
                "km": 2.5,
                "mi": 1.55
            },
            "site_access_codes": [
                {
                    "name": "Customer access code 1",
                    "code": "AB12CD34"
                }
            ]
        }
    ],
    "pagination": {
        "current_page": 1,
        "per_page": 50,
        "total": 25,
        "last_page": 1,
        "from": 1,
        "to": 25,
        "has_more_pages": false
    },
    "links": {
        "first": "http://example.com/api/v1/sites?page=1",
        "last": "http://example.com/api/v1/sites?page=1",
        "prev": null,
        "next": null
    }
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Request      

GET v1/sites

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

latitude   number  optional    

Latitude for location-based search (must include longitude and radius) Example: 51.5074

longitude   number  optional    

Longitude for location-based search (must include latitude and radius) Example: -0.1278

radius   number  optional    

Radius in kilometers for location-based search (must include latitude and longitude, or postcode when enabled) Example: 10

postcode   string  optional    

Postcode for location-based search (this may incur extra usage fees when enabled) Example: SW1A 1AA

per_page   integer  optional    

Number of items per page (max 100) Example: 20

page   integer  optional    

Page number Example: 1

Display the specified site.

requires authentication

Returns detailed information about a specific site.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/sites/01ARZ3NDEKTSV4RRFFQ69G5FAW" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/sites/01ARZ3NDEKTSV4RRFFQ69G5FAW"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/sites/01ARZ3NDEKTSV4RRFFQ69G5FAW';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/sites/01ARZ3NDEKTSV4RRFFQ69G5FAW'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200):


{
    "data": {
        "id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
        "name": "Downtown Location",
        "address": {
            "recipient": null,
            "line_1": "123 Main St",
            "line_2": null,
            "line_3": "Greater London",
            "city": "London",
            "postcode": "SW1A 1AA",
            "country": "United Kingdom",
            "contact_phone": null,
            "contact_email": null,
            "email": null,
            "special_instructions": null,
            "latitude": 51.5074,
            "longitude": -0.1278
        },
        "latitude": 51.5074,
        "longitude": -0.1278,
        "access_instructions": "Enter through main entrance",
        "height_restriction": 2.5,
        "is_active": true,
        "site_access_codes": [
            {
                "name": "Customer access code 1",
                "code": "AB12CD34"
            }
        ]
    }
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (404):


{
    "message": "Site not found"
}
 

Request      

GET v1/sites/{id}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the site Example: 01ARZ3NDEKTSV4RRFFQ69G5FAW

Token Management

Generate API token for account.

requires authentication

Creates a new API token for the authenticated user in the current account context. Requires Admin or Owner role in the current account.

Example request:
curl --request POST \
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/tokens/generate" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"token_name\": \"Production API Token\",
    \"expires_at\": \"2025-12-31T23:59:59Z\"
}"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/tokens/generate"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "token_name": "Production API Token",
    "expires_at": "2025-12-31T23:59:59Z"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/tokens/generate';
$response = $client->post(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'json' => [
            'token_name' => 'Production API Token',
            'expires_at' => '2025-12-31T23:59:59Z',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/tokens/generate'
payload = {
    "token_name": "Production API Token",
    "expires_at": "2025-12-31T23:59:59Z"
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('POST', url, headers=headers, json=payload)
response.json()

Example response (201):


{
    "token": "1|abcdefghijklmnopqrstuvwxyz1234567890",
    "token_name": "Production API Token",
    "account_id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
    "abilities": [
        "*"
    ],
    "expires_at": "2025-12-31T23:59:59.000000Z",
    "created_at": "2025-01-01T00:00:00.000000Z",
    "message": "API token generated successfully"
}
 

Example response (400):


{
    "message": "No account context set"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (422):


{
    "message": "The given data was invalid.",
    "errors": {
        "token_name": [
            "The token name field is required."
        ],
        "expires_at": [
            "The expires at must be a date after now."
        ]
    }
}
 

Request      

POST v1/tokens/generate

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Body Parameters

token_name   string     

Name for the token Example: Production API Token

expires_at   string  optional    

Expiration date and time (ISO 8601). Must be in the future Example: 2025-12-31T23:59:59Z

List API tokens for account.

requires authentication

Returns all API tokens for the authenticated user in the current account context. Requires Admin or Owner role in the current account.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/tokens?search=Production" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/tokens"
);

const params = {
    "search": "Production",
};
Object.keys(params)
    .forEach(key => url.searchParams.append(key, params[key]));

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/tokens';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'query' => [
            'search' => 'Production',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/tokens'
params = {
  'search': 'Production',
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers, params=params)
response.json()

Example response (200):


{
    "tokens": [
        {
            "id": 1,
            "name": "Production API Token",
            "abilities": [
                "*"
            ],
            "last_used_at": "2025-01-15T10:30:00.000000Z",
            "created_at": "2025-01-01T00:00:00.000000Z",
            "expires_at": "2025-12-31T23:59:59.000000Z"
        }
    ],
    "account_id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
    "total": 1
}
 

Example response (400):


{
    "message": "No account context set"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Request      

GET v1/tokens

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Query Parameters

search   string  optional    

Search tokens by name Example: Production

Revoke a specific API token.

requires authentication

Revokes a single API token by ID. Requires Admin or Owner role in the current account.

Example request:
curl --request DELETE \
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/tokens/1" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/tokens/1"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "DELETE",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/tokens/1';
$response = $client->delete(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/tokens/1'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('DELETE', url, headers=headers)
response.json()

Example response (200):


{
    "message": "API token revoked successfully"
}
 

Example response (400):


{
    "message": "No account context set"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (404):


{
    "message": "Token not found"
}
 

Request      

DELETE v1/tokens/{tokenId}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

tokenId   string     

The ID of the token to revoke Example: 1

Revoke all API tokens for account.

requires authentication

Revokes all API tokens for the authenticated user in the current account context. Requires Admin or Owner role in the current account.

Example request:
curl --request DELETE \
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/tokens" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/tokens"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "DELETE",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/tokens';
$response = $client->delete(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/tokens'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('DELETE', url, headers=headers)
response.json()

Example response (200):


{
    "message": "All API tokens revoked successfully",
    "deleted_count": 5
}
 

Example response (400):


{
    "message": "No account context set"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Request      

DELETE v1/tokens

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Webhooks

Display a listing of webhooks.

requires authentication

Returns all webhooks for the authenticated user's account.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200):


{
    "data": [
        {
            "id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
            "account_id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
            "name": "Production Webhook",
            "description": "Webhook for production events",
            "url": "https://example.com/webhook",
            "secret": "whsec_...",
            "event_types": [
                "booking.created",
                "booking.cancelled"
            ],
            "is_active": true,
            "created_at": "2024-01-01T00:00:00.000000Z",
            "updated_at": "2024-01-01T00:00:00.000000Z"
        }
    ]
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Request      

GET v1/webhooks

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Create a new webhook.

requires authentication

Creates a webhook for the authenticated user's account. A unique secret will be generated automatically.

Example request:
curl --request POST \
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"name\": \"Production Webhook\",
    \"description\": \"Webhook for production events\",
    \"url\": \"https:\\/\\/example.com\\/webhook\",
    \"event_types\": [
        \"booking.created\",
        \"booking.cancelled\"
    ],
    \"headers\": [
        {
            \"name\": \"Authorization\",
            \"value\": \"Bearer sk_live_abc123\"
        }
    ],
    \"is_active\": false
}"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "name": "Production Webhook",
    "description": "Webhook for production events",
    "url": "https:\/\/example.com\/webhook",
    "event_types": [
        "booking.created",
        "booking.cancelled"
    ],
    "headers": [
        {
            "name": "Authorization",
            "value": "Bearer sk_live_abc123"
        }
    ],
    "is_active": false
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks';
$response = $client->post(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'json' => [
            'name' => 'Production Webhook',
            'description' => 'Webhook for production events',
            'url' => 'https://example.com/webhook',
            'event_types' => [
                'booking.created',
                'booking.cancelled',
            ],
            'headers' => [
                [
                    'name' => 'Authorization',
                    'value' => 'Bearer sk_live_abc123',
                ],
            ],
            'is_active' => false,
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks'
payload = {
    "name": "Production Webhook",
    "description": "Webhook for production events",
    "url": "https:\/\/example.com\/webhook",
    "event_types": [
        "booking.created",
        "booking.cancelled"
    ],
    "headers": [
        {
            "name": "Authorization",
            "value": "Bearer sk_live_abc123"
        }
    ],
    "is_active": false
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('POST', url, headers=headers, json=payload)
response.json()

Example response (201):


{
    "data": {
        "id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
        "account_id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
        "name": "Production Webhook",
        "description": "Webhook for production events",
        "url": "https://example.com/webhook",
        "secret": "whsec_...",
        "event_types": [
            "booking.created",
            "booking.cancelled"
        ],
        "is_active": true,
        "created_at": "2024-01-01T00:00:00.000000Z",
        "updated_at": "2024-01-01T00:00:00.000000Z"
    }
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (422):


{
    "message": "The given data was invalid."
}
 

Request      

POST v1/webhooks

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

Body Parameters

name   string     

Name of the webhook Example: Production Webhook

description   string  optional    

Description of the webhook Example: Webhook for production events

url   string     

URL to send webhook events Example: https://example.com/webhook

event_types   string[]     

Array of event types to subscribe to

headers   string[]  optional    

Optional custom HTTP headers sent with each delivery

name   string     

Must not be greater than 255 characters. Example: m

value   string     

Must not be greater than 1024 characters. Example: y

is_active   boolean  optional    

Example: false

Display the specified webhook.

requires authentication

Returns detailed information about a specific webhook.

Example request:
curl --request GET \
    --get "https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks/architecto" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks/architecto"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks/architecto';
$response = $client->get(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks/architecto'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('GET', url, headers=headers)
response.json()

Example response (200):


{
    "data": {
        "id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
        "account_id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
        "name": "Production Webhook",
        "description": "Webhook for production events",
        "url": "https://example.com/webhook",
        "secret": "whsec_...",
        "event_types": [
            "booking.created",
            "booking.cancelled"
        ],
        "is_active": true,
        "created_at": "2024-01-01T00:00:00.000000Z",
        "updated_at": "2024-01-01T00:00:00.000000Z"
    }
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (404):


{
    "message": "Webhook not found"
}
 

Request      

GET v1/webhooks/{id}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the webhook. Example: architecto

webhook   string     

The ID of the webhook Example: 01ARZ3NDEKTSV4RRFFQ69G5FAW

Update the specified webhook.

requires authentication

Updates a webhook's details.

Example request:
curl --request PUT \
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks/architecto" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"name\": \"Updated Webhook\",
    \"description\": \"Updated description\",
    \"url\": \"https:\\/\\/example.com\\/webhook\",
    \"event_types\": [
        \"booking.created\"
    ],
    \"headers\": [
        {
            \"name\": \"X-API-Key\",
            \"value\": \"my-key\"
        }
    ],
    \"is_active\": true
}"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks/architecto"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "name": "Updated Webhook",
    "description": "Updated description",
    "url": "https:\/\/example.com\/webhook",
    "event_types": [
        "booking.created"
    ],
    "headers": [
        {
            "name": "X-API-Key",
            "value": "my-key"
        }
    ],
    "is_active": true
};

fetch(url, {
    method: "PUT",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks/architecto';
$response = $client->put(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
        'json' => [
            'name' => 'Updated Webhook',
            'description' => 'Updated description',
            'url' => 'https://example.com/webhook',
            'event_types' => [
                'booking.created',
            ],
            'headers' => [
                [
                    'name' => 'X-API-Key',
                    'value' => 'my-key',
                ],
            ],
            'is_active' => true,
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks/architecto'
payload = {
    "name": "Updated Webhook",
    "description": "Updated description",
    "url": "https:\/\/example.com\/webhook",
    "event_types": [
        "booking.created"
    ],
    "headers": [
        {
            "name": "X-API-Key",
            "value": "my-key"
        }
    ],
    "is_active": true
}
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('PUT', url, headers=headers, json=payload)
response.json()

Example response (200):


{
    "data": {
        "id": "01ARZ3NDEKTSV4RRFFQ69G5FAW",
        "account_id": "01ARZ3NDEKTSV4RRFFQ69G5FAX",
        "name": "Updated Webhook",
        "description": "Updated description",
        "url": "https://example.com/webhook",
        "secret": "whsec_...",
        "event_types": [
            "booking.created"
        ],
        "is_active": true,
        "created_at": "2024-01-01T00:00:00.000000Z",
        "updated_at": "2024-01-01T00:00:00.000000Z"
    }
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (404):


{
    "message": "Webhook not found"
}
 

Example response (422):


{
    "message": "The given data was invalid."
}
 

Request      

PUT v1/webhooks/{id}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the webhook. Example: architecto

webhook   string     

The ID of the webhook Example: 01ARZ3NDEKTSV4RRFFQ69G5FAW

Body Parameters

name   string  optional    

Name of the webhook Example: Updated Webhook

description   string  optional    

Description of the webhook Example: Updated description

url   string  optional    

URL to send webhook events Example: https://example.com/webhook

event_types   string[]  optional    

Array of event types to subscribe to

headers   string[]  optional    

Custom HTTP headers sent with each delivery

name   string     

Must not be greater than 255 characters. Example: m

value   string     

Must not be greater than 1024 characters. Example: y

is_active   boolean  optional    

Whether the webhook is active Example: true

Delete the specified webhook.

requires authentication

Permanently deletes a webhook.

Example request:
curl --request DELETE \
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks/architecto" \
    --header "Authorization: Bearer {YOUR_API_TOKEN}" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks/architecto"
);

const headers = {
    "Authorization": "Bearer {YOUR_API_TOKEN}",
    "Content-Type": "application/json",
    "Accept": "application/json",
};


fetch(url, {
    method: "DELETE",
    headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks/architecto';
$response = $client->delete(
    $url,
    [
        'headers' => [
            'Authorization' => 'Bearer {YOUR_API_TOKEN}',
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ],
    ]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json

url = 'https://shift-collect-api-nrchgrhp.on-forge.com/v1/webhooks/architecto'
headers = {
  'Authorization': 'Bearer {YOUR_API_TOKEN}',
  'Content-Type': 'application/json',
  'Accept': 'application/json'
}

response = requests.request('DELETE', url, headers=headers)
response.json()

Example response (200):


{
    "message": "Webhook deleted successfully"
}
 

Example response (401):


{
    "message": "Unauthenticated."
}
 

Example response (403):


{
    "message": "This action is unauthorised."
}
 

Example response (404):


{
    "message": "Webhook not found"
}
 

Request      

DELETE v1/webhooks/{id}

Headers

Authorization        

Example: Bearer {YOUR_API_TOKEN}

Content-Type        

Example: application/json

Accept        

Example: application/json

URL Parameters

id   string     

The ID of the webhook. Example: architecto

webhook   string     

The ID of the webhook Example: 01ARZ3NDEKTSV4RRFFQ69G5FAW