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

# Start a connection

> Get the URL to send a customer to so they can connect an account.



## OpenAPI

````yaml /openapi.yaml post /v1/connections
openapi: 3.1.0
info:
  title: Nylon API
  version: 1.0.0
  description: |
    One API for publishing to twelve social networks.

    You address a post to connected profile ids; Nylon knows which network each
    one belongs to, what that network accepts, and how to get the media there.
    Character limits, media specs, upload protocols and threading rules are
    normalised before the request reaches a platform, and every failure comes
    back in one error taxonomy.

    ## Conventions

    - Request and response fields are `snake_case`.
    - Successful responses wrap the payload in `data`. List responses add
      `meta.pagination`.
    - Failures return `{ "error": { "code", "message", "details?" } }`.
      Branch on `code`; `message` is written for humans and may change.
    - Times are ISO 8601 with a `Z` offset.
    - Successful responses carry `RateLimit-Limit`, `RateLimit-Remaining` and
      `RateLimit-Reset`. A `429` carries those plus `Retry-After`.
servers:
  - url: https://api.nylon.dev
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Posts
    description: Create, schedule, inspect, edit and retry posts.
  - name: Profiles
    description: Social profiles connected to the authenticated Nylon account.
  - name: Connections
    description: Start a connection and see which networks are available.
  - name: Networks
    description: What each network accepts, as data.
  - name: Validation
    description: Dry-run a post without publishing it.
  - name: Webhooks
    description: Endpoints Nylon calls when a post finishes or a profile stops working.
paths:
  /v1/connections:
    post:
      tags:
        - Connections
      summary: Start a connection
      description: |
        Nylon runs the OAuth apps, so there is no server-to-server way to
        connect an account — the customer has to approve it. What this returns
        is the URL to send them to, already scoped to their Nylon
        organization.

        `flow` says what opens: `oauth_redirect` goes straight to the
        provider's consent screen; `nylon_ui` opens Nylon, because Bluesky
        needs an app password typed in and Mastodon needs a server chosen
        first.

        Billing is checked **here**, before the redirect. Being sent to a
        provider, approving an app and only then being refused leaves an
        authorization granted for nothing.
      operationId: createConnection
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateConnectionRequest'
            examples:
              withReturn:
                summary: Return the customer to your own app afterwards
                value:
                  network: linkedin
                  redirect_url: https://app.example.com/settings/social
      responses:
        '201':
          description: The connection URL.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ConnectionStartResponse'
              examples:
                success:
                  value:
                    data:
                      network: linkedin
                      connect_url: >-
                        https://www.app.nylon.dev/connections?connect=linkedin&redirect_url=https%3A%2F%2Fapp.example.com%2Fsettings%2Fsocial
                      flow: nylon_ui
                      expires_at: null
        '400':
          description: Unknown network, or a network this account has no credentials for.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  schemas:
    CreateConnectionRequest:
      type: object
      required:
        - network
      properties:
        network:
          type: string
          description: >-
            The network to connect. Common aliases such as `twitter` resolve to
            `x`.
          example: linkedin
        redirect_url:
          type:
            - string
            - 'null'
          format: uri
          description: Where to send the customer once the connection is made.
          example: https://app.example.com/settings/social
    ConnectionStartResponse:
      type: object
      required:
        - data
      properties:
        data:
          type: object
          required:
            - network
            - connect_url
            - flow
          properties:
            network:
              $ref: '#/components/schemas/Network'
            connect_url:
              type: string
              format: uri
              description: |
                Open this in the customer's browser. It carries no credential
                of its own — it is opened by a signed-in Nylon user, and that
                session is what authorises the connection.
            flow:
              $ref: '#/components/schemas/ConnectFlow'
            expires_at:
              type:
                - string
                - 'null'
              format: date-time
              description: Always null today; the URL does not expire on its own.
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          $ref: '#/components/schemas/Error'
    Network:
      type: string
      description: A network Nylon publishes to.
      enum:
        - facebook
        - instagram
        - x
        - linkedin
        - pinterest
        - bluesky
        - threads
        - tiktok
        - youtube
        - google_business
        - mastodon
        - discord
      example: instagram
    ConnectFlow:
      type: string
      description: |
        `oauth_redirect` opens the provider's consent screen directly.
        `nylon_ui` opens Nylon, because the network needs something typed in
        first — an app password for Bluesky, a server for Mastodon.
      enum:
        - oauth_redirect
        - nylon_ui
      example: oauth_redirect
    Error:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: string
          description: The stable identifier to branch on.
          enum:
            - invalid_request
            - unauthorized
            - payment_required
            - forbidden
            - not_found
            - conflict
            - rate_limited
            - unsupported
            - publish_failed
            - internal_error
          example: unauthorized
        message:
          type: string
          description: Written for humans. Do not match on it.
          example: A valid Nylon API key is required.
        details:
          type: array
          description: Present when the failure has a per-field or per-network breakdown.
          items:
            $ref: '#/components/schemas/ErrorDetail'
    ErrorDetail:
      type: object
      required:
        - message
      properties:
        field:
          type: string
          description: The request field the problem is about.
          example: profile_ids
        network:
          type: string
          description: The network the problem is about.
          example: instagram
        code:
          type: string
          description: |
            Machine-readable identifier for this problem. On a per-network
            detail this is a publishing code: `invalid_request`,
            `unsupported`, `media_error`, `reauthentication_required`,
            `rejected_by_network`, `network_error`, `timeout`,
            `profile_unavailable` or `internal_error`.
          example: invalid_request
        message:
          type: string
          example: >-
            Instagram requires at least 1 media item — text-only posts are not
            supported.
  responses:
    Unauthorized:
      description: The bearer API key is missing, malformed or revoked.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            missingKey:
              value:
                error:
                  code: unauthorized
                  message: A valid Nylon API key is required.
    PaymentRequired:
      description: |
        Billing is blocking the action. Most often an addressed profile is
        beyond the free allowance while the subscription is inactive — it is
        still connected and still listed with `suspended: true`, but nothing
        can be published through it until billing restarts.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            suspended:
              value:
                error:
                  code: payment_required
                  message: >-
                    Nylon Studio is beyond your free allowance and your
                    subscription is not active. Restart billing to publish
                    through them again.
    RateLimited:
      description: |
        Too many requests for this API key. Reads allow 120 requests a minute;
        publishing endpoints allow 30, because each one costs real upstream
        calls. The limit is per key, not per IP.
      headers:
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
        RateLimit-Limit:
          $ref: '#/components/headers/RateLimitLimit'
        RateLimit-Remaining:
          $ref: '#/components/headers/RateLimitRemaining'
        RateLimit-Reset:
          $ref: '#/components/headers/RateLimitReset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            throttled:
              value:
                error:
                  code: rate_limited
                  message: Too many requests. Retry after the window resets.
    InternalError:
      description: Nylon encountered an unexpected error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  headers:
    RetryAfter:
      description: Seconds to wait before retrying.
      schema:
        type: integer
        example: 47
    RateLimitLimit:
      description: Requests allowed in the current window.
      schema:
        type: integer
        example: 120
    RateLimitRemaining:
      description: Requests left in the current window.
      schema:
        type: integer
        example: 119
    RateLimitReset:
      description: Seconds until the window resets.
      schema:
        type: integer
        example: 47
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Nylon API key
      description: An API key beginning with `nylon_live_`.

````