# Create Bulk GBP Listings API (`listingsapi/create-bulk-gbp-listings-api`) Actor

Create Google Business Profile listings for hundreds of locations in one run. Point it at locations you already have, at new locations it creates first, or both. One result row per location, so a partial failure is visible.

- **URL**: https://apify.com/listingsapi/create-bulk-gbp-listings-api.md
- **Developed by:** [Local Business Listings Submission API](https://apify.com/listingsapi) (community)
- **Categories:**
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Create Bulk GBP Listings API

Create Google Business Profile listings for hundreds of locations in one run. Point it at locations you already have, at brand new locations you want created first, or at both in the same run.

Creating one Google listing at a time is fine for a single store. Onboarding a franchise with 300 outlets is not that job. This Actor loops the create endpoints of the [Listings API](https://www.listingsapi.com) for you, paces itself against your plan rate limit, and writes one result row per location so a partial failure is visible instead of silent.

### What this Actor does

For each item in the run it does one or both of these:

1. Creates the location with `POST /locations`, if you passed a full location payload
2. Creates the Google Business Profile listing with `POST /locations/create/gmb-listing`, linking it to your connected Google account

Then it writes a row carrying the new location ID, the database ID, the location status, whether the Google listing request was accepted, and the error if it was not.

### Creation is asynchronous

The API answering `success: true` means your request was accepted, not that the listing is live. Google verifies and provisions on its own schedule. Treat a successful run as work queued, then check the real state later with `premiumListingsOfLocation` in the [Local SEO Analytics API](https://apify.com/listingsapi/local-seo-analytics-api) Actor.

### What you need

A Listings API account and an API key with Write access. Create one at [listingsapi.com](https://www.listingsapi.com/pricing).

You also need a **connected Google account ID**. Every Google listing is created under one. Get it by running `connectedAccounts` in the [Create Google Listing API](https://apify.com/listingsapi/create-google-listing-api) Actor, which is also where you connect the Google account in the first place.

### Input

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `apiKey` | string | Yes | Your Listings API key. Stored as a secret. |
| `connectedAccountId` | string | Yes | The Google account new listings are created under. Not needed if `createLocationsOnly` is on. |
| `locationIds` | array | No | Locations that already exist and need a Google listing. One ID per line. |
| `locations` | array | No | Full location payloads. Each is created first, then published to Google. |
| `createLocationsOnly` | boolean | No | Create the locations and stop. Default `false`. |
| `continueOnError` | boolean | No | Keep going past a failure and record it on the row. Default `true`. |
| `delayMs` | integer | No | Pause between calls. Default `6500`, which suits 10 requests per minute. |

Pass `locationIds`, `locations`, or both. The run fails immediately if both are empty.

### Required fields on a new location

A location payload needs `name`, `description`, `countryIso`, `subCategoryId`, and `city` for countries that use city level addressing. The description has a **200 character minimum**, which is the most common reason a bulk import fails on the first row.

Get valid `subCategoryId` values from `subCategories`, and valid country and state codes from `countries`, both in the [Local SEO Analytics API](https://apify.com/listingsapi/local-seo-analytics-api) Actor.

### Examples

Add Google listings to twelve locations you already have:

```json
{
  "apiKey": "<your key>",
  "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5",
  "locationIds": [
    "TG9jYXRpb246MTgwMDI4OQ==",
    "TG9jYXRpb246MTgwMDI5MA==",
    "TG9jYXRpb246MTgwMDI5MQ=="
  ]
}
```

Onboard new stores from scratch, creating each location then its Google listing:

```json
{
  "apiKey": "<your key>",
  "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5",
  "locations": [
    {
      "input": {
        "name": "Acme Dental Downtown",
        "description": "Acme Dental Downtown is a family owned dental practice in lower Manhattan offering preventive care, cosmetic dentistry, orthodontics and emergency appointments. Our board certified team combines modern equipment with a gentle, patient first approach, and same week appointments are available for new patients.",
        "storeId": "ACME01",
        "street": "123 Jump Street",
        "city": "New York",
        "stateIso": "NY",
        "postalCode": "10013",
        "countryIso": "US",
        "phone": "6443859313",
        "subCategoryId": 1432,
        "businessHours": [
          { "day": "MONDAY", "type": "OPEN", "slots": [{ "start": "09:00am", "end": "05:00pm" }] },
          { "day": "SUNDAY", "type": "CLOSED", "slots": [] }
        ]
      }
    }
  ]
}
```

Dry import, creating the locations only so you can review them before anything reaches Google:

```json
{
  "apiKey": "<your key>",
  "createLocationsOnly": true,
  "locations": [ { "input": { "name": "..." } } ]
}
```

Run faster on a Growth plan:

```json
{
  "apiKey": "<your key>",
  "connectedAccountId": "4f712c17-4f95-42dd-90f4-97171a2e67b5",
  "locationIds": ["TG9jYXRpb246MTgwMDI4OQ=="],
  "delayMs": 1200
}
```

### Output

One dataset row per location:

```json
{
  "index": 0,
  "mode": "new",
  "label": "Acme Dental Downtown",
  "locationId": "TG9jYXRpb246MTgwMDI5MA==",
  "databaseId": 1800290,
  "locationStatus": "PENDING",
  "locationCreated": true,
  "gmbListingRequested": true,
  "status": "success",
  "error": null
}
```

A failed row keeps the same shape with `status` set to `failed` and the reason in `error`, so you can filter the dataset to failures, fix the payloads, and rerun just those.

The run also writes a `SUMMARY` record to the key value store with items processed, succeeded, failed, locations created and Google listings requested.

### Rate limits

The Actor sends one request at a time and sleeps `delayMs` between calls. A location that has to be created costs two calls, so 100 new locations at the default pacing takes roughly 22 minutes. On a 429 it reads `retry_after_seconds` and waits it out, retrying up to five times.

Plan limits are 10 requests per minute on Launch and 50 on Growth. See [rate limits](https://docs.listingsapi.com/docs/rate-limits).

### Errors

Both endpoints answer with `success` and `errors` inside a 200 response, so an accepted HTTP status does not mean the work happened. This Actor reads both and marks the row failed when `success` is false or `errors` is not empty, rather than reporting a false positive.

HTTP level failures log the status and the `correlation_id` you can quote to support. Codes are listed at [docs.listingsapi.com/docs/error-codes](https://docs.listingsapi.com/docs/error-codes).

### Cost

You pay Apify for platform usage of the run. Location and listing creation are billed by your Listings API plan, which starts at 99 dollars a month with a 14 day trial.

### Related Actors

- [Create Google Listing API](https://apify.com/listingsapi/create-google-listing-api) for connecting the Google account and creating one listing at a time
- [Local Business Listings Submission API](https://apify.com/listingsapi/local-business-listings-submission-api) for creating and syncing locations
- [Local SEO Analytics API](https://apify.com/listingsapi/local-seo-analytics-api) for checking whether the new listings went live
- [Local Business Reviews API](https://apify.com/listingsapi/local-business-reviews-api) for reading and replying to reviews
- [Local Business Posts API](https://apify.com/listingsapi/local-business-posts-api) for publishing to Google, Facebook, Instagram and X

### Links

- Documentation: [docs.listingsapi.com](https://docs.listingsapi.com/docs)
- Create a location: [docs.listingsapi.com/docs/api/locations-create](https://docs.listingsapi.com/docs/api/locations-create)
- Create a GMB listing: [docs.listingsapi.com/docs/api/connected-accounts-create-gmb-listing](https://docs.listingsapi.com/docs/api/connected-accounts-create-gmb-listing)
- SDKs: [docs.listingsapi.com/sdks](https://docs.listingsapi.com/sdks)
- MCP server: [listingsapi.com/mcp](https://www.listingsapi.com/mcp)
- Support: support@listingsapi.com

# Actor input Schema

## `apiKey` (type: `string`):

Your Listings API key. Create one at https://listingsapi.com. This Actor writes, so the key needs Write access.

## `connectedAccountId` (type: `string`):

The Google account the new listings are created under. Required unless createLocationsOnly is on. Get it from the Create Google Listing API Actor, operation connectedAccounts.

## `locationIds` (type: `array`):

Locations that already exist in your account and need a Google listing. One ID per line.

## `locations` (type: `array`):

Full location payloads. Each one is created first, then published to Google. Required fields are name, description of at least 200 characters, countryIso, subCategoryId and city. See https://docs.listingsapi.com/docs/api/locations-create

## `createLocationsOnly` (type: `boolean`):

Create the locations and stop, without creating Google listings. Useful for a dry import you want to review first.

## `continueOnError` (type: `boolean`):

Keep going when one item fails and record the error on its row. Turn this off to stop the run at the first failure.

## `delayMs` (type: `integer`):

Pause between API calls so the run stays inside your plan rate limit. 6500 suits the Launch plan at 10 requests per minute. Lower it to about 1200 on Growth.

## Actor input object example

```json
{
  "locationIds": [],
  "locations": [],
  "createLocationsOnly": false,
  "continueOnError": true,
  "delayMs": 6500
}
```

# Actor output Schema

## `results` (type: `string`):

One row per location processed, carrying the new location ID, whether the Google listing request was accepted, and the error if it was not.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("listingsapi/create-bulk-gbp-listings-api").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("listingsapi/create-bulk-gbp-listings-api").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call listingsapi/create-bulk-gbp-listings-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,listingsapi/create-bulk-gbp-listings-api"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/xhD0LQx0Ue9rQ5oqS/builds/JOu89ip9271npORYu/openapi.json
