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

# Native connect (mobile SDKs)

> The two calls the mobile SDKs make to connect an account from inside an
app. With an SDK you never call this endpoint yourself; it is documented
for teams building on a platform without an SDK yet.

`start` verifies and consumes a connect link, creates the user record if
needed, sends `connect.started`, and returns where to log in and which
cookie to watch, plus a one-time capture credential (`captureNonce` and
`clientSecret`, valid one hour).

`capture` hands the provider session read from the app's WebView to
Verso, which encrypts it, creates the connection (folding a previous
connection of the same account into it), sends `connection.created` and
starts the first sync. A `capture` sent before the provider session is
usable (no `accessToken` yet) returns `waiting`; retry every few seconds.

No API key: the link's token authenticates `start`, and the capture
credential authenticates `capture`. The app and user come from the
link, never from the request.




## OpenAPI

````yaml POST /api/connect-native
openapi: 3.1.0
info:
  title: Verso Fetch API
  version: '2026-09-30'
  description: >
    Read your users' connections and conversations, ingest exports, and delete
    data.


    Every request needs `Authorization: Bearer <API key>`. API keys start with
    `vsk_`

    and are issued at onboarding; several can be active at once so rotation is

    zero-downtime. Using the app secret as a Bearer token still works but is

    deprecated: the app secret is for signing links only.


    The `GET` endpoints are rate limited to 60 requests per minute per app and

    return `RateLimit-*` headers. Errors are JSON objects with a single `error`
    string.
  contact:
    name: Verso
    email: hello@tryverso.ai
servers:
  - url: https://connect.tryverso.ai
    description: Production
security:
  - apiKey: []
tags:
  - name: Connections
    description: Per-user connection status and recent activity.
  - name: Conversations
    description: Normalized conversations of a connection.
  - name: Import
    description: Server-side ingestion of a provider export.
  - name: Deletion
    description: GDPR deletion of a user's or a connection's data.
  - name: Native connect
    description: >-
      What the mobile SDKs call to connect from inside an app. Not needed when
      you use an SDK.
paths:
  /api/connect-native:
    post:
      tags:
        - Native connect
      summary: Native connect (mobile SDKs)
      description: >
        The two calls the mobile SDKs make to connect an account from inside an

        app. With an SDK you never call this endpoint yourself; it is documented

        for teams building on a platform without an SDK yet.


        `start` verifies and consumes a connect link, creates the user record if

        needed, sends `connect.started`, and returns where to log in and which

        cookie to watch, plus a one-time capture credential (`captureNonce` and

        `clientSecret`, valid one hour).


        `capture` hands the provider session read from the app's WebView to

        Verso, which encrypts it, creates the connection (folding a previous

        connection of the same account into it), sends `connection.created` and

        starts the first sync. A `capture` sent before the provider session is

        usable (no `accessToken` yet) returns `waiting`; retry every few
        seconds.


        No API key: the link's token authenticates `start`, and the capture

        credential authenticates `capture`. The app and user come from the

        link, never from the request.
      operationId: connectNative
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - $ref: '#/components/schemas/NativeStartRequest'
                - $ref: '#/components/schemas/NativeCaptureRequest'
            examples:
              start:
                summary: Start
                value:
                  action: start
                  token: eyJhbGciOiJIUzI1NiJ9…
                  device:
                    platform: ios
                    osVersion: '17.5'
                    sdkVersion: 0.1.0
                    model: iPhone15,2
                    appVersion: 3.2.0
              capture:
                summary: Capture
                value:
                  action: capture
                  captureNonce: b139982c-1f4e-4e0a-9d33-5f0c2a1e7b21
                  clientSecret: 89e98bb0…
                  sessionToken: eyJhbGciOiJkaXIi…
                  accessToken: eyJhbGciOiJSUzI1NiI…
                  providerAccountId: user-Bkfd…
                  providerAccountEmail: jane@example.com
      responses:
        '200':
          description: The start data, or the capture outcome (`connected` or `waiting`).
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/NativeStartResponse'
                  - $ref: '#/components/schemas/NativeCaptureResponse'
        '400':
          description: >-
            `Missing token`, `Malformed token`, `Token purpose must be
            'connect'`, `Missing captureNonce`, `Missing clientSecret`, `Missing
            sessionToken`, `Invalid JSON body` or `Unknown action`
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: '`Invalid token: …`: expired link or bad signature.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: >-
            `This link has already been used`, or `Invalid or expired capture
            nonce` (unknown, consumed or older than one hour, or a
            `clientSecret` that does not match).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: >-
            `This ChatGPT account is already connected to another user of this
            app. Request a new link to connect a different account.` The capture
            credential is spent.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security: []
