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

# Connect an adapter key to a partner

> Gives an adapter the key it needs to act through a service the partner has an account with, for the widgets of
the customers the partner manages. Take the `adapterId` and `credentialKey` from
`getPartnerAdapterConnections`. Saving a key that is already connected replaces it.

**What Widgetic does with it.** The key is stored encrypted, bound to this partner, this adapter and this
credential, so that a stored value cannot be moved to another. It is never returned, never logged and never
shown to a visitor of a widget or to your customers. A server of Widgetic opens it for the one call a widget
makes through the adapter, uses it to call the provider on the partner's behalf, and discards it. To cut that
off, remove the key here, or revoke it with the provider.

**What is checked.** That the adapter exists and takes this credential, that a partner may keep it (some are
for an owner only) and that the text is one line of at most 2048 characters. Whether the provider accepts the
key is not checked here: it shows the first time a widget uses it.

**An address that has to be confirmed.** Some credentials are not a key but the email address Widgetic sends a
widget's messages to (`confirmation: email_code` in `getPartnerAdapterConnections`). Saving one checks that it is
one email address and emails a six-digit code to it; the answer says `awaitingConfirmation: true`, and nothing is
sent to the address until the code is given back with `confirmPartnerAdapterConnection`. Saving the same address
again before it is confirmed emails a new code (not sooner than a minute after the last); saving the address that
is already confirmed changes nothing. If the code cannot be emailed, nothing is saved.

A widget whose adapter has no key connected, or whose address is not confirmed yet, is not charged and does not
run that adapter: its visitors are told the feature is unavailable, and the partner is told once a day what to do.

This needs an API key with full access. The caller must be the person who administers the partner, or a
Widgetic administrator. A retry is harmless: saving the same key twice only refreshes when it was set.




## OpenAPI

````yaml /openapi/widgetic-api-public.json put /partners/{partnerId}/adapter-connections/{adapterId}/{credentialKey}
openapi: 3.0.0
info:
  title: Widgetic API Gateway
  version: 1.0.0
  description: API documentation for the Widgetic API Gateway
  license:
    name: Widgetic Integration License
    url: https://docs.widgetic.com/resources/license
servers:
  - url: https://api.widgetic.com/v1
    description: Production server
    variables:
      env:
        default: production
        description: Environment
      apiUrl:
        default: https://api.widgetic.com
        description: API URL
      apiVersion:
        default: /v1
        description: API Version path prefix
