These docs are a work in progress and may not be fully up to date. Some pages may contain internal notes for our team.
Skip to Content

API — Locations

Location CRUD, image management, and CSV bulk import. All endpoints require auth:api, auth_session, and audit middleware. Results are workspace-scoped.

Endpoints

GET /locations

List locations in the active workspace.

Query params: workspace_id, finder_id (optional filter by finder association)

Response 200: Array of location objects.

GET /locations/{id}

Get a single location by numeric ID.

Response 200: Location object with address fields, lat/lng, tags, custom fields, and image URLs.

POST /locations

Create a new location.

Body:

{ "title": "Downtown Store", "address": "123 Main St", "city": "Austin", "state": "TX", "country": "US", "zip": "78701", "lat": 30.2672, "lng": -97.7431, "phone": "+15125550123", "email": "store@example.com", "website": "https://example.com", "workspace_id": 1 }

Response 201: Created location.

PUT /locations/{id}

Update a location’s fields. Partial updates are supported.

Response 200: Updated location.

DELETE /locations/{id}

Delete a location.

Response 204

Image endpoints

POST /locations/{id}/image

Upload an image for a location. Accepts multipart/form-data.

Body: image (file field) — JPEG or PNG.

The image is uploaded to R2 at workspaces/{workspace_id}/locations/{id}/{uuid}.{ext} and served via CDN. The CDN URL is returned in the response and stored on the location record.

Response 200: { image_url: "https://cdn.locationfinders.com/..." }

DELETE /locations/{id}/image

Remove the location’s image. Deletes from R2 on a best-effort basis (failure is logged but does not fail the request).

Response 200: Location with image_url: null.

Bulk import

POST /locations/import

Bulk-create or update locations from a CSV payload. The CSV must include the required fields (title, address columns). Custom fields are matched by name.

Body: multipart/form-data with a file field containing the CSV.

Response 200: { created, updated, skipped, errors[] } summary.

⚠️ Warning: The import endpoint replaces existing locations by matching on an internal key. Rows without a match are created; rows with a match are updated. There is no dry-run mode — validate the CSV before submitting.