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

# Exchange Code for Token

> Exchanges the authorization code from your callback for a `pos_` access token. Call this from your server, since it requires your client secret. The code expires 10 minutes after it is issued and can only be used once. The access token does not expire; users revoke it from Settings > Approved Apps.

This endpoint lives outside `/public/v1` and takes no API key. The token it returns is used as the `Authorization` header on every other endpoint in this reference.

The user approved your app and PostQueen sent them back to you with a code on the query string. Trade it here for the `pos_` token you will use on every call after this one.

Two things about that code are worth planning around. It is good for ten minutes, and it works exactly once, because the exchange clears it as it hands you the token. Run the same request twice and the second one comes back as `invalid_grant`.

<Warning>
  Make this call from your server. It carries your client secret, which never belongs in a browser or a mobile binary. A wrong secret and an unknown `client_id` both answer `401` with `invalid_client`, so the response will not tell you which of the two you got wrong.
</Warning>

The token that comes back does not expire on a clock. It stops working when the user revokes your app from **Settings > Approved Apps**. Full flow, including how to register the app in the first place, on [OAuth2 Authentication](/public-api/oauth).


## OpenAPI

````yaml POST /oauth/token
openapi: 3.1.0
info:
  title: PostQueen Public API
  description: >-
    API for managing social media posts, integrations, and media uploads in
    PostQueen.


    ## Authentication


    All endpoints require an API key passed in the `Authorization` header:


    ```

    Authorization: your-api-key

    ```


    Get your API key from PostQueen Settings.


    ## Rate Limits


    The create-post endpoint is capped per organization per hour. With
    `API_LIMIT` unset the ceiling is **90 requests per hour**; the shipped
    Compose files and PostQueen Cloud both set it to **30**. No other endpoint
    is throttled.


    ## Terminology


    The UI uses `channel`, but the API uses `integration`. They refer to the
    same thing.


    ## Supported Platforms (34)


    **Social Platforms:** X (Twitter), LinkedIn, LinkedIn Page, Facebook,
    Instagram, Instagram Standalone, Threads, Bluesky, Mastodon, Warpcast
    (Farcaster), Nostr, VK


    **Video Platforms:** YouTube, TikTok


    **Community Platforms:** Reddit, Lemmy, Discord, Slack, Telegram, Kick,
    Twitch


    **Design Platforms:** Pinterest, Dribbble


    **Blogging Platforms:** Medium, Dev.to, Hashnode, WordPress, Moltbook


    **Business:** Google My Business (GMB), Listmonk (newsletters), Whop, Skool
  license:
    name: MIT
  version: 1.0.0
servers:
  - url: https://api.postqueen.ai/public/v1
    description: PostQueen Cloud
  - url: https://{host}/api/public/v1
    description: Self-hosted
    variables:
      host:
        default: localhost:4007
        description: Your PostQueen instance domain
security:
  - ApiKeyAuth: []
tags:
  - name: Integrations
    description: Manage connected social media channels
  - name: Posts
    description: Create, list, and delete posts
  - name: Uploads
    description: Upload media files
  - name: Notifications
    description: View organization notifications
  - name: Analytics
    description: View analytics for integrations and posts
  - name: Video Generation
    description: Generate videos with AI
  - name: OAuth
    description: Authorize third-party apps and exchange codes for access tokens
paths:
  /oauth/token:
    post:
      tags:
        - OAuth
      summary: Exchange an authorization code for an access token
      description: >-
        Exchanges the authorization code from your callback for a `pos_` access
        token. Call this from your server, since it requires your client secret.
        The code expires 10 minutes after it is issued and can only be used
        once. The access token does not expire; users revoke it from Settings >
        Approved Apps.


        This endpoint lives outside `/public/v1` and takes no API key. The token
        it returns is used as the `Authorization` header on every other endpoint
        in this reference.
      operationId: oauthToken
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                grant_type:
                  type: string
                  enum:
                    - authorization_code
                  description: Must be `authorization_code`
                code:
                  type: string
                  description: The authorization code from your callback URL
                client_id:
                  type: string
                  description: Your app's Client ID (starts with `pca_`)
                client_secret:
                  type: string
                  description: Your app's Client Secret (starts with `pcs_`)
              required:
                - grant_type
                - code
                - client_id
                - client_secret
            example:
              grant_type: authorization_code
              code: abc123
              client_id: pca_VklHTpdEJ6dJ73FHQEJ97qVA0lcMDsrs
              client_secret: pcs_your_client_secret
      responses:
        '200':
          description: Access token issued
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    description: Organization ID of the user who authorized your app
                  cus:
                    type: string
                    nullable: true
                    description: >-
                      The organization's Stripe customer ID, or null when it has
                      none
                  access_token:
                    type: string
                    description: >-
                      The token to send in the `Authorization` header (starts
                      with `pos_`)
                  token_type:
                    type: string
                    description: Always `bearer`
              example:
                id: 85460a39-6329-4cf4-a252-187ce89a3480
                cus: cus_stripe_customer_id
                access_token: pos_aBcDeFgHiJkLmNoPqRsTuVwXyZ1234567890abcd
                token_type: bearer
        '400':
          description: >-
            `unsupported_grant_type` when `grant_type` is not
            `authorization_code`, or `invalid_grant` when the code is unknown,
            belongs to another app, or has expired
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    enum:
                      - unsupported_grant_type
                      - invalid_grant
                  error_description:
                    type: string
                    description: Present only when the code has expired
              example:
                error: invalid_grant
                error_description: Code has expired
        '401':
          description: >-
            `invalid_client` when the Client ID is unknown or the Client Secret
            does not match
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    enum:
                      - invalid_client
              example:
                error: invalid_client
      security: []
      servers:
        - url: https://api.postqueen.ai
          description: PostQueen Cloud
        - url: https://{host}/api
          description: Self-hosted
          variables:
            host:
              default: localhost:5000
              description: Your PostQueen instance domain
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: Your PostQueen API key

````