security: []
tags: []
paths:
  /partners/{partnerId}/adapter-connections/{adapterId}/{credentialKey}:
    put:
      tags:
        - Partners
      summary: Connect an adapter key to a partner
      description: >
        Gives an adapter the key it needs to act through a service the partner
        has an account with, for the widgets of

        the customers the partner manages. Take the `adapterId` and
        `credentialKey` from

        `getPartnerAdapterConnections`. Saving a key that is already connected
        replaces it.


        **What Widgetic does with it.** The key is stored encrypted, bound to
        this partner, this adapter and this

        credential, so that a stored value cannot be moved to another. It is
        never returned, never logged and never

        shown to a visitor of a widget or to your customers. A server of
        Widgetic opens it for the one call a widget

        makes through the adapter, uses it to call the provider on the partner's
        behalf, and discards it. To cut that

        off, remove the key here, or revoke it with the provider.


        **What is checked.** That the adapter exists and takes this credential,
        that a partner may keep it (some are

        for an owner only) and that the text is one line of at most 2048
        characters. Whether the provider accepts the

        key is not checked here: it shows the first time a widget uses it.


        **An address that has to be confirmed.** Some credentials are not a key
        but the email address Widgetic sends a

        widget's messages to (`confirmation: email_code` in
        `getPartnerAdapterConnections`). Saving one checks that it is

        one email address and emails a six-digit code to it; the answer says
        `awaitingConfirmation: true`, and nothing is

        sent to the address until the code is given back with
        `confirmPartnerAdapterConnection`. Saving the same address

        again before it is confirmed emails a new code (not sooner than a minute
        after the last); saving the address that

        is already confirmed changes nothing. If the code cannot be emailed,
        nothing is saved.


        A widget whose adapter has no key connected, or whose address is not
        confirmed yet, is not charged and does not

        run that adapter: its visitors are told the feature is unavailable, and
        the partner is told once a day what to do.


        This needs an API key with full access. The caller must be the person
        who administers the partner, or a

        Widgetic administrator. A retry is harmless: saving the same key twice
        only refreshes when it was set.
      operationId: setPartnerAdapterConnection
      parameters:
        - in: path
          name: partnerId
          required: true
          schema:
            type: string
            format: uuid
          description: The partner that keeps the key
        - in: path
          name: adapterId
          required: true
          schema:
            type: string
            maxLength: 40
          description: The adapter the key is for
        - in: path
          name: credentialKey
          required: true
          schema:
            type: string
            maxLength: 40
          description: The key's name within the adapter
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SetAdapterConnectionRequest'
      responses:
        '200':
          description: The key was saved
          content:
            application/json:
              schema:
                title: AdapterConnectionResponse
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/AdapterConnection'
                  meta:
                    $ref: '#/components/schemas/ResponseMeta'
                required:
                  - success
                  - data
        '400':
          description: >-
            A path value or the body is malformed. The body takes exactly one
            field, `credential`
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: The API key is missing or invalid
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: >-
            The caller does not administer this partner, or the API key has not
            full access
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: >-
            There is no such adapter, the adapter has no such credential, a
            partner may not keep it, or the partner does not exist
            (ADAPTER_NOT_FOUND, CREDENTIAL_NOT_FOUND,
            CREDENTIAL_NOT_FOR_THIS_ACCOUNT, HOLDER_NOT_FOUND)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: >-
            The credential is not one line of text of at most 2048 characters
            (CREDENTIAL_VALUE_INVALID), is not one email address where one is
            needed (CREDENTIAL_ADDRESS_INVALID), or the email provider refused
            the address a code was to be emailed to
            (CONFIRMATION_ADDRESS_REFUSED). Nothing was saved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: >-
            Too many changes in a short time (try again after the Retry-After
            seconds), or too many codes were emailed to that address or for that
            account (CONFIRMATION_TOO_SOON, CONFIRMATION_LIMIT_REACHED)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: >-
            Adapter keys cannot be saved on this server right now
            (ADAPTER_CONNECTIONS_UNAVAILABLE), or the code could not be emailed
            (CONFIRMATION_NOT_SENT). Nothing was changed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - apiKeyAuth: []
      x-code-samples:
        - lang: TypeScript
          label: TypeScript SDK
          source: >
            import { Configuration, PartnersApi } from '@widgetic/api-sdk-ts';


            const partnersApi = new PartnersApi(new Configuration({ apiKey:
            'YOUR_API_KEY' }));


            const { data: connection } = await
            partnersApi.setPartnerAdapterConnection({
              partnerId,
              adapterId: 'email',
              credentialKey: 'resendApiKey',
              setAdapterConnectionRequest: { credential: 'YOUR_PROVIDER_KEY' },
            });

            console.log(connection.connected, connection.updatedAt);


            // An address a widget's messages are emailed to: a code is emailed
            to it, and it is used once the code is given back.

            const { data: address } = await
            partnersApi.setPartnerAdapterConnection({
              partnerId,
              adapterId: 'email',
              credentialKey: 'recipient',
              setAdapterConnectionRequest: { credential: 'owner@example.com' },
            });

            console.log(address.awaitingConfirmation);
