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

http
        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.

Shell
        # 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

JSON
        {
  "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):

JSON
        {
  "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.

JSON
        {
  "types": ["book_store", "library"]
}

    

tags: An array of strings, of useful tags for filtering and grouping.

JSON
        {
  "tags": ["science", "comics"]
}

    

address: An address object for the store.

JSON
        {
  "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.

JSON
        {
  "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.

JSON
        {
  "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.

JSON
        {
  "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.

JSON
        {
  "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.

Sample create request
        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.

Sample update request
        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.

Sample delete request
        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

Shell
        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.

Retrieve all assets
Shell
        curl 'https://api.woosmap.com/stores?private_key=YOUR_PRIVATE_KEY'

    

You can also retrieve a specific asset by its storeId:

Retrieve a specific asset
Shell
        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.

Sample replace request
        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

JSON
        "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) - Returns 200 OK on success with the number of imported assets.
  • PUT (Update) - Returns 200 OK on success with the number of updated assets.
  • DELETE - Returns 200 OK on success.
  • Replace - Returns 200 OK on 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.

Was this helpful?