Data Management
Create, update, delete, retrieve, and replace store assets in your Woosmap project.
Complete API Specification: Data Management API Reference
What is the Data Management Endpoint?
Manage the store and asset data within your Woosmap project. It provides full CRUD (Create, Read, Update, Delete) operations through standard HTTP methods, supporting batch imports up to 15MB, along with an atomic replace operation for swapping entire datasets without downtime.
What It Does
This endpoint handles the complete lifecycle of your location data. You can add new assets in batch using POST,
update existing assets with PUT, retrieve assets as GeoJSON with GET, remove individual
or all assets with DELETE, and atomically replace your entire dataset using the replace operation. All write
operations accept JSON payloads containing an array of store objects, each with a unique storeId, name, and
geographic coordinates.
Key Characteristics
Data Management is designed for server-side workflows where you need to populate, maintain, and synchronize your
location data. All write operations (POST, PUT, DELETE) require a private key and are strictly
server-side. Read operations (GET) can use either a private or public key. Batch operations are atomic per
request, if any asset in a batch fails validation, the entire batch is rejected. The storeId you assign to each
asset is your stable identifier used across all operations.
When to Use This Endpoint
Use Data Management to import your stores and locations into Woosmap, keep your asset data in sync with your internal systems, remove outdated locations, or perform full dataset replacements during scheduled data refreshes. It is the entry point for populating the data that powers Search and Autocomplete.
Don’t use Data Management for searching or querying your assets; that’s what Search is for. If you need users to find stores interactively, use Autocomplete instead.
New to the API? Start with the Making Your First Request tutorial or follow the Integration Path guide for the recommended setup workflow.
API Endpoint
POST|GET|PUT|DELETE https://api.woosmap.com/stores
Authentication
Authenticate using either a key (public API key for client-side read requests) or private_key (required for all
write operations). Private keys should be kept secret and never exposed in client code.
| Key | Description |
|---|---|
| private_key | A private key is used for server api calls (POST, PUT and DELETE) where modification of the data occurs. |
| key | A public key is used client side to fetch your project data. |
The private key can modify and delete data, so it must remain private. The public key can be made public since it’s used client side.
# Server-side (write operations)
https://api.woosmap.com/stores?private_key=YOUR_PRIVATE_KEY
# Client-side (read only)
https://api.woosmap.com/stores?key=YOUR_PUBLIC_KEY
For complete authentication details and security best practices, see API Keys Documentation.
Operations Overview
The Data Management endpoint supports five operations via standard HTTP methods:
| Operation | Method | Description |
|---|---|---|
| Add Assets | POST |
Create new assets in batch |
| Update Assets | PUT |
Modify existing assets in batch |
| Delete Assets | DELETE |
Remove one, several, or all assets |
| Get Assets | GET |
Retrieve all assets or a specific asset by storeId |
| Replace Assets | POST |
Atomically replace all assets with a new dataset |
All write operations require the private_key parameter. The request body for POST, PUT, and replace must be
a JSON object with a stores array. Each element must follow the data structure defined below.
Request Body Format
{
"stores": [
{
"storeId": "unique identifier",
"name": "Store Name",
"location": {
"lat": 43.6,
"lng": 3.883
}
}
]
}
For a more complete store example including types, tags, user properties, and opening hours, see the API Reference.
Data Structure
Required Data
An asset element has the following minimal structure (more complete store example):
{
"storeId": "unique identifier",
"name": "Store Name",
"location": {
"lat": 43.6,
"lng": 3.883
}
}
storeId, name and location are mandatory, everything else is optional.
The storeId you assign in request bodies (camelCase) is returned as store_id (snake_case) in API responses. When
filtering via the Query Syntax, use the field name idstore.
The storeId field must be a unique identifier for your store and match the following regexp [a-zA-Z0-9_]+. Or in
English, uppercase and lowercase alphanumeric characters and underscores.
Optional Data
types : An array of strings, with the types of the store.
{
"types": ["book_store", "library"]
}
tags: An array of strings, of useful tags for filtering and grouping.
{
"tags": ["science", "comics"]
}
address: An address object for the store.
{
"address": {
"lines": ["Road name", "Another line of address"],
"countryCode": "FR",
"city": "Paris",
"zipcode": "75000"
}
}
contact: An object for the contact details of your asset, with optional website, phone and email values.
{
"contact": {
"website": "website url",
"phone": "phone number",
"email": "contact email"
}
}
openingHours: An object to define the opening times of your store.
In this example the store will be open between 8:30am and 7:30pm every day except sunday (7) where it’ll be closed.
The december 24th 2015 the store will be open from 9:00am to 6:00pm and the december 25th 2015 the store will be closed.
For more details concerning Open Hours see the dedicated page Opening Hours.
{
"openingHours": {
"timezone": "Europe/Paris",
"usual": {
"7": [],
"default": [{ "start": "08:30", "end": "19:30" }]
},
"special": {
"2015-12-24": [{ "start": "09:00", "end": "18:00" }],
"2015-12-25": []
}
}
}
userProperties: An object containing additional user-defined data.
{
"rating": 5,
"internal_id": "123abc"
}
localizedNames: You can define alternate names for your assets. These localized names are useful for multi-language integrations.
Combined with the Autocomplete endpoint, you can let your users find your store in their native language.
{
"localizedNames": {
"ar": "\u0645\u0631\u0643\u0632 \u0641\u064a\u0644\u064a\u062a\u0632\u064a \u0627\u0644\u062a\u062c\u0627\u0631\u064a",
"fr": "Centre Commercial Velizy",
"it": "Centro Commerciale Velizy",
"gb": "Velizy Shopping Center",
"id": "Pusat Perbelanjaan Velizy",
"ko": "\ubc38\ub9ac\uc9c0 \uc1fc\ud551\uc13c\ud130",
"sv": "V\u00e9lizy, galleria",
"th": "\u0e28\u0e39\u0e19\u0e22\u0e4c\u0e2a\u0e23\u0e23\u0e1e\u0e2a\u0e34\u0e19\u0e04\u0e49\u0e32 Velizy Shopping Center",
"tr": "Velizy Al\u0131\u015fveri\u015f Merkezi"
}
}
Add Assets
Create assets in a batch.
Warning: storeId must not exist when using POST method, if one store already exists, the batch will be refused.
https://api.woosmap.com/stores
?private_key=YOUR_PRIVATE_API_KEY
curl -L 'https://api.woosmap.com/stores?private_key=YOUR_PRIVATE_API_KEY' \
-H 'content-type: application/json' \
-d '{
"stores": [
{
"storeId": "store_123",
"name": "My first cool store",
"location": {
"lat": 43.61,
"lng": 3.88
}
}
]
}'
const axios = require('axios');
let data = JSON.stringify({
"stores": [
{
"storeId": "store_123",
"name": "My first cool store",
"location": {
"lat": 43.61,
"lng": 3.88
}
}
]
});
let config = {
method: 'post',
maxBodyLength: Infinity,
url: 'https://api.woosmap.com/stores?private_key=YOUR_PRIVATE_API_KEY',
headers: {
'content-type': 'application/json'
},
data : data
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
import requests
import json
url = "https://api.woosmap.com/stores?private_key=YOUR_PRIVATE_API_KEY"
payload = json.dumps({
"stores": [
{
"storeId": "store_123",
"name": "My first cool store",
"location": {
"lat": 43.61,
"lng": 3.88
}
}
]
})
headers = {
'content-type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n \"stores\": [\n {\n \"storeId\": \"store_123\",\n \"name\": \"My first cool store\",\n \"location\": {\n \"lat\": 43.61,\n \"lng\": 3.88\n }\n }\n ]\n}");
Request request = new Request.Builder()
.url("https://api.woosmap.com/stores?private_key=YOUR_PRIVATE_API_KEY")
.method("POST", body)
.addHeader("content-type", "application/json")
.build();
Response response = client.newCall(request).execute();
require "uri"
require "json"
require "net/http"
url = URI("https://api.woosmap.com/stores?private_key=YOUR_PRIVATE_API_KEY")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["content-type"] = "application/json"
request.body = JSON.dump({
"stores": [
{
"storeId": "store_123",
"name": "My first cool store",
"location": {
"lat": 43.61,
"lng": 3.88
}
}
]
})
response = https.request(request)
puts response.read_body
Complete Sample
For a more complete store example, see the API Reference.
Update Assets
Modify existing assets. You can modify any field. Location, name, types, tags, user properties, opening hours, and more.
Warning: storeId must exist when using PUT method, if one asset does not exist, the batch will be refused.
https://api.woosmap.com/stores
?private_key=YOUR_PRIVATE_API_KEY
curl -L -X PUT 'https://api.woosmap.com/stores?private_key=YOUR_PRIVATE_API_KEY' \
-H 'content-type: application/json' \
-d '{
"stores": [
{
"storeId": "store_123",
"name": "My amazing store",
"location": {
"lat": 43.61,
"lng": 3.88
}
}
]
}'
const axios = require('axios');
let data = JSON.stringify({
"stores": [
{
"storeId": "store_123",
"name": "My amazing store",
"location": {
"lat": 43.61,
"lng": 3.88
}
}
]
});
let config = {
method: 'put',
maxBodyLength: Infinity,
url: 'https://api.woosmap.com/stores?private_key=YOUR_PRIVATE_API_KEY',
headers: {
'content-type': 'application/json'
},
data : data
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
import requests
import json
url = "https://api.woosmap.com/stores?private_key=YOUR_PRIVATE_API_KEY"
payload = json.dumps({
"stores": [
{
"storeId": "store_123",
"name": "My amazing store",
"location": {
"lat": 43.61,
"lng": 3.88
}
}
]
})
headers = {
'content-type': 'application/json'
}
response = requests.request("PUT", url, headers=headers, data=payload)
print(response.text)
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n \"stores\": [\n {\n \"storeId\": \"store_123\",\n \"name\": \"My amazing store\",\n \"location\": {\n \"lat\": 43.61,\n \"lng\": 3.88\n }\n }\n ]\n}");
Request request = new Request.Builder()
.url("https://api.woosmap.com/stores?private_key=YOUR_PRIVATE_API_KEY")
.method("PUT", body)
.addHeader("content-type", "application/json")
.build();
Response response = client.newCall(request).execute();
require "uri"
require "json"
require "net/http"
url = URI("https://api.woosmap.com/stores?private_key=YOUR_PRIVATE_API_KEY")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Put.new(url)
request["content-type"] = "application/json"
request.body = JSON.dump({
"stores": [
{
"storeId": "store_123",
"name": "My amazing store",
"location": {
"lat": 43.61,
"lng": 3.88
}
}
]
})
response = https.request(request)
puts response.read_body
The restrictions on POST and PUT on storeIds are made to ensure identifier stability.
Delete Assets
Remove one or more assets using the DELETE method. The storeId is the id you defined. To delete several
assets, use a comma to separate the IDs.
https://api.woosmap.com/stores/
?private_key=YOUR_PRIVATE_API_KEY
&query=idstore%3A%3Dstore_123
curl -L -X DELETE 'https://api.woosmap.com/stores/?query=idstore%3A%3Dstore_123&private_key=YOUR_PRIVATE_API_KEY'
const axios = require('axios');
let config = {
method: 'delete',
maxBodyLength: Infinity,
url: 'https://api.woosmap.com/stores/?query=idstore%3A%3Dstore_123&private_key=YOUR_PRIVATE_API_KEY',
headers: { }
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
import requests
url = "https://api.woosmap.com/stores/?query=idstore%3A%3Dstore_123&private_key=YOUR_PRIVATE_API_KEY"
payload = {}
headers = {}
response = requests.request("DELETE", url, headers=headers, data=payload)
print(response.text)
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
.url("https://api.woosmap.com/stores/?query=idstore%3A%3Dstore_123&private_key=YOUR_PRIVATE_API_KEY")
.method("DELETE", body)
.build();
Response response = client.newCall(request).execute();
require "uri"
require "net/http"
url = URI("https://api.woosmap.com/stores/?query=idstore%3A%3Dstore_123&private_key=YOUR_PRIVATE_API_KEY")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Delete.new(url)
response = https.request(request)
puts response.read_body
To delete all assets in a project, omit the storeId
curl -X DELETE 'https://api.woosmap.com/stores?private_key=YOUR_PRIVATE_KEY'
Get Assets
Use the GET method to retrieve your data. The API returns a GeoJSON response.
curl 'https://api.woosmap.com/stores?private_key=YOUR_PRIVATE_KEY'
You can also retrieve a specific asset by its storeId:
curl 'https://api.woosmap.com/stores/YOUR_STORE_ID?private_key=YOUR_PRIVATE_KEY'
Your assets can also be visualized with the Store Locator Widget associated with your project in the Woosmap Console (Widgets tab).
For querying and filtering your assets, use the Search Query endpoint.
Replace Assets
You can replace all assets of a Project making a POST request on the /stores/replace endpoint. This will delete all
previous assets and import assets from the JSON payload.
https://api.woosmap.com/stores/replace
?private_key=YOUR_PRIVATE_API_KEY
curl -L 'https://api.woosmap.com/stores/replace?private_key=YOUR_PRIVATE_API_KEY' \
-H 'content-type: application/json' \
-d '{
"stores": [
{
"storeId": "store_123",
"name": "My first cool store",
"location": {
"lat": 43.61,
"lng": 3.88
}
}
]
}'
const axios = require('axios');
let data = JSON.stringify({
"stores": [
{
"storeId": "store_123",
"name": "My first cool store",
"location": {
"lat": 43.61,
"lng": 3.88
}
}
]
});
let config = {
method: 'post',
maxBodyLength: Infinity,
url: 'https://api.woosmap.com/stores/replace?private_key=YOUR_PRIVATE_API_KEY',
headers: {
'content-type': 'application/json'
},
data : data
};
axios.request(config)
.then((response) => {
console.log(JSON.stringify(response.data));
})
.catch((error) => {
console.log(error);
});
import requests
import json
url = "https://api.woosmap.com/stores/replace?private_key=YOUR_PRIVATE_API_KEY"
payload = json.dumps({
"stores": [
{
"storeId": "store_123",
"name": "My first cool store",
"location": {
"lat": 43.61,
"lng": 3.88
}
}
]
})
headers = {
'content-type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n \"stores\": [\n {\n \"storeId\": \"store_123\",\n \"name\": \"My first cool store\",\n \"location\": {\n \"lat\": 43.61,\n \"lng\": 3.88\n }\n }\n ]\n}");
Request request = new Request.Builder()
.url("https://api.woosmap.com/stores/replace?private_key=YOUR_PRIVATE_API_KEY")
.method("POST", body)
.addHeader("content-type", "application/json")
.build();
Response response = client.newCall(request).execute();
require "uri"
require "json"
require "net/http"
url = URI("https://api.woosmap.com/stores/replace?private_key=YOUR_PRIVATE_API_KEY")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["content-type"] = "application/json"
request.body = JSON.dump({
"stores": [
{
"storeId": "store_123",
"name": "My first cool store",
"location": {
"lat": 43.61,
"lng": 3.88
}
}
]
})
response = https.request(request)
puts response.read_body
During the operation, previous assets will still exist and so will be available for queries.
If the import fails, previous assets will not be deleted.
Understanding the Response
The GET method returns your assets in GeoJSON format. When retrieving all assets, the
response is a FeatureCollection containing an array of Feature objects. When retrieving a single asset by
storeId, the response is a single Feature object.
See the API Reference for a complete GeoJSON response example.
Key Response Fields
type - Either FeatureCollection (all assets) or Feature (single asset)
features - Array of GeoJSON Feature objects (when retrieving all assets)
geometry - The geographic coordinates of the asset
"geometry": {
"type": "Point",
"coordinates": [3.883, 43.600]
}
properties - The asset data including storeId, name, types, tags, user_properties,
contact, address, and open (opening hours). See the Data Structure section
for the complete field reference.
Write Operation Responses
POST(Add) - Returns200 OKon success with the number of imported assets.PUT(Update) - Returns200 OKon success with the number of updated assets.DELETE- Returns200 OKon success.- Replace - Returns
200 OKon success with the number of imported assets.
If any asset in a batch fails validation, the entire request is rejected with an error message indicating the issue.
Troubleshooting
| Issue | Common Cause | Solution |
|---|---|---|
Batch rejected on POST |
A storeId in the request already exists. |
Use PUT to update existing assets, or verify your storeId values are unique. |
Batch rejected on PUT |
A storeId in the request does not exist. |
Use POST to create new assets |
| Timeout errors | The process exceeds 30 seconds due to file size or data complexity | Reduce the number of assets per request to reduce the processing time. |
| Invalid JSON format | Request body does not follow the required structure of a stores array. |
Verify each asset includes storeId, name, and location with lat/lng. |
| Authentication errors | Write operations (POST, PUT, DELETE) require a private_key |
Public keys (key) only work for GET requests. |
Usage Limits & Quotas
- Rate Limit: Maximum of 10 queries per second (QPS) per Project
- Payload Size: JSON file should not exceed 15MB
- Exceeding rate limits returns an error response
if a request exceeds 30 seconds (due to file size or data complexity), a Timeout message is returned. Reduce the number of assets in the request to lighten the process time.
Related Features
- Opening Hours - Format for defining store opening hours
- Search - Query and filter assets by attributes, location, and zones
- Autocomplete - Interactive store search with typeahead suggestions
- Zones - Define and manage geographic zones for your assets
- Stores API Overview - Introduction to the Stores API
- Integration Path - Recommended setup workflow
- Making Your First Request - Step-by-step tutorial