Skip to main content

1. Overview

SocialAPI publishes local posts to one connected Google Business Profile location: updates, events, offers, and alerts. A local post appears on the location’s Business Profile in Google Search and Google Maps. Each connected google account is one location, so a post with one Google target publishes on one location. For everything outside publishing, see the Google Business Profile API page.

2. Supported media

  • Text: text holds up to 1,500 characters. A longer text fails pre-publish validation with 400 publishing.validation_failed.
  • Images: 1 image per post, JPEG or PNG, up to 5 MB. A second media item fails validation with 400 publishing.validation_failed (“carousel/album posts are not supported on google”).
  • Video: not accepted. A video item fails validation with 400 publishing.validation_failed.
  • Media sources: Google fetches the image from a URL, so use a media_id (a file in your media library) or a public url. A platform_attachment_id item returns 422 publishing.media.unsupported_source.

3. Create post

Send POST /v1/posts with a Google account in targets and "publish_now": true. Without publish_now or scheduled_at, SocialAPI saves the post as a draft.
  • text becomes the body of the local post. It is required: a request without it returns 400 validation.field_required.
  • title is not used by Google Business Profile posts. Put an event’s name in platform_data.google.event.title.
  • platform_data.google (or the target’s own platform_data) carries the post type and its extra fields. A key in a target’s platform_data wins over the same key in platform_data.google.
Response (HTTP 201):
SocialAPI publishes in the background. The target moves from pending to publishing, then to published or failed, and the post ends as published, partial, or failed. Poll GET /v1/posts/{pid} or subscribe to the post.published, post.partial, and post.failed webhook events. Publishing or scheduling costs 1 post credit; a draft is free (see Plans and credits).

Platform data fields

Pass these in platform_data.google or in a target’s platform_data: SocialAPI validates topicType and callToAction: an invalid value fails pre-publish validation with 400 publishing.validation_failed. When you set skip_validation, the target fails instead with validation.invalid_call_to_action, and error.message gives the reason. SocialAPI forwards any additional keys in platform_data.google that name one of Google’s writable local post fields (event, offer, alertType, languageCode) to Google without validating them, so Google’s own rules apply to their content. SocialAPI drops every other key, including keys meant for other platforms in the same post. See Google’s LocalPost reference for the full shape of event and offer.

Event post example


4. Update post

A local post cannot be edited after it is published. To change a published post, delete it (section 5) and publish a new one. Before publishing, PATCH /v1/posts/{pid} edits a post in draft, scheduled, or failed status. The change applies when the post publishes:
The response (HTTP 200) is the updated post, in the same shape as the create response. A PATCH on a published post returns 409 post.state_invalid (“Only draft, scheduled, or failed posts can be edited”). See Scheduling for rescheduling and the full list of editable fields.

5. Delete post

DELETE /v1/posts/{pid} deletes the local post from Google for every published target, and removes a draft, scheduled, or failed post from SocialAPI:
Response (HTTP 200):
If Google refuses the delete, or the local post no longer exists on Google, the target’s outcome is failed with Google’s reason in message, and SocialAPI keeps the post ("deleted": false). To remove the post from one location of a multi-target post, send POST /v1/posts/{pid}/unpublish with that target’s account_id:

6. Retrieve posts

GET /v1/posts lists posts, filtered by platform or account:
Response (HTTP 200):
  • platform_post_id is Google’s full resource name for the local post. Treat it as an opaque string.
  • permalink is the link Google returns to view the post.
  • Google reports no engagement counts for local posts. A Google target has no metrics object, or one whose likes, comments, shares, and saves are all 0. Location-level performance (views, calls, direction requests, website clicks) is at Performance metrics.

7. Quirks, errors, and recovery

Scheduling is held by SocialAPI

Google publishes a local post the moment it is created and has no scheduling of its own. With scheduled_at, SocialAPI keeps the post as scheduled and creates it on Google at that time. Until then the post exists only in SocialAPI, and you can still edit or cancel it.

A published post cannot be edited

PATCH /v1/posts/{pid} works only before publishing. A published local post keeps its text, image, and button until you delete it.

The location must allow posting

A location whose merchant does not control the profile (details.has_voice_of_merchant is false) cannot publish. details.can_operate_local_post reports whether the location supports local posts at all. Both flags are described on Google Business Profile locations.

Posting caps

SocialAPI refuses a publish that would pass 25 posts in an hour or 50 posts in 24 hours for one account, with 429 publishing.velocity_limit. A scheduled post is held and published when the window clears. See Posting velocity caps.

Errors on a failed target

A failed target carries an error object:
  • platform.google.api_error: Google rejected the post. message carries Google’s reason, for example an EVENT post with no event.title, an ALERT post with no alertType, or an image Google could not fetch. Fix the request and retry.
  • platform.google.access_denied: Google refused the operation for this location, for example because posting is disabled on the profile or the connected Google account has no role on the location. message carries Google’s reason. Reconnecting does not fix it: resolve it in Google Business Profile.
  • platform.google.auth: Google no longer accepts the connection. Reconnect the account.
  • platform.google.rate_limit: Google’s own limit was reached. Wait, then retry the post.

Recovery

  • Retry a failed or partial post with POST /v1/posts/{pid}/retry. A retry costs 1 post credit.
  • To change a published post, delete it and publish a new one.
All codes, with their HTTP status, are listed in Errors.

8. Full worked example

This example uploads an image, publishes an offer post with it, and checks the result. Step 1: Upload the image
Response (HTTP 201):
Step 2: Publish the offer post
The response (HTTP 201) has "status": "publishing" and the post id, as in section 3. Step 3: Check the result
Response (HTTP 200) once Google has the post:
If the target is failed, read targets[].error (section 7), fix the request, and call POST /v1/posts/{pid}/retry.

9. Required OAuth scopes

Publishing uses 1 of the scopes SocialAPI’s Google app requests when an account connects. You register no Google app and configure nothing. The scopes that identify the Google login are listed in Scopes. The scopes a scoped API key needs, the credit cost of a post, and the MCP tools that publish are on Publishing.
Last modified on October 13, 2026