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

# Create an OAuth provider credential

> Creates a `system.credential` of `kind: oauth_token` carrying an upstream service's OAuth client config — authorize URL, token URL, client_id, encrypted client_secret, upstream API base URL, and optional default scope. The resulting credential id is passed as `credential_ref` on subsequent `POST /connections/install` calls so multiple integrations of the same upstream (e.g. `google.calendar` + `google.tasks`) share one OAuth client and one stored secret instead of duplicating per-integration.

The client_secret is encrypted server-side under the `connectionOauthToken` HKDF domain (AES-256-GCM). Decryption only happens at the OAuth proxy + callback paths; the plaintext is never returned by any read path.

Tenant-scoped: the credential is created in the calling key's tenant, and integrations within that tenant can reference it. Cross-tenant reuse is not supported — each tenant brings its own OAuth provider config.



## OpenAPI

````yaml /openapi.json post /credentials/oauth-provider
openapi: 3.1.0
info:
  title: Marfa API
  version: 4.2.0
  description: Typed data layer for structured personal data
servers: []
security: []
paths:
  /credentials/oauth-provider:
    post:
      tags:
        - Credentials
      summary: Create an OAuth provider credential
      description: >-
        Creates a `system.credential` of `kind: oauth_token` carrying an
        upstream service's OAuth client config — authorize URL, token URL,
        client_id, encrypted client_secret, upstream API base URL, and optional
        default scope. The resulting credential id is passed as `credential_ref`
        on subsequent `POST /connections/install` calls so multiple integrations
        of the same upstream (e.g. `google.calendar` + `google.tasks`) share one
        OAuth client and one stored secret instead of duplicating
        per-integration.


        The client_secret is encrypted server-side under the
        `connectionOauthToken` HKDF domain (AES-256-GCM). Decryption only
        happens at the OAuth proxy + callback paths; the plaintext is never
        returned by any read path.


        Tenant-scoped: the credential is created in the calling key's tenant,
        and integrations within that tenant can reference it. Cross-tenant reuse
        is not supported — each tenant brings its own OAuth provider config.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                label:
                  type: string
                  minLength: 1
                  maxLength: 200
                oauth_authorize_url:
                  type: string
                  maxLength: 2048
                  format: uri
                oauth_token_url:
                  type: string
                  maxLength: 2048
                  format: uri
                oauth_client_id:
                  type: string
                  minLength: 1
                  maxLength: 512
                oauth_client_secret:
                  type: string
                  minLength: 1
                  maxLength: 2048
                upstream_base_url:
                  type: string
                  maxLength: 2048
                  format: uri
                oauth_default_scope:
                  type: string
                  maxLength: 2048
              required:
                - label
                - oauth_authorize_url
                - oauth_token_url
                - oauth_client_id
                - oauth_client_secret
                - upstream_base_url
      responses:
        '201':
          description: >-
            Credential created. Returns the new credential's id for use as
            `credential_ref` on install.
          content:
            application/json:
              schema:
                type: object
                properties:
                  credential_id:
                    type: string
                required:
                  - credential_id
        '400':
          description: Invalid request body.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        enum:
                          - validation_error
                          - missing_required_field
                      message:
                        type: string
                      details:
                        type: object
                        additionalProperties:
                          nullable: true
                    required:
                      - code
                      - message
                required:
                  - error
        '401':
          description: Authentication required.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        enum:
                          - unauthorized
                      message:
                        type: string
                      details:
                        type: object
                        additionalProperties:
                          nullable: true
                    required:
                      - code
                      - message
                required:
                  - error
        '403':
          description: Caller is not an admin or tenant_admin.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        enum:
                          - forbidden
                      message:
                        type: string
                      details:
                        type: object
                        additionalProperties:
                          nullable: true
                    required:
                      - code
                      - message
                required:
                  - error
      security:
        - bearerAuth: []
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key or OAuth Token
      description: Pass an API key (marfa_k1_...) or OAuth access token (marfa_at_...)

````