Klaviyo · Authentication Profile

Klaviyo Authentication

Authentication

Klaviyo secures its APIs with apiKey and oauth2 across 4 declared security schemes, as derived from its OpenAPI definitions. OAuth 2.0 is offered via the authorizationCode flow(s).

MarketingEmailSMSCustomer DataE-CommerceAutomation
Methods: apiKey, oauth2 Schemes: 4 OAuth flows: authorizationCode API key in: header, query

Security Schemes

Klaviyo-API-Key apiKey
· in: header (Authorization)
PublicKeyCompanyId apiKey
· in: query (company_id)
KlaviyoOAuth2 oauth2
· flows: authorizationCode
KlaviyoMCPOAuth oauth2
· flows: authorizationCode

Source

Authentication Profile

Raw ↑
generated: '2026-08-13'
method: searched
source: https://developers.klaviyo.com/en/docs/authenticate_
docs:
  - https://developers.klaviyo.com/en/docs/authenticate_
  - https://developers.klaviyo.com/en/docs/set_up_oauth
  - https://developers.klaviyo.com/en/docs/create_a_public_oauth_app
derived_from: openapi/*.yml (23 files, revision 2026-04-15)
supersedes: >-
  The 2026-07-11 derived version, which recorded only the apiKey scheme because that is
  all Klaviyo declares in its OpenAPI. Klaviyo also ships a full OAuth 2.0 + PKCE model
  and a public-key client-side model, neither of which appears in the spec's
  securitySchemes — both are added here from the docs.

summary:
  types: [apiKey, oauth2]
  api_key_in: [header, query]
  oauth2_flows: [authorizationCode]
  pkce_required: true
  audiences: [server-side (private key), client-side (public key), third-party integrations (OAuth)]

schemes:
  - name: Klaviyo-API-Key
    type: apiKey
    in: header
    parameter: Authorization
    format: 'Klaviyo-API-Key <private-api-key>'
    key_prefix: pk_
    audience: server-side
    description: >-
      Private key authentication for /api/ endpoints. The Authorization header is set to
      `Klaviyo-API-Key your-private-api-key`. Keys carry per-resource read/write
      permissions selected at creation time, using the same <resource>:<read|write>
      vocabulary as OAuth scopes.
    declared_in_openapi: true
    sources:
      - openapi/klaviyo-accounts-api-openapi.yml
      - openapi/klaviyo-profiles-api-openapi.yml
      - (and every other document in openapi/)

  - name: PublicKeyCompanyId
    type: apiKey
    in: query
    parameter: company_id
    format: 6-character alphanumeric public API key / company ID
    audience: client-side / browser
    description: >-
      Public key authentication for the /client/ endpoint family and the onsite
      JavaScript loader. Safe to expose in client-side code — it cannot read account
      data, only write events and profile identifications. Used by
      create_client_event, create_client_profile, bulk_create_client_events and by
      https://static.klaviyo.com/onsite/js/klaviyo.js.
    declared_in_openapi: false
    declared_in_openapi_note: >-
      The /client/ operations exist in the OpenAPI but the public-key scheme is not
      declared as a securityScheme; the spec carries a single global
      `security: [{Klaviyo-API-Key: []}]`.

  - name: KlaviyoOAuth2
    type: oauth2
    audience: third-party integrations and marketplace apps
    description: >-
      OAuth 2.0 Authorization Code grant with mandatory PKCE. Required for any app
      listed in the Klaviyo App Marketplace. Delegated access — the token is scoped to
      what the installing account granted.
    declared_in_openapi: false
    declared_in_openapi_note: >-
      Klaviyo does NOT declare an oauth2 securityScheme in its published OpenAPI, which
      is why derive-oauth-scopes.py reports zero oauth2 providers for this repo. The
      scope vocabulary IS published in the spec, but as an `x-klaviyo-scopes` vendor
      extension on each operation rather than in securitySchemes.
    flows:
      - flow: authorizationCode
        authorizationUrl: https://www.klaviyo.com/oauth/authorize
        tokenUrl: https://a.klaviyo.com/oauth/token
        revocationUrl: https://a.klaviyo.com/oauth/revoke
        refreshUrl: https://a.klaviyo.com/oauth/token
        pkce_required: true
        code_challenge_method: S256
        code_verifier: 43-128 characters, letters/digits/underscore/period/hyphen/tilde
        code_challenge: SHA-256 of the verifier, base64url encoded
        pkce_note: >-
          A new code_challenge/code_verifier pair is required for EVERY authorization
          request. Klaviyo requires PKCE for both public and confidential client types,
          not just public ones.
        scope_count: 46
        scopes_artifact: scopes/klaviyo-scopes.yml
    token_lifetimes:
      authorization_code: 5 minutes
      access_token: 1 hour (rely on the returned expires_in rather than hard-coding)
      refresh_token: valid until the app is uninstalled; revoked if unused for 90 days

  - name: KlaviyoMCPOAuth
    type: oauth2
    audience: MCP clients calling the hosted server
    description: >-
      The hosted MCP server at https://mcp.klaviyo.com/mcp runs its OWN authorization
      server, separate from the integration OAuth above. It supports RFC 7591 dynamic
      client registration, which is what lets an MCP client connect without a
      pre-registered app.
    declared_in_openapi: false
    discovery:
      authorization_server_metadata: well-known/klaviyo-mcp-oauth-authorization-server.json
      protected_resource_metadata: well-known/klaviyo-mcp-oauth-protected-resource.json
    flows:
      - flow: authorizationCode
        issuer: https://mcp.klaviyo.com
        authorizationUrl: https://mcp.klaviyo.com/authorize
        tokenUrl: https://mcp.klaviyo.com/token
        registrationUrl: https://mcp.klaviyo.com/register
        revocationUrl: https://mcp.klaviyo.com/token
        code_challenge_methods: [S256, plain]
        dynamic_client_registration: true
    note: >-
      The LOCAL stdio MCP server uses a different model entirely — a private API key in
      the PRIVATE_API_KEY environment variable. Remote = OAuth, local = API key. See
      mcp/klaviyo-mcp.yml.

oidc:
  discovery_document: well-known/klaviyo-openid-configuration.json
  issuer: https://a.klaviyo.com
  jwks_uri: https://auth.services.klaviyo.com/oauth/v2/keys
  userinfo_endpoint: https://auth.services.klaviyo.com/oidc/v1/userinfo
  introspection_endpoint: https://auth.services.klaviyo.com/oauth/v2/introspect
  scopes_supported: [openid, profile, email, phone]
  note: >-
    https://a.klaviyo.com/.well-known/openid-configuration returns 200. Its
    authorization_endpoint is /staff/mcp/oauth/authorize, indicating this issuer serves
    Klaviyo's internal/staff identity surface rather than the public integration OAuth
    flow. Recorded because it is a real, anonymously readable discovery document, not
    because it is the endpoint a partner integration should use — for that, use the
    KlaviyoOAuth2 scheme above.

required_headers:
  - name: revision
    required: true
    format: ISO 8601 date, e.g. 2026-07-15
    note: Required on every request alongside authentication. See lifecycle/klaviyo-lifecycle.yml.

x-evidence:
  - {fetched: '2026-08-13', url: 'https://developers.klaviyo.com/en/docs/authenticate_', http_status: 200}
  - {fetched: '2026-08-13', url: 'https://developers.klaviyo.com/en/docs/set_up_oauth', http_status: 200}
  - {fetched: '2026-08-13', url: 'https://a.klaviyo.com/.well-known/openid-configuration', http_status: 200}
  - {fetched: '2026-08-13', url: 'https://mcp.klaviyo.com/.well-known/oauth-authorization-server', http_status: 200}