postzen-dev Connect API

Start and complete OAuth account connection flows.

Operations 4

GET /v1/connect/pinterest/select-board List Pinterest boards for the connect flow #
POST /v1/connect/pinterest/select-board Select Pinterest board #
GET /v1/connect/{platform} Create an OAuth connect URL #
POST /v1/connect/{platform} Complete an OAuth connection #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/postzen-dev:postzen-dev-connect-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

postzen-dev-connect-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: PostZen Public Connect API
  version: 1.0.0
  description: The PostZen Public API lets server-side integrations manage profiles, connected social accounts, OAuth connection flows, media uploads, post creation, and outbound webhooks.
servers:
- url: https://api.postzen.dev
  description: Production API
security:
- bearerAuth: []
tags:
- name: Connect
  description: Start and complete OAuth account connection flows.
paths:
  /v1/connect/pinterest/select-board:
    get:
      tags:
      - Connect
      operationId: listPinterestBoardsForSelection
      summary: List Pinterest boards for the connect flow
      description: Lists boards after Pinterest OAuth completes so the client can show a board picker. The state handle remains valid for board selection for 30 minutes from connect-flow creation. This endpoint requires a read-write API key.
      parameters:
      - name: state
        in: query
        required: true
        description: State token returned by `GET /v1/connect/pinterest`.
        schema:
          type: string
      responses:
        '200':
          description: Pinterest boards returned for selection.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PinterestBoardsResponse'
              example:
                boards:
                - id: '123456789012345678'
                  name: Product inspiration
                  privacy: PUBLIC
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: The connect session was not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: connect_session_not_found
        '409':
          description: Pinterest OAuth has not completed for this connect session.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: connect_not_completed
        '410':
          description: The connect session is too old for board selection.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: connect_session_expired
        '424':
          description: The connected Pinterest account is no longer available.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: not_connected
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalError'
        '502':
          description: Pinterest could not answer the request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: request_failed
    post:
      tags:
      - Connect
      operationId: selectPinterestBoard
      summary: Select Pinterest board
      description: Verifies and stores the default board for the Pinterest account created by the connect session. This endpoint requires a read-write API key.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PinterestSelectBoardRequest'
            example:
              state: 3q2Xv8Zk1mR5tY7wA9bC4dE6
              boardId: '123456789012345678'
              boardName: Product inspiration
              redirectUrl: https://example.com/connect/complete
      responses:
        '200':
          description: Pinterest board selected and stored as the account default.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PinterestSelectBoardResponse'
              example:
                message: Pinterest connected successfully with default board
                account:
                  _id: j97kp4mw2xnv6r1t8c3zq5bs9fh0yg4d
                  platform: pinterest
                  providerAccountId: '987654321098765432'
                  profileId:
                    _id: jh72r5nqk9wx3v8m1t4cz6bs0fy5dg3e
                    name: Marketing Team
                    slug: marketing-team
                    color: '#4caf50'
                  username: acme
                  displayName: Acme
                  status: connected
                  isActive: true
                  connectedAt: '2026-06-19T16:00:00.000Z'
                  defaultBoardId: '123456789012345678'
                  defaultBoardName: Product inspiration
                redirectUrl: https://example.com/connect/complete?connected=pinterest&profileId=jh72r5nqk9wx3v8m1t4cz6bs0fy5dg3e&board=Product+inspiration
        '400':
          description: Invalid request or the selected board does not exist.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: board_not_found
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: The connect session was not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: connect_session_not_found
        '409':
          description: Pinterest OAuth has not completed for this connect session.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: connect_not_completed
        '410':
          description: The connect session is too old for board selection.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: connect_session_expired
        '424':
          description: The connected Pinterest account is no longer available.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: not_connected
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '500':
          $ref: '#/components/responses/InternalError'
        '502':
          description: Pinterest could not verify the board.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: request_failed
  /v1/connect/{platform}:
    parameters:
    - name: platform
      in: path
      required: true
      description: Social platform to connect. `twitter` is accepted as an alias for `x`.
      schema:
        $ref: '#/components/schemas/PublicPlatformInput'
    get:
      tags:
      - Connect
      operationId: createConnectUrl
      summary: Create an OAuth connect URL
      description: 'Initiates an OAuth connection flow and returns an authorization URL to redirect the user to. The OAuth state expires after 10 minutes. This endpoint requires a read-write API key.


        For `bluesky`, the returned `authUrl` is a PostZen-hosted page where the user enters their Bluesky handle and app password (no developer app or OAuth redirect is required); the connection completes when they submit that form.


        For `telegram`, the returned `authUrl` is a PostZen-hosted page that issues a short-lived access code (there is no OAuth grant and no Telegram authorization screen); the connection completes when the user adds @PostZenScheduleBot as an administrator of a channel or group and sends that code to the bot.


        To reauthorize an existing account, pass `accountId` instead of `profileId`. The flow is pinned to that account: the user must authorize the same provider account, and the account keeps its id, profile, scheduled posts and comment automations. Reauthorizing an account whose status is `connected` or `needsReauth` does not count against your plan''s included accounts. Disconnecting and connecting again instead creates a new account id and cancels the account''s pending posts, so prefer `accountId`.'
      parameters:
      - name: profileId
        in: query
        required: false
        description: PostZen profile id to attach a new account to. Required unless `accountId` is set; when both are set they must agree.
        schema:
          type: string
      - name: accountId
        in: query
        required: false
        description: Reauthorize an existing account instead of connecting a new one. The account keeps its id, profile, scheduled posts and comment automations. The platform in the path must match the account's platform. Use this when an account's status is `needsReauth`.
        schema:
          type: string
      - name: redirectUrl
        in: query
        description: Custom URL PostZen redirects to after the connection completes.
        schema:
          type: string
          format: uri
      responses:
        '200':
          description: OAuth URL created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConnectStartResponse'
              example:
                authUrl: https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=86xk2ab9cdef01&state=3q2Xv8Zk1mR5tY7wA9bC4dE6&scope=openid%20profile%20w_member_social%20email
                state: 3q2Xv8Zk1mR5tY7wA9bC4dE6
                usage:
                  accountsConnected: 1
                  accountsIncluded: 2
                  planId: free
                  upgradeUrl: https://app.postzen.dev/billing?source=account_usage&utm_source=api&utm_medium=usage&utm_campaign=account_cap
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          $ref: '#/components/responses/InternalError'
    post:
      tags:
      - Connect
      operationId: completeConnect
      summary: Complete an OAuth connection
      description: Exchanges an OAuth authorization code for tokens and connects the account to the specified profile. This endpoint requires a read-write API key.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ConnectCompleteRequest'
            example:
              code: AQTF0v6PZnq1yTkGxg3M4S8d
              state: 3q2Xv8Zk1mR5tY7wA9bC4dE6
              profileId: jh72r5nqk9wx3v8m1t4cz6bs0fy5dg3e
      responses:
        '200':
          description: Account connected.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConnectCompleteResponse'
              example:
                message: Account connected successfully
                platform: twitter
                profileId: jh72r5nqk9wx3v8m1t4cz6bs0fy5dg3e
                status: connected
                accounts:
                - _id: j97kp4mw2xnv6r1t8c3zq5bs9fh0yg4d
                  platform: twitter
                  providerAccountId: '1934567890123456789'
                  profileId:
                    _id: jh72r5nqk9wx3v8m1t4cz6bs0fy5dg3e
                    name: Marketing Team
                    slug: marketing-team
                    color: '#4caf50'
                  username: acme
                  displayName: Acme
                  status: connected
                  isActive: true
                  connectedAt: '2026-06-19T16:00:00.000Z'
        '400':
          description: Invalid request, expired OAuth state, or a failed platform callback. Callback failures return a camelCase error code with an optional `errorDescription`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConnectCompleteErrorResponse'
              example:
                error: oauthCallbackFailed
                errorDescription: OAuth callback did not complete a matching platform connection
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          description: The API key does not have access to the profile, or the OAuth state belongs to a different user or profile.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConnectCompleteErrorResponse'
              example:
                error: oauthStateUserMismatch
        '404':
          $ref: '#/components/responses/NotFound'
        '500':
          description: The platform token exchange failed or an unexpected server error occurred.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConnectCompleteErrorResponse'
              example:
                error: linkedinOauthFailed
