> ## Documentation Index
> Fetch the complete documentation index at: https://docs.social-api.ai/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Base URL: https://api.social-api.ai/v1. Send your API key in the Authorization header: Authorization: Bearer <your API key>.
> Every error response from /v1 is JSON: { "error": { "code", "message", "meta" (optional) }, "request_id" }. Branch on error.code; use error.message only for logs.
> A 429 response carries a Retry-After header, in seconds, when the limit has a known wait.
> Paginated list endpoints return next_cursor, at the top level or inside pagination (see /guides/pagination). Pass it as the cursor query parameter to get the next page. An absent or empty next_cursor means you have the last page.
> Treat every ID as an opaque string: do not parse it or assume a format.
> Support differs by platform and by operation. Check /platforms/overview before assuming an operation works on a platform. An unsupported operation returns 501 with error.code resource.not_supported.

# Pinterest publishing

> Full reference for publishing Pins via SocialAPI, including the board target, Pin title, description, link, alt text, scheduling, and quirks.

## 1. Overview

A Pin needs a destination board and one image. Pinterest has no text-only or link-only post, and no default board: every Pinterest target sets `board_id`.

| Field | Value |
| - | - |
| Platform slug | `pinterest` |
| Auth type | OAuth 2.0 |
| API | Pinterest API v5 |
| Create post | Yes (a Pin) |
| Update post | No (`409 post.state_invalid` on a published post) |
| Delete post | Yes |
| Schedule | Yes (deferred publish via `scheduled_at`) |
| First comment | No (`first_comment` is ignored) |
| Posting caps | 1,000 posts per 24 hours for each board, with no hourly cap: see [Posting velocity caps](/guides/rate-limits#posting-velocity-caps) |

***

## 2. Supported media

| Content type | How to trigger | Notes |
| - | - | - |
| Image Pin | One image in `media` | The only Pin type SocialAPI publishes |

SocialAPI sends the first `media` item to Pinterest as the Pin's image and ignores the rest. A Pin with no image fails validation on the field `media`. SocialAPI does not check the image's type or size in advance: Pinterest rejects a file it does not accept, and the target fails. A video is not supported.

**Field limits:** title 100 characters, description 800 characters, alt text 500 characters, and link 2,048 characters. A longer value in `platform_data.pinterest` fails validation with `400 publishing.validation_failed`, and the issue names the field. SocialAPI checks the 800-character limit only on `platform_data.pinterest.description`: a longer `text` is sent as is and Pinterest refuses it.

> [!WARNING]
>
> Attach the image through the `media` array. Each item sets a `source_type`: `media_id` for a file you uploaded to SocialAPI, or `url` for a public `http(s)` URL Pinterest can fetch. A `platform_attachment_id` item returns `422 publishing.media.unsupported_source`. To upload first, see [Media](/guides/media).

***

## 3. Create post

Use `POST /v1/posts` with a target that sets `account_id` and `board_id`, and `publish_now: true`. Get `board_id` from [Pinterest boards](/platforms/pinterest/boards#list-boards).

```bash theme={null}
curl -X POST https://api.social-api.ai/v1/posts \
  -H "Authorization: Bearer $SOCAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "One pan, forty minutes, no marinade.",
    "media": [{ "source_type": "media_id", "source": "f47ac10b-58cc-4372-a567-0e02b2c3d479" }],
    "publish_now": true,
    "targets": [{
      "account_id": "acc_01HZ9X3Q4R5M6N7P8V2K0W1J",
      "board_id": "8828"
    }],
    "platform_data": {
      "pinterest": {
        "title": "Weeknight roast chicken",
        "link": "https://example.com/recipes/chicken",
        "alt_text": "A roast chicken on a sheet pan with lemons"
      }
    }
  }'
```

Response (HTTP 201):

```json theme={null}
{
  "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "text": "One pan, forty minutes, no marinade.",
  "status": "publishing",
  "hidden": false,
  "retry_count": 0,
  "created_at": "2026-10-13T09:00:00Z",
  "updated_at": "2026-10-13T09:00:00Z",
  "targets": [
    {
      "account_id": "acc_01HZ9X3Q4R5M6N7P8V2K0W1J",
      "page_id": "sapi_board_01HZ9X3Q4R5M6N7P8V2K0W1J",
      "platform": "pinterest",
      "status": "publishing"
    }
  ]
}
```

### Target field

| Field | Type | Required | Description |
| - | - | - | - |
| `board_id` | string | Yes | The board to Pin to. Use the `id` or the `board_id` that [List boards](/platforms/pinterest/boards#list-boards) returns. `page_id` is accepted as an alias, but sending both fails with `400 validation.duplicate_board_id` |

A target with neither `board_id` nor `page_id` fails with `400 validation.board_id_required`. A `board_id` inside `platform_data` fails with `400 validation.use_board_id`: set it on the target.

### Pin text

The post's `text` is the Pin's description. Set the Pin's title in `platform_data.pinterest.title`: the post's top-level `title` field is not used for a Pin.

### Platform data fields

Send these keys in `platform_data.pinterest` on the post, which applies them to every Pinterest target. To set them for one target, send them flat in that target's `platform_data` (`targets[].platform_data`, with no `pinterest` key). When both set the same key, the target's value wins.

| Key | Type | Required | Notes |
| - | - | - | - |
| `title` | string, up to 100 characters | No | The Pin title |
| `description` | string, up to 800 characters | No | Replaces `text` as the Pin description |
| `link` | string, up to 2,048 characters | No | The destination URL. An absolute `http` or `https` URL |
| `alt_text` | string, up to 500 characters | No | Alt text for the image |

SocialAPI forwards any additional keys in `platform_data.pinterest` that the table above lists, and no others. Pinterest has no other publish options that SocialAPI passes through: an unlisted key is ignored without a warning.

### Scheduling

Set `scheduled_at` to an ISO 8601 timestamp (UTC) instead of `publish_now`. SocialAPI holds the post and publishes it at that time.

```json theme={null}
{
  "media": [{ "source_type": "media_id", "source": "f47ac10b-58cc-4372-a567-0e02b2c3d479" }],
  "targets": [{
    "account_id": "acc_01HZ9X3Q4R5M6N7P8V2K0W1J",
    "board_id": "8828"
  }],
  "scheduled_at": "2026-11-15T10:00:00Z"
}
```

***

## 4. Update post

SocialAPI offers no edit of a published Pin. Pinterest's edit call is in beta and not open to every app, and a Pin's image never changes. `PATCH /v1/posts/{pid}` edits only a post in `draft`, `scheduled`, or `failed` status, and returns `409 post.state_invalid` for a published post. To change a Pin, delete it and publish a new one: the new Pin has a new ID.

***

## 5. Delete post

`DELETE /v1/posts/{pid}` deletes the Pin from Pinterest when its Pinterest target is `published`. See [Delete a post](/guides/delivery#delete-a-post). Deleting a board deletes every Pin on it: see [Pinterest boards](/platforms/pinterest/boards#delete-a-board).

```bash theme={null}
curl -X DELETE https://api.social-api.ai/v1/posts/7c9e6679-7425-40de-944b-e07fc1f90ae7 \
  -H "Authorization: Bearer $SOCAPI_KEY"
```

***

## 6. Retrieve posts

`GET /v1/platforms/pinterest/accounts/{id}/pins` returns the account's Pins, read from Pinterest on every call. The response and its fields are in [List Pins](/platforms/pinterest#list-pins). Each published target of a post you created carries `platform_post_id` and `permalink`.

Pinterest reports no engagement counts on the Pin list, so a Pin has no metrics. `GET /v1/posts/{pid}/metrics` returns HTTP 200, and the Pinterest target carries `error.code: resource.not_supported`. Account-level counts are in [Analytics](/guides/analytics).

***

## 7. Quirks, errors, and recovery

### A Pin needs a board

There is no default board, and a target without `board_id` is refused. When the connected account does not own the board, Pinterest refuses the Pin and the target fails with `403 platform.pinterest.403`.

### Boards and Pins are read live

SocialAPI stores no board or Pin. A board you just created appears on the next call. If Pinterest is unavailable, a call fails.

### Errors on a failed target

A publish that fails after the request returned puts a structured error on the target, in `targets[].error`, with its `code`. Every code is in [Errors](/guides/errors).

* `401 platform.pinterest.auth`: Pinterest reported that authentication failed. The account is marked `token_expired`, and every later call that acts on the account returns `403 account.reconnection_required` until you reconnect it.
* `401 platform.pinterest.unauthorized`: Pinterest answered 401 without naming the token. The account keeps working. Reconnect if it persists.
* `403 platform.pinterest.403`: Pinterest refused the action for this account or board. Read `message`.
* `404 platform.pinterest.404`: Pinterest reports that the board or Pin does not exist.
* `429 platform.pinterest.rate_limit`: Pinterest's own limit. Wait, then retry.

### Recovery

* **Rate limit.** Wait for the seconds in `Retry-After`, or at least 60 seconds when it is absent, then send `POST /v1/posts/{pid}/retry`. See [Delivery](/guides/delivery).
* **Auth error.** Reconnect the Pinterest account through the OAuth flow.
* **Wrong board.** Delete the Pin, then publish it to the right board.

***

## 8. Full worked example

This example finds a board, publishes a Pin to it, and reads the result.

**Step 1: List boards**

```bash theme={null}
curl https://api.social-api.ai/v1/accounts/acc_01HZ9X3Q4R5M6N7P8V2K0W1J/boards \
  -H "Authorization: Bearer $SOCAPI_KEY"
```

Response (HTTP 200):

```json theme={null}
{
  "data": [
    {
      "id": "sapi_board_01HZ9X3Q4R5M6N7P8V2K0W1J",
      "board_id": "8828",
      "name": "Recipes",
      "privacy": "PUBLIC"
    }
  ]
}
```

**Step 2: Upload media**

Upload the image and verify it as described in [Media](/guides/media). The result is a `media_id`, here `f47ac10b-58cc-4372-a567-0e02b2c3d479`.

**Step 3: Publish the Pin**

```bash theme={null}
curl -X POST https://api.social-api.ai/v1/posts \
  -H "Authorization: Bearer $SOCAPI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Weeknight dinner idea: sheet-pan salmon.",
    "media": [{ "source_type": "media_id", "source": "f47ac10b-58cc-4372-a567-0e02b2c3d479" }],
    "publish_now": true,
    "targets": [{
      "account_id": "acc_01HZ9X3Q4R5M6N7P8V2K0W1J",
      "board_id": "8828"
    }],
    "platform_data": {
      "pinterest": {
        "title": "Sheet-pan salmon",
        "link": "https://example.com/recipes/salmon"
      }
    }
  }'
```

Response (HTTP 201): the post with `status: "publishing"`, as in [Create post](#3-create-post).

**Step 4: Check the status**

```bash theme={null}
curl https://api.social-api.ai/v1/posts/7c9e6679-7425-40de-944b-e07fc1f90ae7 \
  -H "Authorization: Bearer $SOCAPI_KEY"
```

Response (HTTP 200) once published:

```json theme={null}
{
  "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "text": "Weeknight dinner idea: sheet-pan salmon.",
  "status": "published",
  "hidden": false,
  "retry_count": 0,
  "published_at": "2026-10-13T09:00:04Z",
  "created_at": "2026-10-13T09:00:00Z",
  "updated_at": "2026-10-13T09:00:04Z",
  "targets": [
    {
      "account_id": "acc_01HZ9X3Q4R5M6N7P8V2K0W1J",
      "page_id": "sapi_board_01HZ9X3Q4R5M6N7P8V2K0W1J",
      "platform": "pinterest",
      "status": "published",
      "platform_post_id": "813744",
      "permalink": "https://www.pinterest.com/pin/813744/",
      "published_at": "2026-10-13T09:00:04Z"
    }
  ]
}
```

***

## 9. Required OAuth scopes

SocialAPI's Pinterest app requests these scopes during the OAuth flow. You configure nothing. The full list is in [Pinterest scopes](/platforms/pinterest#scopes).

| Scope | Purpose |
| - | - |
| `boards:read` | List boards to choose `board_id` |
| `boards:write` | Required by Pinterest to create and delete Pins |
| `pins:write` | Create and delete Pins |

The scopes a scoped API key needs, the credit cost of a post, and the MCP tools that publish are on [Publishing](/guides/publishing).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.