Locations
A location is a place where you keep boxes. Customers find locations by district, address and amenities.
#The Location object
| Name | Type | Description |
|---|---|---|
id | uuid | BoxLatvia's identifier. |
external_id | string | null | Your identifier, if you set one. |
name | string | Name. |
description | string | null | Description. |
address | string | null | Street address. |
district | string | null | District code. |
district_name | string | null | The district's name, for display. |
latitude | number | null | Latitude. |
longitude | number | null | Longitude. |
box_count | integer | How many boxes the location has. |
features | string[] | Amenity codes. |
missing | string[] | What is still needed before customers can see the location: any of address, coordinates, district, features. Empty when complete. |
created_at | datetime | ISO 8601, UTC. |
updated_at | datetime | ISO 8601, UTC. |
{
"id": "9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3",
"external_id": "WH-IMANTA",
"name": "Imanta noliktava",
"description": "Sausa, apsildāma noliktava ar 24/7 piekļuvi",
"address": "Kurzemes prospekts 1, Rīga",
"district": "riga-imanta",
"district_name": "Rīga - Imanta",
"latitude": 56.9496,
"longitude": 24.0536,
"box_count": 0,
"features": [
"24-7-piekluve",
"apkure",
"autostavvieta",
"video-noverosana",
"viedatslega"
],
"missing": [],
"created_at": "2026-11-07T09:30:12.418Z",
"updated_at": "2026-11-07T09:30:12.418Z"
}#Endpoints
#List locations
/v1/locationslocations:readYour locations, oldest first, one page at a time.
Query parameters
| Name | Type | Description |
|---|---|---|
limit | integer | Page size, 1 to 200. Default 50. |
cursor | string | The next_cursor of the previous page. Do not build cursors yourself. |
external_id | string | Only the location with this identifier of yours. |
Example
The last page has "next_cursor": null.
curl "$API/v1/locations?limit=2" \
-u "$CLIENT_ID:$CLIENT_SECRET"const API = "https://api.boxlatvia.lv";
const auth = "Basic " + btoa(`${CLIENT_ID}:${CLIENT_SECRET}`);
const res = await fetch(`${API}/v1/locations?limit=2`, {
headers: { Authorization: auth },
});
console.log(res.status, await res.json());import requests
API = "https://api.boxlatvia.lv"
r = requests.get(
f"{API}/v1/locations?limit=2",
auth=(CLIENT_ID, CLIENT_SECRET),
)
print(r.status_code, r.json()){
"data": [
{
"id": "9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3",
"external_id": "WH-IMANTA",
"name": "Imanta noliktava",
"description": "Sausa, apsildāma noliktava ar 24/7 piekļuvi",
"address": "Kurzemes prospekts 1, Rīga",
"district": "riga-imanta",
"district_name": "Rīga - Imanta",
"latitude": 56.9496,
"longitude": 24.0536,
"box_count": 0,
"features": [
"24-7-piekluve",
"apkure",
"autostavvieta",
"video-noverosana",
"viedatslega"
],
"missing": [],
"created_at": "2026-11-07T09:30:12.418Z",
"updated_at": "2026-11-07T09:30:12.418Z"
},
{
"id": "4758ace9-4962-4906-bb6c-736ec772cb37",
"external_id": null,
"name": "Teika noliktava",
"description": null,
"address": null,
"district": null,
"district_name": null,
"latitude": null,
"longitude": null,
"box_count": 0,
"features": [],
"missing": [
"address",
"coordinates",
"district",
"features"
],
"created_at": "2026-11-07T09:30:12.418Z",
"updated_at": "2026-11-07T09:30:12.418Z"
}
],
"next_cursor": "WyIyMDI2LTExLTA2IDEwOjAwOjAwLjAwMDAwMyswMCIsImE5NmM5NmQzLWFiMjAtNDYxYi1hZmExLTUwYWQ3YzU2ZTQ3ZSJd"
}Errors
| Status | When |
|---|---|
| 400 | The cursor is not one returned by a previous response. |
#Create a location
/v1/locationslocations:writeCreates a location. Only name is required: you can fill the rest in step by step; missing tells you what is left.
Query parameters
| Name | Type | Description |
|---|---|---|
validate_only | boolean | true runs every check and returns what would happen, but saves nothing. See dry runs. |
Headers
| Name | Type | Description |
|---|---|---|
Idempotency-Key | string | Optional. 1 to 200 printable characters. A retry with the same key returns the original result instead of creating a duplicate. See safe retries. |
Request body
| Name | Type | Description |
|---|---|---|
name required | string | Name of the location, up to 100 characters. Required when creating. |
description | string | null | Up to 250 characters. |
address | string | null | Street address, up to 250 characters. |
district | string | null | District code, see Reference data. |
latitude | number | null | −90 to 90. Send together with longitude. |
longitude | number | null | −180 to 180. Send together with latitude. |
external_id | string | Your own identifier, up to 100 characters, unique among your locations. Can be set once and then never changes. |
features | string[] | Amenity codes, see Reference data. Replaces the whole set; send [] to clear. At least 5 are needed before customers can find the location. |
Examples
The Location header and the ETag are returned with the new object.
curl -X POST "$API/v1/locations" \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ebfa60c9-5887-4526-9615-2d2ebdd9a0ed" \
-d '{
"name": "Imanta noliktava",
"external_id": "WH-IMANTA",
"description": "Sausa, apsildāma noliktava ar 24/7 piekļuvi",
"address": "Kurzemes prospekts 1, Rīga",
"district": "riga-imanta",
"latitude": 56.9496,
"longitude": 24.0536,
"features": [
"24-7-piekluve",
"apkure",
"video-noverosana",
"viedatslega",
"autostavvieta"
]
}'const API = "https://api.boxlatvia.lv";
const auth = "Basic " + btoa(`${CLIENT_ID}:${CLIENT_SECRET}`);
const res = await fetch(`${API}/v1/locations`, {
method: "POST",
headers: { Authorization: auth, "Content-Type": "application/json", "Idempotency-Key": "ebfa60c9-5887-4526-9615-2d2ebdd9a0ed" },
body: JSON.stringify({
"name": "Imanta noliktava",
"external_id": "WH-IMANTA",
"description": "Sausa, apsildāma noliktava ar 24/7 piekļuvi",
"address": "Kurzemes prospekts 1, Rīga",
"district": "riga-imanta",
"latitude": 56.9496,
"longitude": 24.0536,
"features": [
"24-7-piekluve",
"apkure",
"video-noverosana",
"viedatslega",
"autostavvieta"
]
}),
});
console.log(res.status, await res.json());import requests
API = "https://api.boxlatvia.lv"
r = requests.post(
f"{API}/v1/locations",
auth=(CLIENT_ID, CLIENT_SECRET),
headers={"Idempotency-Key": "ebfa60c9-5887-4526-9615-2d2ebdd9a0ed"},
json={
"name": "Imanta noliktava",
"external_id": "WH-IMANTA",
"description": "Sausa, apsildāma noliktava ar 24/7 piekļuvi",
"address": "Kurzemes prospekts 1, Rīga",
"district": "riga-imanta",
"latitude": 56.9496,
"longitude": 24.0536,
"features": [
"24-7-piekluve",
"apkure",
"video-noverosana",
"viedatslega",
"autostavvieta",
],
},
)
print(r.status_code, r.json()){
"id": "9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3",
"external_id": "WH-IMANTA",
"name": "Imanta noliktava",
"description": "Sausa, apsildāma noliktava ar 24/7 piekļuvi",
"address": "Kurzemes prospekts 1, Rīga",
"district": "riga-imanta",
"district_name": "Rīga - Imanta",
"latitude": 56.9496,
"longitude": 24.0536,
"box_count": 0,
"features": [
"24-7-piekluve",
"apkure",
"autostavvieta",
"video-noverosana",
"viedatslega"
],
"missing": [],
"created_at": "2026-11-07T09:30:12.418Z",
"updated_at": "2026-11-07T09:30:12.418Z"
}Everything still needed is listed in missing.
curl -X POST "$API/v1/locations" \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"name": "Teika noliktava"
}'const API = "https://api.boxlatvia.lv";
const auth = "Basic " + btoa(`${CLIENT_ID}:${CLIENT_SECRET}`);
const res = await fetch(`${API}/v1/locations`, {
method: "POST",
headers: { Authorization: auth, "Content-Type": "application/json" },
body: JSON.stringify({
"name": "Teika noliktava"
}),
});
console.log(res.status, await res.json());import requests
API = "https://api.boxlatvia.lv"
r = requests.post(
f"{API}/v1/locations",
auth=(CLIENT_ID, CLIENT_SECRET),
json={
"name": "Teika noliktava",
},
)
print(r.status_code, r.json()){
"id": "4758ace9-4962-4906-bb6c-736ec772cb37",
"external_id": null,
"name": "Teika noliktava",
"description": null,
"address": null,
"district": null,
"district_name": null,
"latitude": null,
"longitude": null,
"box_count": 0,
"features": [],
"missing": [
"address",
"coordinates",
"district",
"features"
],
"created_at": "2026-11-07T09:30:12.418Z",
"updated_at": "2026-11-07T09:30:12.418Z"
}Same checks, nothing saved. The response carries X-Validate-Only: true.
curl -X POST "$API/v1/locations?validate_only=true" \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"name": "Mārupes noliktava",
"district": "marupes-novads-pinki"
}'const API = "https://api.boxlatvia.lv";
const auth = "Basic " + btoa(`${CLIENT_ID}:${CLIENT_SECRET}`);
const res = await fetch(`${API}/v1/locations?validate_only=true`, {
method: "POST",
headers: { Authorization: auth, "Content-Type": "application/json" },
body: JSON.stringify({
"name": "Mārupes noliktava",
"district": "marupes-novads-pinki"
}),
});
console.log(res.status, await res.json());import requests
API = "https://api.boxlatvia.lv"
r = requests.post(
f"{API}/v1/locations?validate_only=true",
auth=(CLIENT_ID, CLIENT_SECRET),
json={
"name": "Mārupes noliktava",
"district": "marupes-novads-pinki",
},
)
print(r.status_code, r.json()){
"id": "bf18a79f-f762-4775-a17d-5ffa0623ebd7",
"external_id": null,
"name": "Mārupes noliktava",
"description": null,
"address": null,
"district": "marupes-novads-pinki",
"district_name": "Mārupes novads - Piņķi",
"latitude": null,
"longitude": null,
"box_count": 0,
"features": [],
"missing": [
"address",
"coordinates",
"features"
],
"created_at": "2026-11-07T09:30:12.418Z",
"updated_at": "2026-11-07T09:30:12.418Z"
}Every problem is reported at once.
curl -X POST "$API/v1/locations" \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"name": "",
"latitude": 95,
"longitude": 24.0536
}'const API = "https://api.boxlatvia.lv";
const auth = "Basic " + btoa(`${CLIENT_ID}:${CLIENT_SECRET}`);
const res = await fetch(`${API}/v1/locations`, {
method: "POST",
headers: { Authorization: auth, "Content-Type": "application/json" },
body: JSON.stringify({
"name": "",
"latitude": 95,
"longitude": 24.0536
}),
});
console.log(res.status, await res.json());import requests
API = "https://api.boxlatvia.lv"
r = requests.post(
f"{API}/v1/locations",
auth=(CLIENT_ID, CLIENT_SECRET),
json={
"name": "",
"latitude": 95,
"longitude": 24.0536,
},
)
print(r.status_code, r.json()){
"type": "https://api.boxlatvia.lv/problems/validation-failed",
"title": "Validation failed",
"status": 422,
"detail": "One or more fields are invalid.",
"request_id": "5f22a099-b84d-48eb-b078-6c5423a2175e",
"errors": [
{
"field": "name",
"message": "must not be empty"
},
{
"field": "latitude",
"message": "Number must be less than or equal to 90"
}
]
}curl -X POST "$API/v1/locations" \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"name": "Centra noliktava",
"district": "atlantis",
"features": [
"24-7-piekluve",
"sauna"
]
}'const API = "https://api.boxlatvia.lv";
const auth = "Basic " + btoa(`${CLIENT_ID}:${CLIENT_SECRET}`);
const res = await fetch(`${API}/v1/locations`, {
method: "POST",
headers: { Authorization: auth, "Content-Type": "application/json" },
body: JSON.stringify({
"name": "Centra noliktava",
"district": "atlantis",
"features": [
"24-7-piekluve",
"sauna"
]
}),
});
console.log(res.status, await res.json());import requests
API = "https://api.boxlatvia.lv"
r = requests.post(
f"{API}/v1/locations",
auth=(CLIENT_ID, CLIENT_SECRET),
json={
"name": "Centra noliktava",
"district": "atlantis",
"features": [
"24-7-piekluve",
"sauna",
],
},
)
print(r.status_code, r.json()){
"type": "https://api.boxlatvia.lv/problems/validation-failed",
"title": "Validation failed",
"status": 422,
"detail": "One or more fields are invalid.",
"request_id": "a52756bd-76c1-4887-9100-0e46deb7de27",
"errors": [
{
"field": "district",
"message": "is not a known district code"
},
{
"field": "features",
"message": "unknown or inactive feature code(s): sauna"
}
]
}The answer names the existing location in existing_id.
curl -X POST "$API/v1/locations" \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"name": "Cita noliktava",
"external_id": "WH-IMANTA"
}'const API = "https://api.boxlatvia.lv";
const auth = "Basic " + btoa(`${CLIENT_ID}:${CLIENT_SECRET}`);
const res = await fetch(`${API}/v1/locations`, {
method: "POST",
headers: { Authorization: auth, "Content-Type": "application/json" },
body: JSON.stringify({
"name": "Cita noliktava",
"external_id": "WH-IMANTA"
}),
});
console.log(res.status, await res.json());import requests
API = "https://api.boxlatvia.lv"
r = requests.post(
f"{API}/v1/locations",
auth=(CLIENT_ID, CLIENT_SECRET),
json={
"name": "Cita noliktava",
"external_id": "WH-IMANTA",
},
)
print(r.status_code, r.json()){
"type": "https://api.boxlatvia.lv/problems/duplicate-external-id",
"title": "Conflict",
"status": 409,
"detail": "A location with this external_id already exists.",
"request_id": "8d45de36-bd83-4dcf-b271-0e25822b5a2b",
"existing_id": "9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3",
"existing": "https://api.boxlatvia.lv/v1/locations/9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3"
}Errors
| Status | When |
|---|---|
| 409 | external_id is already used by another of your locations. |
| 422 | A value is invalid, or a district or feature code is unknown. |
#Retrieve a location
/v1/locations/{id}locations:readOne location. The response carries the ETag you need to change or delete it.
Path parameters
| Name | Type | Description |
|---|---|---|
id | uuid | The location's BoxLatvia id. |
Example
curl "$API/v1/locations/9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3" \
-u "$CLIENT_ID:$CLIENT_SECRET"const API = "https://api.boxlatvia.lv";
const auth = "Basic " + btoa(`${CLIENT_ID}:${CLIENT_SECRET}`);
const res = await fetch(`${API}/v1/locations/9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3`, {
headers: { Authorization: auth },
});
console.log(res.status, await res.json());import requests
API = "https://api.boxlatvia.lv"
r = requests.get(
f"{API}/v1/locations/9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3",
auth=(CLIENT_ID, CLIENT_SECRET),
)
print(r.status_code, r.json()){
"id": "9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3",
"external_id": "WH-IMANTA",
"name": "Imanta noliktava",
"description": "Sausa, apsildāma noliktava ar 24/7 piekļuvi",
"address": "Kurzemes prospekts 1, Rīga",
"district": "riga-imanta",
"district_name": "Rīga - Imanta",
"latitude": 56.9496,
"longitude": 24.0536,
"box_count": 0,
"features": [
"24-7-piekluve",
"apkure",
"autostavvieta",
"video-noverosana",
"viedatslega"
],
"missing": [],
"created_at": "2026-11-07T09:30:12.418Z",
"updated_at": "2026-11-07T09:30:12.418Z"
}Errors
| Status | When |
|---|---|
| 404 | No such location of yours. |
#Update a location
/v1/locations/{id}locations:writeChanges only the fields you send. external_id can be set once and then never changes.
Path parameters
| Name | Type | Description |
|---|---|---|
id | uuid | The location's BoxLatvia id. |
Query parameters
| Name | Type | Description |
|---|---|---|
validate_only | boolean | true runs every check and returns what would happen, but saves nothing. See dry runs. |
Headers
| Name | Type | Description |
|---|---|---|
If-Match required | string | The ETag from a previous GET, exactly as received. 428 if missing, 412 if the object changed since. See conditional updates. |
Request body (any of the fields)
| Name | Type | Description |
|---|---|---|
name required | string | Name of the location, up to 100 characters. Required when creating. |
description | string | null | Up to 250 characters. |
address | string | null | Street address, up to 250 characters. |
district | string | null | District code, see Reference data. |
latitude | number | null | −90 to 90. Send together with longitude. |
longitude | number | null | −180 to 180. Send together with latitude. |
external_id | string | Your own identifier, up to 100 characters, unique among your locations. Can be set once and then never changes. |
features | string[] | Amenity codes, see Reference data. Replaces the whole set; send [] to clear. At least 5 are needed before customers can find the location. |
Examples
curl -X PATCH "$API/v1/locations/9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3" \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/json" \
-H "If-Match: W/\"a15c541949287f3563009a45\"" \
-d '{
"address": "Kurzemes prospekts 3, Rīga",
"description": "Sausa, apsildāma noliktava ar uzbrauktuvi"
}'const API = "https://api.boxlatvia.lv";
const auth = "Basic " + btoa(`${CLIENT_ID}:${CLIENT_SECRET}`);
const res = await fetch(`${API}/v1/locations/9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3`, {
method: "PATCH",
headers: { Authorization: auth, "Content-Type": "application/json", "If-Match": "W/\"a15c541949287f3563009a45\"" },
body: JSON.stringify({
"address": "Kurzemes prospekts 3, Rīga",
"description": "Sausa, apsildāma noliktava ar uzbrauktuvi"
}),
});
console.log(res.status, await res.json());import requests
API = "https://api.boxlatvia.lv"
r = requests.patch(
f"{API}/v1/locations/9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3",
auth=(CLIENT_ID, CLIENT_SECRET),
headers={"If-Match": "W/\"a15c541949287f3563009a45\""},
json={
"address": "Kurzemes prospekts 3, Rīga",
"description": "Sausa, apsildāma noliktava ar uzbrauktuvi",
},
)
print(r.status_code, r.json()){
"id": "9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3",
"external_id": "WH-IMANTA",
"name": "Imanta noliktava",
"description": "Sausa, apsildāma noliktava ar uzbrauktuvi",
"address": "Kurzemes prospekts 3, Rīga",
"district": "riga-imanta",
"district_name": "Rīga - Imanta",
"latitude": 56.9496,
"longitude": 24.0536,
"box_count": 0,
"features": [
"24-7-piekluve",
"apkure",
"autostavvieta",
"video-noverosana",
"viedatslega"
],
"missing": [],
"created_at": "2026-11-07T09:30:12.418Z",
"updated_at": "2026-11-07T14:05:41.092Z"
}curl -X PATCH "$API/v1/locations/9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3" \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"address": "Kurzemes prospekts 3, Rīga"
}'const API = "https://api.boxlatvia.lv";
const auth = "Basic " + btoa(`${CLIENT_ID}:${CLIENT_SECRET}`);
const res = await fetch(`${API}/v1/locations/9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3`, {
method: "PATCH",
headers: { Authorization: auth, "Content-Type": "application/json" },
body: JSON.stringify({
"address": "Kurzemes prospekts 3, Rīga"
}),
});
console.log(res.status, await res.json());import requests
API = "https://api.boxlatvia.lv"
r = requests.patch(
f"{API}/v1/locations/9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3",
auth=(CLIENT_ID, CLIENT_SECRET),
json={
"address": "Kurzemes prospekts 3, Rīga",
},
)
print(r.status_code, r.json()){
"type": "https://api.boxlatvia.lv/problems/precondition-required",
"title": "Precondition required",
"status": 428,
"detail": "Send the current version in an If-Match header (the ETag from a GET of this resource).",
"request_id": "f61a59eb-da5b-4d6f-8308-caa9ddd62ba6"
}Someone changed the location after you read it. Read it again and retry.
curl -X PATCH "$API/v1/locations/9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3" \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/json" \
-H "If-Match: W/\"a15c541949287f3563009a45\"" \
-d '{
"address": "Cita adrese"
}'const API = "https://api.boxlatvia.lv";
const auth = "Basic " + btoa(`${CLIENT_ID}:${CLIENT_SECRET}`);
const res = await fetch(`${API}/v1/locations/9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3`, {
method: "PATCH",
headers: { Authorization: auth, "Content-Type": "application/json", "If-Match": "W/\"a15c541949287f3563009a45\"" },
body: JSON.stringify({
"address": "Cita adrese"
}),
});
console.log(res.status, await res.json());import requests
API = "https://api.boxlatvia.lv"
r = requests.patch(
f"{API}/v1/locations/9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3",
auth=(CLIENT_ID, CLIENT_SECRET),
headers={"If-Match": "W/\"a15c541949287f3563009a45\""},
json={
"address": "Cita adrese",
},
)
print(r.status_code, r.json()){
"type": "https://api.boxlatvia.lv/problems/precondition-failed",
"title": "Precondition failed",
"status": 412,
"detail": "The resource changed since you read it. GET it again and retry with the new ETag.",
"request_id": "98ae51e1-6505-43f4-8589-b524d2dd65c2"
}Errors
| Status | When |
|---|---|
| 404 | No such location of yours. |
| 412 | The location changed since you read it. |
| 422 | A value is invalid, or external_id was already set. |
| 428 | If-Match is missing. |
#Create or update by your own id
/v1/locations/by-external-id/{external_id}locations:writeCreates the location if your id is new, otherwise updates the fields you send. No If-Match is needed: meant for feeds that should win.
Path parameters
| Name | Type | Description |
|---|---|---|
external_id | string | Your identifier for the location. |
Query parameters
| Name | Type | Description |
|---|---|---|
validate_only | boolean | true runs every check and returns what would happen, but saves nothing. See dry runs. |
Request body
| Name | Type | Description |
|---|---|---|
name required | string | Name of the location, up to 100 characters. Required when creating. |
description | string | null | Up to 250 characters. |
address | string | null | Street address, up to 250 characters. |
district | string | null | District code, see Reference data. |
latitude | number | null | −90 to 90. Send together with longitude. |
longitude | number | null | −180 to 180. Send together with latitude. |
external_id | string | Your own identifier, up to 100 characters, unique among your locations. Can be set once and then never changes. |
features | string[] | Amenity codes, see Reference data. Replaces the whole set; send [] to clear. At least 5 are needed before customers can find the location. |
Examples
A new location needs a name.
curl -X PUT "$API/v1/locations/by-external-id/WH-PINKI" \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"name": "Piņķu noliktava",
"address": "Priedaines iela 19, Piņķi",
"district": "marupes-novads-pinki"
}'const API = "https://api.boxlatvia.lv";
const auth = "Basic " + btoa(`${CLIENT_ID}:${CLIENT_SECRET}`);
const res = await fetch(`${API}/v1/locations/by-external-id/WH-PINKI`, {
method: "PUT",
headers: { Authorization: auth, "Content-Type": "application/json" },
body: JSON.stringify({
"name": "Piņķu noliktava",
"address": "Priedaines iela 19, Piņķi",
"district": "marupes-novads-pinki"
}),
});
console.log(res.status, await res.json());import requests
API = "https://api.boxlatvia.lv"
r = requests.put(
f"{API}/v1/locations/by-external-id/WH-PINKI",
auth=(CLIENT_ID, CLIENT_SECRET),
json={
"name": "Piņķu noliktava",
"address": "Priedaines iela 19, Piņķi",
"district": "marupes-novads-pinki",
},
)
print(r.status_code, r.json()){
"id": "154ab2ad-0419-4cb2-a214-cc8d5e8b032c",
"external_id": "WH-PINKI",
"name": "Piņķu noliktava",
"description": null,
"address": "Priedaines iela 19, Piņķi",
"district": "marupes-novads-pinki",
"district_name": "Mārupes novads - Piņķi",
"latitude": null,
"longitude": null,
"box_count": 0,
"features": [],
"missing": [
"coordinates",
"features"
],
"created_at": "2026-11-07T09:30:12.418Z",
"updated_at": "2026-11-07T09:30:12.418Z"
}Only the fields you send change.
curl -X PUT "$API/v1/locations/by-external-id/WH-PINKI" \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"description": "Jauna noliktava ar uzbrauktuvi"
}'const API = "https://api.boxlatvia.lv";
const auth = "Basic " + btoa(`${CLIENT_ID}:${CLIENT_SECRET}`);
const res = await fetch(`${API}/v1/locations/by-external-id/WH-PINKI`, {
method: "PUT",
headers: { Authorization: auth, "Content-Type": "application/json" },
body: JSON.stringify({
"description": "Jauna noliktava ar uzbrauktuvi"
}),
});
console.log(res.status, await res.json());import requests
API = "https://api.boxlatvia.lv"
r = requests.put(
f"{API}/v1/locations/by-external-id/WH-PINKI",
auth=(CLIENT_ID, CLIENT_SECRET),
json={
"description": "Jauna noliktava ar uzbrauktuvi",
},
)
print(r.status_code, r.json()){
"id": "154ab2ad-0419-4cb2-a214-cc8d5e8b032c",
"external_id": "WH-PINKI",
"name": "Piņķu noliktava",
"description": "Jauna noliktava ar uzbrauktuvi",
"address": "Priedaines iela 19, Piņķi",
"district": "marupes-novads-pinki",
"district_name": "Mārupes novads - Piņķi",
"latitude": null,
"longitude": null,
"box_count": 0,
"features": [],
"missing": [
"coordinates",
"features"
],
"created_at": "2026-11-07T09:30:12.418Z",
"updated_at": "2026-11-07T14:05:41.092Z"
}Errors
| Status | When |
|---|---|
| 422 | A value is invalid, or the body contains a different external_id. |
#Delete a location
/v1/locations/{id}locations:writeDeletes the location and its pictures. Refused while it still has boxes.
Path parameters
| Name | Type | Description |
|---|---|---|
id | uuid | The location's BoxLatvia id. |
Query parameters
| Name | Type | Description |
|---|---|---|
validate_only | boolean | true runs every check and returns what would happen, but saves nothing. See dry runs. |
Headers
| Name | Type | Description |
|---|---|---|
If-Match required | string | The ETag from a previous GET, exactly as received. 428 if missing, 412 if the object changed since. See conditional updates. |
Examples
curl -X DELETE "$API/v1/locations/2a8487f7-145e-40c0-ac01-c918a2f7c759" \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-H "If-Match: W/\"d7761dc4eb50ce8a08ae74d4\""const API = "https://api.boxlatvia.lv";
const auth = "Basic " + btoa(`${CLIENT_ID}:${CLIENT_SECRET}`);
const res = await fetch(`${API}/v1/locations/2a8487f7-145e-40c0-ac01-c918a2f7c759`, {
method: "DELETE",
headers: { Authorization: auth, "If-Match": "W/\"d7761dc4eb50ce8a08ae74d4\"" },
});
console.log(res.status); // 204, no bodyimport requests
API = "https://api.boxlatvia.lv"
r = requests.delete(
f"{API}/v1/locations/2a8487f7-145e-40c0-ac01-c918a2f7c759",
auth=(CLIENT_ID, CLIENT_SECRET),
headers={"If-Match": "W/\"d7761dc4eb50ce8a08ae74d4\""},
)
print(r.status_code) # 204, no bodycurl -X DELETE "$API/v1/locations/9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3" \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-H "If-Match: W/\"690d868c2dd969cc637a8941\""const API = "https://api.boxlatvia.lv";
const auth = "Basic " + btoa(`${CLIENT_ID}:${CLIENT_SECRET}`);
const res = await fetch(`${API}/v1/locations/9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3`, {
method: "DELETE",
headers: { Authorization: auth, "If-Match": "W/\"690d868c2dd969cc637a8941\"" },
});
console.log(res.status, await res.json());import requests
API = "https://api.boxlatvia.lv"
r = requests.delete(
f"{API}/v1/locations/9d80d5f4-d17a-4f3e-99f6-4ab43b132bc3",
auth=(CLIENT_ID, CLIENT_SECRET),
headers={"If-Match": "W/\"690d868c2dd969cc637a8941\""},
)
print(r.status_code, r.json()){
"type": "https://api.boxlatvia.lv/problems/location-has-boxes",
"title": "Conflict",
"status": 409,
"detail": "This location still has 2 box(es). Delete or move them first.",
"request_id": "fa8d71d9-3e96-420a-b803-839b592d6a56",
"box_count": 2
}Errors
| Status | When |
|---|---|
| 404 | No such location of yours. |
| 409 | The location still has boxes: delete or move them first. |
| 412 | The location changed since you read it. |
| 428 | If-Match is missing. |