components:
  schemas:
    NativeStartRequest:
      type: object
      required:
        - action
        - token
      properties:
        action:
          type: string
          enum:
            - start
        token:
          type: string
          description: >-
            The `token` of a connect link signed with `signLink()` (`purpose:
            "connect"`).
        device:
          type: object
          description: >-
            What the SDK reports about the device. Stored with the connection
            for support; each value is truncated to 80 characters.
          properties:
            platform:
              type: string
              example: ios
            osVersion:
              type: string
              example: '17.5'
            sdkVersion:
              type: string
              example: 0.1.0
            model:
              type: string
              example: iPhone15,2
            appVersion:
              type: string
              example: 3.2.0
    NativeCaptureRequest:
      type: object
      required:
        - action
        - captureNonce
        - clientSecret
        - sessionToken
      properties:
        action:
          type: string
          enum:
            - capture
        captureNonce:
          type: string
          format: uuid
        clientSecret:
          type: string
        sessionToken:
          type: string
          description: The value of the session cookie (chunks concatenated).
        accessToken:
          type: string
          description: >-
            `accessToken` from `sessionUrl`. Absent while the login is not
            complete: Verso answers `waiting`.
        providerAccountId:
          type: string
          description: >-
            `user.id` from `sessionUrl`. Enables the one-account-one-user rule
            and reconnect merging.
        providerAccountEmail:
          type: string
          description: >-
            `user.email` from `sessionUrl`. Hashed on receipt, never stored in
            clear.
    NativeStartResponse:
      type: object
      required:
        - captureNonce
        - clientSecret
        - provider
        - loginUrl
        - cookieDomain
        - cookieName
        - sessionUrl
        - expiresInSeconds
      properties:
        captureNonce:
          type: string
          format: uuid
          description: Identifies this connect attempt in `capture`.
        clientSecret:
          type: string
          description: >-
            Returned once. Proves in `capture` that the caller is the SDK
            instance that started the flow.
        provider:
          type: string
          example: chatgpt
        loginUrl:
          type: string
          format: uri
          description: Where to send the WebView.
          example: https://chatgpt.com/auth/login
        cookieDomain:
          type: string
          example: chatgpt.com
        cookieName:
          type: string
          description: >-
            The session cookie to watch. The provider may split it into
            `<cookieName>.0`, `<cookieName>.1`, … chunks; concatenate them in
            order.
          example: __Secure-next-auth.session-token
        sessionUrl:
          type: string
          format: uri
          description: >-
            Fetched from inside the WebView once the cookie is present; its JSON
            carries `accessToken`, `user.id` and `user.email`.
          example: https://chatgpt.com/api/auth/session
        expiresInSeconds:
          type: integer
          description: Lifetime of the capture credential.
          example: 3600
    NativeCaptureResponse:
      oneOf:
        - type: object
          required:
            - status
            - connectionId
          properties:
            status:
              type: string
              enum:
                - connected
            connectionId:
              type: string
              format: uuid
        - type: object
          required:
            - status
          properties:
            status:
              type: string
              enum:
                - waiting
            reason:
              type: string
              example: ChatGPT session not ready
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          description: Human-readable message. Stable strings, safe to match on.
          example: Connection not found
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: |
        Your API key (`vsk_…`), issued at onboarding. Keep it server-side.

````