Look up countries, states and categories

Fetch the supported countries and state codes, resolve a business category to its numeric id, and see which publishers your plan covers before you create a location.

Creating a location needs three values you cannot guess: a countryIso and stateIso the API accepts, a numeric subCategoryId, and, if you want to limit publishers, the site ids in your plan. Three catalog endpoints supply them. All three return a plain array with no pagination.

1. List countries and state codes

GET /countries returns every supported country with its ISO code, a hasCity flag, and a states array. The iso values feed countryIso and stateIso on create and update. The Python SDK exposes this as client.countries() and the Node SDK as client.fetchCountries().

Countries
curl https://listingsapi.com/api/v4/countries \-H "Authorization: API $LISTINGSAPI_KEY"
JSON
{  "data": {    "supportedCountries": [      {        "databaseId": 13,        "iso": "AU",        "name": "Australia",        "hasCity": true,        "states": [          { "id": "139", "iso": "VIC", "name": "Victoria" },          { "id": "142", "iso": "NSW", "name": "New South Wales" }        ]      },      {        "databaseId": 17,        "iso": "BE",        "name": "Belgium",        "hasCity": true,        "states": []      }    ]  }}

hasCity: true means city is mandatory on create unless the location is a service-area business with hideAddress: true. A country with an empty states array is not subdivided, so leave stateIso out for it.

2. Find a category id

GET /sub-categories returns the full category catalog. The value you send as subCategoryId is databaseId, the integer, not the base64 id. Restaurants, for example, is 1432. Filter the list by name in your own code; there is no server-side search parameter.

Find a category
curl https://listingsapi.com/api/v4/sub-categories \-H "Authorization: API $LISTINGSAPI_KEY" \| jq '.data.subcategories[] | select(.name | test("restaurant"; "i")) | {databaseId, name, primary}'
JSON
{  "data": {    "subcategories": [      {        "databaseId": 1432,        "id": "U3ViQ2F0ZWdvcnk6MTQzMg==",        "key": "restaurants",        "name": "Restaurants",        "primary": true      }    ]  }}
FieldUse it for
databaseIdThe integer to send as subCategoryId, or inside additionalCategoryIds for up to 9 secondary categories.
nameThe human-readable label to show in a picker and to match against.
keyA URL-friendly slug of the name, stable across renames.
primaryWhether the category may be a location's primary subcategory. Only pick true entries for subCategoryId.

3. See which publishers your plan covers

GET /plan-sites lists every publisher in your plan with a numeric id, a url, the countries it accepts, and the countries where it honors hideAddress. These ids are the only valid values for enabledSiteIds on create and submissionDisabledSiteIds on update. Filter by the location's country so you only offer publishers that will accept it.

Plan sites
curl https://listingsapi.com/api/v4/plan-sites \-H "Authorization: API $LISTINGSAPI_KEY" \| jq '.data.planSites[] | select(.supportedCountries | index("US")) | {id, name, url}'
JSON
{  "data": {    "planSites": [      {        "id": 1,        "name": "Google Maps",        "url": "maps.google.com",        "supportedCountries": ["US", "CA", "IN", "GB", "DE"],        "hideAddressSupportedCountries": ["US", "CA", "AU", "IN", "GB"]      },      {        "id": 2,        "name": "Yelp",        "url": "yelp.com",        "supportedCountries": ["US", "CA", "GB", "DE", "FR"],        "hideAddressSupportedCountries": ["US", "CA", "AU", "GB"]      }    ]  }}

Both country arrays are truncated here; the live response can list 50 or more codes per site. For a service-area business, check hideAddressSupportedCountries as well, since a publisher that accepts the country may still refuse a listing with no street address.

4. Cache these lookups

All three catalogs change rarely and none of them paginate, so fetch each once at startup, keep it in memory or a small table, and refresh on a schedule. Calling them inline on every create burns rate limit for no new information; on the Launch plan that is 3 of your 10 requests per minute.

CatalogSizeRefresh when
CountriesDozens of countries, hundreds of statesRarely. Daily is more than enough.
SubcategoriesRoughly 6,000 entriesDaily, or when a create fails with an unknown subCategoryId.
Plan sitesDozens of publishersOn a plan change, since the list is scoped to your plan.

Build a lowercase name to databaseId map for subcategories and a countryIso to states map for countries. Validate the address against the cache before you call create, so an unsupported countryIso (SY10036) or a missing city (SY10126) is caught with a clear message on your side.

Next steps