POI categories

getPOICategories() returns every POI category the Search API knows, with its names and synonyms in a language. Use it to build a category picker, or to find categories by name or synonym. A category’s code, a POICategory, works in:

The Node.js POI categories example finds categories by keyword, best match first, and feeds their codes to discoverPlaces.

Basic usage

import { getPOICategories } from '@tomtom-org/maps-sdk/services';
const { poiCategories: categories } = await getPOICategories();
categories.forEach((category) => {
console.log(category.name); // e.g. "Sports Center"
console.log(category.code); // e.g. "SPORTS_CENTER"
console.log(category.synonyms); // e.g. ["Sports Centre"]
console.log(category.childCategoryCodes); // e.g. ["FITNESS_CLUB_AND_CENTER", "HORSE_RIDING", ...]
});

Getting codes directly: getPOICategoryCodes

getPOICategoryCodes takes the same parameters and returns only the codes:

import { discoverPlaces, getPOICategoryCodes } from '@tomtom-org/maps-sdk/services';
const all = await getPOICategoryCodes();
// Codes matching a keyword, best match first, e.g. ['RESTAURANT', 'RESTAURANT_AREA']
const restaurantCodes = await getPOICategoryCodes({ filters: ['restaurant'] });
const results = await discoverPlaces({
filters: { poiCategories: restaurantCodes },
geoBias: { position: [4.9041, 52.3676] },
});

Fetching in a specific language

language localizes the names and synonyms, and defaults to the global language:

const { poiCategories: categories } = await getPOICategories({ language: 'fr-FR' });
console.log(categories[0].name); // e.g. "Centre sportif"

Filtering categories

filters finds categories by keyword. It matches client-side against the cached list, so it sends no request after the first. Each filter ranks the categories it matches, strongest first:

  1. A category code, such as 'CAFE', matches that category only.
  2. Any other filter ranks an exact name or synonym first, then a name or synonym that starts with the filter ('parking' finds 'Parking Garage'), then one with it as a later word, and last one containing it as a substring.
  • A filter keeps only matches close to its best one, so 'bar' finds 'Bar' but not 'Nail Salon' through its synonym 'Nail Bar'.
  • Matching ignores case, accents and punctuation. A substring match ignores spaces too. 'cafe' finds 'Café', and 'bookstore' finds 'Book Shop' through its synonym 'Book Store'. A blank filter matches nothing.
  • Several filters merge round-robin, so each filter’s best match comes first, with one entry per code. A category ranked below its matched parent is left out, because the parent already covers it.
const { poiCategories: gymCategories } = await getPOICategories({ filters: ['gym'] });
// Each filter's best match first, one entry per code
const { poiCategories: combined } = await getPOICategories({ filters: ['gym', 'parking'] });
const { poiCategories: restaurants } = await getPOICategories({ language: 'en-GB', filters: ['restaurant'] });

Pass code values to discoverPlaces(), such as the one picked from a dropdown:

import { discoverPlaces, getPOICategories } from '@tomtom-org/maps-sdk/services';
const { poiCategories: allCategories } = await getPOICategories();
const options = allCategories.map((category) => ({ label: category.name, value: category.code }));
const results = await discoverPlaces({
filters: { poiCategories: ['SPORTS_CENTER'] },
geoBias: { position: [4.9041, 52.3676] },
limit: 20,
});

When the category comes as a word rather than a choice from a list, skip the lookup and pass it as filters.poiCategoryQuery, which resolves it with resolvePOICategories:

const gyms = await discoverPlaces({ filters: { poiCategoryQuery: 'gym' }, geoBias: { position: [4.9041, 52.3676] } });

Resolving words for a search: resolvePOICategories

resolvePOICategories turns words, or codes, into the poiCategories of one search, and reports the words that match nothing. Call it before searching to handle those words yourself. You can search with the rest, ask the user or fall back to a free-text query.

import { discoverPlaces, resolvePOICategories } from '@tomtom-org/maps-sdk/services';
const { poiCategories, unmatched } = await resolvePOICategories({ filters: ['café', 'PHARMACY', 'xyzzy'] });
// unmatched: ['xyzzy']
if (poiCategories.length) {
const places = await discoverPlaces({ filters: { poiCategories }, geoBias: { position: [4.9041, 52.3676] } });
}
  • Each filter matches as in Filtering categories, so a code stays itself.
  • It keeps each filter’s best three codes, merged round-robin and capped at the 10 a search accepts.
  • filters.poiCategoryQuery runs this lookup, so both resolve a word the same way.
  • Codes alone skip the catalogue request and come back as given, never folded into a parent, with duplicates dropped.
  • resolvePOICategories builds one search, while getPOICategoryCodes lists every close match, for a picker or the map’s POI icons.

Filtering the map’s built-in POI icons

To choose which of the map’s own POI icons show, set the POIsModule filters.categories setting to generic parent codes or POICategoryGroup values such as 'FOOD_DRINKS_GROUP'. It doesn’t support specific child codes such as 'ITALIAN_RESTAURANT', so use the parent 'RESTAURANT' or a group. The POIs module guide covers the setting and its groups.

import { POIsModule, TomTomMap } from '@tomtom-org/maps-sdk/map';
import { getPOICategoryCodes } from '@tomtom-org/maps-sdk/services';
const map = new TomTomMap({ mapLibre: { container: 'map' } });
const poisModule = await POIsModule.get(map);
const codes = await getPOICategoryCodes({ filters: ['restaurant', 'sports center'] });
poisModule.updateConfig({ filters: { categories: { show: 'only', values: codes } } });

Exploring sub-categories

childCategoryCodes lists a category’s sub-categories, for drill-down navigation:

const { poiCategories: categories } = await getPOICategories();
const restaurant = categories.find((category) => category.code === 'RESTAURANT');
console.log(restaurant?.childCategoryCodes); // e.g. ['ITALIAN_RESTAURANT', 'FRENCH_RESTAURANT', ...]

Note that a search by a parent code returns places in these sub-categories too.

Cache management

  • The first call in a language fetches the list. Every later call in that language reads the cache, filtered or not, including resolvePOICategories and filters.poiCategoryQuery.
  • The cache is in memory for the lifetime of the page or process. There is nothing to clear.
const { poiCategories: english } = await getPOICategories({ language: 'en-GB' });
const { poiCategories: french } = await getPOICategories({ language: 'fr-FR' }); // a second request

Parameter reference

On top of the options every service call takes:

ParameterTypeDescription
languagestringIETF language tag for names and synonyms, e.g. 'en-GB', 'fr-FR'. Defaults to the global language.
filtersstring[]Keywords matched client-side, as in Filtering categories. Omit it to return every category. resolvePOICategories requires it.

Response reference

Each entry of poiCategories:

FieldTypeDescription
codePOICategoryThe code filters.poiCategories takes.
namestringCategory name in the requested language.
childCategoryCodesPOICategory[]Sub-category codes, whether or not they matched filters.
synonymsstring[]Alternative names in the requested language.

resolvePOICategories returns { poiCategories, unmatched } instead. It holds the codes for one search, best first, and the filters that matched nothing, as given.

  • Discover places — Searching by category code or by category in words
  • POIs module — The map’s own POI icons, filtered by parent codes or groups
  • Search suggestions — A category the user is typing, as a category suggestion