Submissions
POI submissions are batches of point-of-interest locations you import into your company’s data. You can list them, read a single one, create them by file upload or by an inline list of locations, and delete a submission that is still waiting for Intuizi’s review.
All submission endpoints are authenticated and JSON-only. Reads use the read rate bucket (120 requests/min); creates and deletes use the write bucket (30 requests/min).
List Submissions
GET /api/v2/my-data/pois/submissions/index
Lists the POI submissions for the authenticated user’s company, with optional search and sort.
Auth: bearer token + Accept: application/json. Rate limit: read bucket.
Query parameters
| Field | Type | Required | Description |
|---|---|---|---|
q | string | No | Free-text search on the submission name. |
sortBy | string | No | Sort field. One of name, status, created_at, updated_at. |
orderBy | string | No | Sort direction. One of asc, desc. |
curl "https://console.intuizi.com/api/v2/my-data/pois/submissions/index?q=Hilton&sortBy=status&orderBy=desc" \
-H "Authorization: Bearer <YOUR_TOKEN>" \
-H "Accept: application/json"Response
{
"status": "success",
"code": 200,
"message": "Resource fetched successfully.",
"data": [
{
"id": 1,
"name": "Virgin train Stations POIs",
"pois_imported": 123,
"pois_imported_count": 123,
"company": { "id": 123, "name": "Company Name" },
"user": { "id": 123, "name": "John Doe" },
"status": { "id": 1, "name": "Waiting" },
"brand": { "id": 123, "name": "Virgin" },
"actions": { "key": "gps-coordinates", "remove": 0, "update": 1 },
"backfill": { "requested": false, "status": null, "job_id": null },
"created_at": "2025-01-01 12:00:00",
"updated_at": "2025-01-01 12:00:00"
}
]
}Get Submission
GET /api/v2/my-data/pois/submissions/{id}
Retrieves a single submission owned by the authenticated user’s company.
Auth: bearer token + Accept: application/json. Rate limit: read bucket.
Path parameters
| Field | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The submission id to fetch. |
curl "https://console.intuizi.com/api/v2/my-data/pois/submissions/123" \
-H "Authorization: Bearer <YOUR_TOKEN>" \
-H "Accept: application/json"Response
{
"status": "success",
"code": 200,
"message": "Resource fetched successfully.",
"data": [
{
"id": 1,
"name": "Virgin train Stations POIs",
"pois_imported": 123,
"pois_imported_count": 123,
"company": { "id": 123, "name": "Company Name" },
"user": { "id": 123, "name": "John Doe" },
"status": { "id": 1, "name": "Waiting" },
"brand": { "id": 123, "name": "Virgin" },
"actions": { "key": "gps-coordinates", "remove": 0, "update": 1 },
"backfill": { "requested": false, "status": null, "job_id": null },
"created_at": "2025-01-01 12:00:00",
"updated_at": "2025-01-01 12:00:00"
}
]
}A new submission starts at status 4 Importing and moves to 1 Waiting on
its own once Intuizi has read its locations. From Waiting, Intuizi reviews it
by hand: an approved submission becomes 2 Imported, and only then do its
locations appear in List POIs. A declined one
becomes 3 Disabled. The review is not automatic, so do not poll for
Imported as if it were a processing step. See
Status Codes.
Create Submission by File
POST /api/v2/my-data/pois/submissions/create-by-file
Creates a submission from an uploaded CSV file of locations. For large files, browser clients, or JSON-only integrations, use the presigned upload flow with Create Submission by Upload instead - both doors accept the same files and produce the same submission.
Auth: bearer token + Accept: application/json. Because this is a file
upload, send Content-Type: multipart/form-data (not JSON). Rate limit: write
bucket (30 requests/min).
Body (multipart form fields)
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | The submission name. |
brand_id | integer | Yes | The brand id the POIs belong to. Must exist. |
locations_file | file | Yes | A CSV of locations with a .csv or .txt extension, up to 50 MB. The first row is the header row. Required headers: country|alpha_2 or country|alpha_3, longitude, and latitude. Optional headers: location_id, store_id, name, address1, address2, city, state, zip_code, dma_desc, polygon, sqft, is_verified, max_trade_area|miles or max_trade_area|meters, external_id, master_id, placekey, h3_index, h3_index_integer, category_taxonomy, and sub_category_taxonomy. A file with any other header is rejected. A location_id value must be the id of one of your POIs, as a whole number (101 or 101.0). |
update | boolean | No | Update the brand’s existing POIs that a listed location matches (see key). As a multipart form field, send 1 or 0 (the string true is rejected). |
remove | boolean | No | Archive the brand’s existing POIs that no listed location matches (see key), and keep the matched ones, updated only with update. Applied once, over the whole submission - see the note below this table. As a multipart form field, send 1 or 0 (the string true is rejected). |
key | string | No | How each listed location is matched to the brand’s existing POIs. One of location-id, gps-coordinates, store-id, master-id, external-id. Defaults to gps-coordinates when left out or null. location-id matches a location’s location_id column to the id of one of the brand’s POIs. |
Matching. Locations are matched, and update and remove applied, when
Intuizi approves the submission, not when it is created, and the same way on
all three creates. A listed location that matches an existing POI of the
brand is never added a second time: with update it updates that POI, and
without update the POI is left as it is. A location that matches nothing is
added as a new POI.
remove is applied once, after every location of the submission has been
matched, whatever the submission’s size. Every POI the brand had before the
approval that no location matches is archived. The POIs a location matches
keep their ids, and the POIs the submission adds are kept. A submission whose
locations carry values for its key but match no POI archives every POI the
brand had. One that holds no location at all, or in which no location has a
value for its key (a location_id, store_id, master_id, or
external_id, a blank value counting as none), archives nothing. Each
remove submission archives every POI of the brand that it does not list,
so send every location the brand should keep in one submission, not the
ones to drop. If an approval is
interrupted part way, its locations are still imported but remove is not
applied. Send the remove submission again to apply it.
With the location-id key, a location matches the brand’s POI whose id is
its location_id, the id that List POIs
returns. A location with no location_id, or with one that is not the id of
one of the brand’s POIs, matches nothing and is added as a new POI. A
remove submission in which no location has a location_id names no POI to
keep, so it archives nothing.
curl -X POST "https://console.intuizi.com/api/v2/my-data/pois/submissions/create-by-file" \
-H "Authorization: Bearer <YOUR_TOKEN>" \
-H "Accept: application/json" \
-F "name=Virgin train Stations POIs" \
-F "brand_id=123" \
-F "key=gps-coordinates" \
-F "update=1" \
-F "locations_file=@locations.csv"Response
{
"status": "success",
"code": 201,
"message": "Resource created successfully.",
"data": [
{
"value": 123,
"text": "Virgin train Stations POIs"
}
]
}Create Submission by Upload
POST /api/v2/my-data/pois/submissions/create-by-upload
Creates a submission from a file previously uploaded through the presigned
upload flow: reserve an upload with purpose
poi_submission, PUT the CSV to the returned URL, then call this endpoint
with the upload_reference. The file requirements are the same as
Create Submission by File,
and the response is identical. The reference is one-shot - a second create
with the same reference is rejected.
Auth: bearer token + Accept: application/json + Content-Type: application/json. Rate limit: write bucket (30 requests/min). Optional:
Idempotency-Key header makes this create safe to retry - see
Idempotency.
Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | The submission name. |
brand_id | integer | Yes | The brand id the POIs belong to. Must exist. |
upload_reference | string | Yes | The upload_reference from Create an Upload (purpose poi_submission), after the file was PUT to the presigned URL. |
update | boolean | No | Update the brand’s existing POIs that a listed location matches (see key). |
remove | boolean | No | Archive the brand’s existing POIs that no listed location matches (see key), and keep the matched ones, updated only with update. Applied once, over the whole submission - see the matching note under Create Submission by File. |
key | string | No | How each listed location is matched to the brand’s existing POIs. One of location-id, gps-coordinates, store-id, master-id, external-id. Defaults to gps-coordinates when left out or null. location-id matches a location’s location_id to the id of one of the brand’s POIs - see the matching note under Create Submission by File. |
curl -X POST "https://console.intuizi.com/api/v2/my-data/pois/submissions/create-by-upload" \
-H "Authorization: Bearer <YOUR_TOKEN>" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"name": "Virgin train Stations POIs",
"brand_id": 123,
"upload_reference": "upl_01k0p3v9example"
}'Response
{
"status": "success",
"code": 201,
"message": "Resource created successfully.",
"data": [
{
"value": 123,
"text": "Virgin train Stations POIs"
}
]
}Create Submission by List
POST /api/v2/my-data/pois/submissions/create-by-list
Creates a submission from an inline list of location objects (no file upload).
Auth: bearer token + Accept: application/json + Content-Type: application/json. Rate limit: write bucket (30 requests/min).
Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | The submission name (max 255 chars). |
brand_id | integer | Yes | The brand id the POIs belong to. Must exist. |
country_isocode | string | No | ISO code standard for locations[].country. One of alpha_2, alpha_3. Defaults to alpha_3. |
update | boolean | No | Update the brand’s existing POIs that a listed location matches (see key). |
remove | boolean | No | Archive the brand’s existing POIs that no listed location matches (see key), and keep the matched ones, updated only with update. Applied once, over the whole submission - see the matching note under Create Submission by File. |
key | string | No | How each listed location is matched to the brand’s existing POIs. One of location-id, gps-coordinates, store-id, master-id, external-id. Defaults to gps-coordinates when left out or null. location-id matches a location’s location_id to the id of one of the brand’s POIs - see the matching note under Create Submission by File. |
locations | object[] | Yes | The list of location objects (see below). |
Each entry in locations[]:
| Field | Type | Required | Description |
|---|---|---|---|
country | string | Yes | 2- or 3-letter ISO country code, matching country_isocode. |
longitude | number | Yes | Longitude, between -180 and 180. |
latitude | number | Yes | Latitude, between -90 and 90. |
location_id | integer | No | The id of one of your POIs, as List POIs returns it. With the location-id key, the location matches the brand’s POI with this id, and with no match it is added as a new POI. |
store_id | string | No | Your reference store id. |
name | string | No | POI name (max 255 chars). |
address1 | string | No | Address line 1. |
address2 | string | No | Address line 2. |
city | string | No | City. |
state | string | No | State. |
zip_code | string | No | ZIP/postal code. |
dma_desc | string | No | DMA description. |
polygon | string | No | WKT polygon. |
sqft | number | No | Polygon square footage. |
is_verified | boolean | No | Whether the POI is verified. |
max_trade_area | number | No | Max trade-area radius in miles (min 0.1). |
external_id | string | No | External id. |
master_id | string | No | Master id. |
category_taxonomy | string | No | Category taxonomy label. |
sub_category_taxonomy | string | No | Sub-category taxonomy label. |
curl -X POST "https://console.intuizi.com/api/v2/my-data/pois/submissions/create-by-list" \
-H "Authorization: Bearer <YOUR_TOKEN>" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"name": "Starbucks NYC",
"brand_id": 123,
"country_isocode": "alpha_3",
"locations": [
{
"store_id": "ST-NY-001",
"name": "Starbucks Times Square",
"address1": "1560 Broadway",
"city": "New York",
"state": "NY",
"zip_code": "10036",
"country": "USA",
"longitude": -73.9855,
"latitude": 40.7580
}
]
}'Response
{
"status": "success",
"code": 201,
"message": "Resource created successfully.",
"data": [
{
"value": 123,
"text": "Starbucks NYC"
}
]
}Backfill (optional)
Any of the three creates above can optionally request a historical visitation backfill for the submission’s brand. POI locations only start accumulating visitation from the day they are added; a backfill makes the historical signal for the submission’s brand available for a chosen window. The submission and its backfill are requested in a single call. The backfill is submitted as soon as Intuizi has read the submission’s locations (status Waiting), before they are imported, so it covers the locations the brand already has at that point and not the ones in this submission. Deleting the submission does not cancel it.
Backfills are a gated capability: they require additional permissions that
need to be approved by your Account Manager. A create that requests a backfill
while your account is not enabled returns 403; a create without a backfill is
unaffected.
Add these fields to the create body (they work the same on create-by-file,
create-by-upload, and create-by-list):
| Field | Type | Required | Description |
|---|---|---|---|
backfill | boolean | No | Set true to request a backfill for this submission’s brand. |
backfill_recency | string | With backfill | The window. One of last_30_days, last_90_days, last_180_days, last_full_month, or custom. |
backfill_start_date | string | With custom | Window start, YYYY-MM-DD. By default the earliest available date is 2024-01-01; an earlier start is raised to that floor. |
backfill_end_date | string | With custom | Window end, YYYY-MM-DD. On or after backfill_start_date and not later than today. |
Presets are measured from today and resolve to concrete UTC dates server-side.
last_full_month is the whole previous calendar month. Only custom requires
backfill_start_date / backfill_end_date.
curl -X POST "https://console.intuizi.com/api/v2/my-data/pois/submissions/create-by-upload" \
-H "Authorization: Bearer <YOUR_TOKEN>" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"name": "Virgin train Stations POIs",
"brand_id": 123,
"upload_reference": "upl_01k0p3v9example",
"backfill": true,
"backfill_recency": "last_90_days"
}'Backfill status on the submission read
When a submission requested a backfill, Get Submission
carries a backfill block so you can follow it:
{
"backfill": {
"requested": true,
"status": "queued",
"job_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
}
}requested reflects whether the submission asked for a backfill. job_id and
status populate once the submission has reached Waiting and the backfill has
been submitted. status is a string that progresses to a terminal value
(succeeded, warning, failed, cancelled, or completed_with_errors).
For a submission with no backfill, requested is false and the other fields
are null.
Delete Submission
POST /api/v2/my-data/pois/submissions/delete-by-id
Deletes a submission by id. Only a submission at status 1 Waiting is
eligible: Intuizi has read its locations and not yet reviewed it. Deleting it
does not cancel a backfill it requested.
Auth: bearer token + Accept: application/json + Content-Type: application/json. Rate limit: write bucket (30 requests/min).
Body
| Field | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The submission id to delete. Must be a submission at status 1 Waiting owned by your company. |
curl -X POST "https://console.intuizi.com/api/v2/my-data/pois/submissions/delete-by-id" \
-H "Authorization: Bearer <YOUR_TOKEN>" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{ "id": 123 }'Response
{
"status": "success",
"code": 200,
"message": "Resource deleted successfully.",
"data": []
}Failed requests use the shared error envelope - see Errors.