Skip to main content

Batch Find or Create Places API

Overview

The batch_find_or_create_places API endpoint allows you to find or create multiple places in a single request. It uses the same lookup mechanism as the find_create_business method and the import_addresses command.

Endpoint

POST /api/v0.3/batch_find_or_create_places

Authentication

No authentication required (based on current API configuration).

Request Format

Headers

Content-Type: application/json

Body (Two Formats Supported)

Format 1: Simple Array (Legacy)

Send a JSON array of place objects directly:

[
{ "name": "Place 1", "address": "123 Main St" },
{ "name": "Place 2", "address": "456 Oak Ave" }
]

Send a JSON object with places array and optional batch tagging:

{
"places": [
{ "name": "Place 1", "address": "123 Main St" },
{ "name": "Place 2", "address": "456 Oak Ave" }
],
"editorial_categories": ["restaurants", "outdoor-dining"],
"tags": ["family-friendly", "dog-friendly"]
}

Top-Level Fields (Format 2 only)

FieldTypeRequiredDescription
placesarrayYesArray of place objects (see below)
editorial_categoriesarrayNoEditorial category names or slugs to add to ALL places
tagsarrayNoTag names to add to ALL places

Place Object Fields

Each place object in the places array can contain the following fields:

FieldTypeRequiredDescription
namestringYesName of the place
addressstringNoFull street address (recommended for accurate matching)
vibemap_idstringNoExisting Vibemap place ID (if known)
urlstringNoWebsite URL
citystringNoCity name (helps with matching)
latitudenumberNoLatitude coordinate
longitudenumberNoLongitude coordinate

Example Request (Simple Format)

[
{
"name": "Café Deluxe",
"address": "123 Main Street, San Francisco, CA 94102",
"city": "San Francisco",
"url": "https://cafedeluxe.com",
"latitude": 37.7749,
"longitude": -122.4194
},
{
"name": "The Book Shop",
"address": "456 Oak Ave",
"vibemap_id": "123e4567-e89b-12d3-a456-426614174000"
}
]

Example Request (With Batch Tagging)

{
"places": [
{
"name": "Café Deluxe",
"address": "123 Main Street, San Francisco, CA 94102",
"city": "San Francisco",
"url": "https://cafedeluxe.com"
},
{
"name": "The Book Shop",
"address": "456 Oak Ave"
}
],
"editorial_categories": ["cafes-coffee", "bookstores"],
"tags": ["cozy", "wifi", "locally-owned"]
}

Response Format

Success Response (200 OK)

{
"count": 2,
"results": [
{
"name": "Café Deluxe",
"address": "123 Main Street, San Francisco, CA 94102",
"city": "San Francisco",
"url": "https://cafedeluxe.com",
"vibemap_id": "123e4567-e89b-12d3-a456-426614174000",
"vibemap_url": "https://vibemap.com/place/cafe-deluxe",
"status": "found",
"found_or_created": "found",
"editorial_categories_added": ["cafes-coffee"],
"tags_added": ["cozy", "wifi", "locally-owned"],
"error": null
},
{
"name": "The Book Shop",
"address": "456 Oak Ave",
"vibemap_id": "456e7890-e12b-34d5-b678-901234567890",
"vibemap_url": "https://vibemap.com/place/the-book-shop",
"status": "created",
"found_or_created": "created",
"editorial_categories_added": ["bookstores"],
"tags_added": ["cozy", "wifi", "locally-owned"],
"error": null
}
]
}

Response Fields

FieldTypeDescription
countintegerTotal number of places processed
resultsarrayArray of result objects
results[].vibemap_idstringVibemap UUID of the place (found or created)
results[].vibemap_urlstringDirect URL to the place on Vibemap
results[].statusstringStatus: "found", "created", or "error"
results[].found_or_createdstringSame as status (explicit column)
results[].editorial_categories_addedarrayList of editorial category names added to this place
results[].tags_addedarrayList of tag names added to this place
results[].errorstring/nullError message if status is "error", otherwise null

All original fields from the request are also included in each result object.

Error Response (400 Bad Request)

{
"error": "Request body must be a JSON array of place objects"
}

Place Lookup Logic

The API uses a multi-step lookup process (same as find_place_django):

  1. By Vibemap ID: If vibemap_id is provided, look up directly by ID
  2. Exact Match: Search for exact name and address match (case-insensitive)
  3. Fuzzy Match: Use trigram similarity matching on name and address
  4. URL Match: If URL is provided, search by URL

If no match is found, a new place is created.

Status Values

  • found: Existing place was found in the database
  • created: New place was created
  • error: An error occurred processing this place (see error field)

Examples

cURL Example

curl -X POST https://api.vibemap.com/api/v0.3/batch_find_or_create_places \
-H "Content-Type: application/json" \
-d '[
{
"name": "Blue Bottle Coffee",
"address": "66 Mint St, San Francisco, CA 94103",
"city": "San Francisco"
}
]'

Python Example

import requests

places = [
{
"name": "Blue Bottle Coffee",
"address": "66 Mint St, San Francisco, CA 94103",
"city": "San Francisco",
"latitude": 37.7825,
"longitude": -122.4061
},
{
"name": "The Mill",
"address": "736 Divisadero St, San Francisco, CA",
"url": "https://themillsf.com"
}
]

response = requests.post(
'https://api.vibemap.com/api/v0.3/batch_find_or_create_places',
json=places
)

results = response.json()
for place in results['results']:
print(f"{place['name']}: {place['status']} - {place['vibemap_url']}")

JavaScript Example

const places = [
{
name: "Sightglass Coffee",
address: "270 7th St, San Francisco, CA 94103",
city: "San Francisco"
}
];

fetch('https://api.vibemap.com/api/v0.3/batch_find_or_create_places', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(places)
})
.then(response => response.json())
.then(data => {
console.log('Results:', data.results);
});

Notes

  • The API processes places sequentially in the order provided
  • Each place is processed independently - if one fails, others will still be processed
  • Duplicate detection uses fuzzy matching on name and address
  • For best results, provide as much information as possible (name, address, city)
  • Coordinates (latitude/longitude) are used for geolocation when creating new places
  • The API reuses the battle-tested lookup logic from the import_addresses management command
  • GET /api/v0.3/find_business - Find a single business with Google search integration
  • POST /api/v0.3/places - Create a single place (full PlaceViewSet)
  • GET /api/v0.3/places/{id} - Retrieve place details