components:
  schemas:
    SetAdapterConnectionRequest:
      type: object
      required:
        - credential
      additionalProperties: false
      properties:
        credential:
          type: string
          format: password
          writeOnly: true
          maxLength: 2048
          description: >-
            The key exactly as its provider gave it: one line of text, at most
            2048 characters. It is stored encrypted and is never returned or
            logged. For a credential that is an email address (`confirmation:
            email_code`), write that one address, with nothing else
          example: YOUR_PROVIDER_KEY
      example:
        credential: YOUR_PROVIDER_KEY
    AdapterConnection:
      type: object
      description: >-
        A key an adapter can take from an account, and whether the account has
        connected it. The key itself is never part of this: it is given once,
        when it is connected, and Widgetic keeps it encrypted.
      required:
        - adapterId
        - adapterLabel
        - credentialKey
        - label
        - scope
        - connected
        - updatedAt
        - confirmation
        - awaitingConfirmation
        - confirmedAt
      properties:
        adapterId:
          type: string
          description: The adapter the key is for (its id in the adapter catalog)
          example: email
        adapterLabel:
          type: string
          description: What the adapter is called to its owner
          example: Email
        credentialKey:
          type: string
          description: >-
            The name of the key within the adapter. Use it, with the adapter id,
            to connect or remove the key
          example: resendApiKey
        label:
          type: string
          description: What the key is called to its owner
          example: Resend API key
        scope:
          type: string
          enum:
            - owner
            - partner
            - owner_or_partner
          description: >-
            Who may keep this key. `owner` is the person who made the widget, in
            their own account. `partner` is a partner, for the widgets of the
            customers it manages. `owner_or_partner` is either; for a widget of
            a managed customer the partner's key is used.
        connected:
          type: boolean
          description: Whether this account has connected the key
        updatedAt:
          type: string
          format: date-time
          nullable: true
          description: When the key was last set. Null when it is not connected
        confirmation:
          type: string
          nullable: true
          description: >-
            How this credential is proved before it is used. `email_code` means
            it is an email address: saving it emails a code to it, and it is
            used only after the code is given back
            (`confirmUserAdapterConnection`, `confirmPartnerAdapterConnection`).
            Null for a credential that is used as soon as it is saved
          example: email_code
        awaitingConfirmation:
          type: boolean
          description: >-
            True when the credential is connected but has not been confirmed
            yet, so no adapter uses it. Always false when `confirmation` is null
            or the credential is not connected
        confirmedAt:
          type: string
          format: date-time
          nullable: true
          description: >-
            When the credential was confirmed. Null when it is not connected, is
            awaiting its code, or needs no confirmation
      example:
        adapterId: email
        adapterLabel: Email
        credentialKey: resendApiKey
        label: Resend API key
        scope: Example scope
        connected: true
        updatedAt: '2026-01-15T09:30:00.000Z'
        confirmation: email_code
        awaitingConfirmation: true
        confirmedAt: '2026-01-15T09:30:00.000Z'
    ResponseMeta:
      type: object
      description: >-
        Extra information about the answer: where a page sits in a list, the
        cursor of the next page, or warnings about a call that succeeded with a
        caveat.
      additionalProperties: true
      properties:
        page:
          type: integer
          description: The page that was read, counting from 1.
          example: 1
        size:
          type: integer
          description: How many items one page holds.
          example: 20
        total:
          type: integer
          description: How many items the whole list has.
          example: 135
        limit:
          type: integer
          description: The same as `size`.
          example: 20
        offset:
          type: integer
          description: How many items come before this page.
          example: 0
        hasNextPage:
          type: boolean
          example: true
        hasPreviousPage:
          type: boolean
          example: false
        nextCursor:
          type: string
          nullable: true
          description: >-
            Pass this as `cursor` to read the next page of a list that is read
            by cursor. `null` on the last page.
        warnings:
          type: array
          items:
            type: string
          description: >-
            Things the call did not do, though it succeeded (for example a table
            that could not be created just now).
    ErrorResponse:
      type: object
      required:
        - success
        - message
        - error
      additionalProperties: true
      properties:
        success:
          type: boolean
          description: Always `false` on a failure.
          example: false
        message:
          type: string
          description: The same text as `error.message`, for a caller that reads one line.
        error:
          $ref: '#/components/schemas/ErrorDetail'
    ErrorDetail:
      type: object
      required:
        - code
        - message
        - timestamp
      properties:
        code:
          type: string
          description: Machine-readable error code.
          example: RESOURCE_NOT_FOUND
        message:
          type: string
          description: Human-readable explanation.
          example: Composition not found
        param:
          type: string
          description: The field that caused the error, when one did.
          example: name
        docUrl:
          type: string
          description: Where this error is explained.
        suggestedAction:
          type: string
          description: What to do about it.
        retryAfter:
          type: integer
          description: >-
            Seconds to wait before trying again (rate limits). The same number
            is in the `Retry-After` header.
          example: 60
        details:
          type: object
          additionalProperties: true
          description: >-
            More about the error: the fields that failed, a limit that was
            reached.
        correlationId:
          type: string
          description: Quote this when you ask support about the call.
          example: req_123e4567-e89b-12d3-a456-426614174000
        timestamp:
          type: string
          format: date-time
          example: '2026-10-15T10:00:00.000Z'
  securitySchemes:
    apiKeyAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

````

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