components:
  schemas:
    ConnectCompleteErrorResponse:
      type: object
      required:
      - error
      properties:
        error:
          type: string
          description: Human-readable message, or a camelCase error code (for example `oauthCallbackFailed`) when the platform callback fails.
        errorDescription:
          type: string
          description: Additional detail reported by the platform, when available.
    PinterestSelectBoardRequest:
      type: object
      additionalProperties: false
      required:
      - state
      - boardId
      properties:
        state:
          type: string
          minLength: 1
        boardId:
          type: string
          minLength: 1
        boardName:
          type: string
        redirectUrl:
          type: string
          format: uri
    PublicPlatformOutput:
      type: string
      enum:
      - twitter
      - instagram
      - tiktok
      - linkedin
      - facebook
      - youtube
      - threads
      - pinterest
      - bluesky
      - telegram
    ConnectCompleteRequest:
      type: object
      required:
      - code
      - state
      - profileId
      properties:
        code:
          type: string
          description: OAuth authorization code returned by the platform.
        state:
          type: string
          description: State returned by `GET /v1/connect/{platform}`.
        profileId:
          type: string
          description: PostZen profile id used when the connection was initiated.
    PaymentRequiredError:
      type: object
      required:
      - error
      - code
      - reason
      - documentationUrl
      - dashboardUrl
      properties:
        error:
          type: string
          description: Human-readable reason. Plan-limit messages end with `Upgrade at <billing URL>.`
        code:
          type: string
          const: paymentRequired
        reason:
          type: string
          enum:
          - freeTierExceeded
          - xRequiresPaymentMethod
          - accountPaused
          - freePostLimitExceeded
        documentationUrl:
          type: string
          format: uri
        dashboardUrl:
          type: string
          format: uri
        details:
          type: object
          description: Reason-specific context. Account-connection limits use the plan and account fields; `freePostLimitExceeded` uses `postsUsed`, `postLimit` and `periodEndsAt`.
          properties:
            planId:
              type: string
              enum:
              - free
              - starter
              - pro
              - scale
            includedAccounts:
              type: number
            freeTierAccountLimit:
              type: number
              description: Same value as `includedAccounts`; retained for compatibility.
            currentAccountCount:
              type: number
            hasPaymentMethod:
              type: boolean
            postsUsed:
              type: number
              description: Platform-posts already counted in the current UTC month.
            postLimit:
              type: number
              description: The plan's monthly platform-post allowance.
            periodEndsAt:
              type: string
              format: date-time
              description: 'When the monthly post allowance resets: the start of the next UTC month.'
    PinterestBoardsResponse:
      type: object
      required:
      - boards
      properties:
        boards:
          type: array
          items:
            $ref: '#/components/schemas/PinterestBoard'
    PinterestSelectBoardResponse:
      type: object
      required:
      - message
      - account
      properties:
        message:
          type: string
          const: Pinterest connected successfully with default board
        account:
          $ref: '#/components/schemas/Account'
        redirectUrl:
          type: string
          format: uri
    PublicPlatformInput:
      type: string
      enum:
      - twitter
      - x
      - instagram
      - tiktok
      - linkedin
      - facebook
      - youtube
      - threads
      - pinterest
      - bluesky
      - telegram
    ErrorResponse:
      type: object
      required:
      - error
      properties:
        error:
          type: string
        type:
          type: string
        code:
          type: string
        param:
          type:
          - string
          - 'null'
    RateLimitError:
      type: object
      required:
      - error
      - retryAfter
      properties:
        error:
          type: string
          const: rate_limited
        retryAfter:
          type: integer
          minimum: 1
          description: Number of seconds to wait before retrying.
    PinterestBoard:
      type: object
      required:
      - id
      - name
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type: string
        privacy:
          type: string
          enum:
          - PUBLIC
          - PROTECTED
          - SECRET
        pinCount:
          type: integer
          minimum: 0
    ConnectCompleteResponse:
      type: object
      required:
      - message
      - platform
      - profileId
      - status
      properties:
        message:
          type: string
        platform:
          $ref: '#/components/schemas/PublicPlatformOutput'
        profileId:
          type: string
        status:
          type: string
          enum:
          - connected
          - needsReauth
        missingScopes:
          type: array
          items:
            type: string
        connectedAccountCount:
          type: integer
          minimum: 0
        accounts:
          type: array
          items:
            $ref: '#/components/schemas/Account'
    AccountProfileSummary:
      type: object
      required:
      - _id
      - name
      - slug
      - color
      properties:
        _id:
          type: string
        name:
          type: string
        slug:
          type: string
        color:
          type: string
    Account:
      type: object
      required:
      - _id
      - platform
      - providerAccountId
      - profileId
      - username
      - displayName
      - status
      - isActive
      - connectedAt
      properties:
        _id:
          type: string
        platform:
          $ref: '#/components/schemas/PublicPlatformOutput'
        providerAccountId:
          type: string
        profileId:
          $ref: '#/components/schemas/AccountProfileSummary'
        username:
          type: string
        displayName:
          type: string
        profileUrl:
          type: string
          format: uri
        avatarUrl:
          type: string
          format: uri
        status:
          type: string
          enum:
          - connected
          - needsReauth
          - disconnected
          - disabled
        isActive:
          type: boolean
        connectedAt:
          type: string
          format: date-time
        lastSyncedAt:
          type: string
          format: date-time
        defaultBoardId:
          type: string
          description: Default Pinterest board id. Present only when one has been selected for a Pinterest account.
        defaultBoardName:
          type: string
          description: Default Pinterest board name. Present when Pinterest returned a name for the selected default board.
    ConnectStartResponse:
      type: object
      required:
      - authUrl
      - state
      properties:
        authUrl:
          type: string
          format: uri
          description: URL to redirect the user to for platform authorization.
        state:
          type: string
          description: OAuth state parameter generated by PostZen.
        usage:
          type: object
          description: Connected-account usage once this connection completes, counting the account being connected.
          required:
          - accountsConnected
          - accountsIncluded
          - planId
          - upgradeUrl
          properties:
            accountsConnected:
              type: number
              description: Active connected accounts after this connection, including the one being connected.
            accountsIncluded:
              type: number
              description: Accounts included in the plan. On Free this is a hard cap; paid plans bill extra accounts.
            planId:
              type: string
              enum:
              - free
              - starter
              - pro
              - scale
            upgradeUrl:
              type: string
              format: uri
              description: Dashboard billing page, where the user can move to a plan with more accounts.
  responses:
    InternalError:
      description: Unexpected server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error: Failed to create post
    Unauthorized:
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error: Unauthorized
    NotFound:
      description: Resource not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error: Not found
    TooManyRequests:
      description: Rate limit exceeded. Retry after the interval indicated by the `Retry-After` header.
      headers:
        Retry-After:
          description: Number of seconds to wait before retrying.
          schema:
            type: integer
            minimum: 1
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/RateLimitError'
          example:
            error: rate_limited
            retryAfter: 30
    Forbidden:
      description: The API key does not have sufficient permission or profile access.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error: API key requires read_write permission
    PaymentRequired:
      description: A plan limit, missing payment method, or paused account prevents the requested operation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/PaymentRequiredError'
          example:
            error: The Free plan includes 2 connected accounts. Upgrade your plan to connect more. Upgrade at https://app.postzen.dev/billing?source=account_limit_error&utm_source=api&utm_medium=error&utm_campaign=account_cap.
            code: paymentRequired
            reason: freeTierExceeded
            documentationUrl: https://docs.postzen.dev/api-reference/connect/create-connect-url
            dashboardUrl: https://app.postzen.dev/billing
            details:
              planId: free
              includedAccounts: 2
              freeTierAccountLimit: 2
              currentAccountCount: 2
              hasPaymentMethod: false
    BadRequest:
      description: Invalid request.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error: JSON body is required
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: PostZen API key.