Create a connection

POST /v1/connections · permission connections:write

Registers a new connection in the environment. Connections that need protocol configuration (social, enterprise) start inactive; activate them explicitly with :activate. An enterprise connection cannot be created active: a new connection cannot have a successful test sign-in yet. Settings must not contain secrets. An environment can hold at most 100 connections and 20 generic social (oidc_generic, oauth2_generic) connections, and an organization at most 20 connections.

Request

JSON body (unknown fields are rejected with 400 unknown_field):

Field Type Required Description
key string yes Stable configuration key, ^[a-z0-9_-]{1,64}$, unique in the environment, immutable.
type string yes database, passwordless, passkey, social or enterprise. Immutable.
strategy string yes Strategy for the type, for example password, email_otp, google, saml. Immutable.
name string yes 1-128 characters, unique in the environment.
display_name string no 1-128 characters shown on sign-in screens.
status string no active or inactive. Defaults to active for database, passwordless, passkey and to inactive for social, enterprise.
org_id string no Owner organization (org_…), enterprise only. Omitted: an environment connection. Immutable.
allowed_email_domains array of strings no E-mail domains routed to this connection by home realm discovery: IDNA A-label, lower case (for example xn--bcher-kva.example), unique, at most 100; non-empty only for enterprise. On an organization connection every domain must be a verified domain of the organization, and an active organization connection needs at least one.
allow_external_domains boolean no Also sign in users whose e-mail domain is not listed. enterprise only; default false.
jit_mode string no Just-in-time provisioning: create creates the user at first sign-in, create_and_update also updates the profile from the identity provider, off requires an existing account. enterprise only. Defaults to create_and_update for an environment connection. On an organization connection the mode follows the default when omitted: create_and_update while the organization has no active SCIM directory, off while it has one (or when the directory state cannot be read); the value is derived on every read, and a mode you set explicitly is not affected.
email_trust boolean no Trust the e-mail address the identity provider asserts for automatic account linking and just-in-time provisioning. enterprise only; default false. On an organization connection true needs a non-empty allowed_email_domains in which every domain is a verified domain of the organization.
default_role_ids array of strings no Environment roles (rol_…, unique, at most 10) granted to the membership a just-in-time sign-in creates, in addition to the environment's default role and the connection's group role mappings. Only on an organization enterprise connection. Every role must be a non-privileged environment role of this environment; another environment's role, an organization role, a privileged role or a missing role is rejected. A role deleted or made privileged later is skipped at sign-in.
trust_idp_mfa boolean no Accept the multi-factor authentication the identity provider asserts (SAML authentication context, OIDC amr/acr) as the session's MFA proof. enterprise only; default false.
settings object no Settings without secrets, up to 32 KiB. Keys or values that look like secrets are rejected.
Idempotency-Key header no Optional key (16-64 characters) that makes a retried request safe.

Response

201 Created with the connection and an ETag header holding its version.

{
  "id": "conn_0k3v8m1q2x9dz4h7s5t6w0y1ab",
  "key": "google",
  "type": "social",
  "strategy": "google",
  "name": "Google",
  "display_name": "Sign in with Google",
  "status": "inactive",
  "org_id": null,
  "allowed_email_domains": [],
  "allow_external_domains": false,
  "jit_mode": null,
  "email_trust": null,
  "default_role_ids": [],
  "trust_idp_mfa": null,
  "allow_idp_initiated": null,
  "idp_initiated_default_application_id": null,
  "idp_initiated_allowed_application_ids": [],
  "settings": {},
  "created_at": "2026-10-05T09:30:00.123456Z",
  "updated_at": "2026-10-05T09:30:00.123456Z"
}

Passkey settings

For type: "passkey" the settings object accepts only the keys below. Any other key, a wrong type or an out-of-range value is rejected with 422 validation_failed and an errors[].pointer such as /settings/max_credentials_per_user. A null value means the default. Shape errors are reported before plan errors.

Key Type Notes
rp_id string Absent, null or empty: each sign-in host is its own rpId. Otherwise the host name of an active custom domain of the environment (lower-case, IDNA A-label); any other value is 422 validation_failed (/settings/rp_id). Once the environment has passkeys, change it with Change the passkey rpId.
rp_name string Up to 128 characters.
passkey_first_factor_enabled, security_key_second_factor_enabled boolean Default true.
user_verification string preferred (default) or required.
max_credentials_per_user integer 1-20, default 20; fractions are rejected.
require_device_bound_passkeys boolean Plan-gated: true needs Startup.
attestation_required boolean Plan-gated: true needs Enterprise.
aaguid_allowlist, aaguid_blocklist array of UUID strings At most 500 unique entries each (errors point at /settings/<key>/<index>). Plan-gated: a non-empty list needs Enterprise.
related_origins array of strings https://host[:port] origins. Plan-gated: a non-empty list needs Enterprise.
passkey_enrollment_prompt string off or after_login (default).

Writing a non-default value of a plan-gated key fails with 403 plan_feature_unavailable and the members feature and required_plan. Until plan entitlements are available, these keys cannot be set in any environment; writing a default value (false, [], null) or removing the key is always allowed. When the feature is available, every related_origins entry must be an active verified custom domain of the environment, otherwise the request fails with 422 related_origin_not_verified.

Errors

HTTP code When
400 unknown_field The body contains an unknown field.
403 quota_exceeded A connection limit of the environment or of the organization (org_id) is reached.
409 conflict A connection with the same key or name exists.
409 connection_test_required The request creates an enterprise connection with status: active; nothing is written. Create it inactive, test its sign-in, then activate it with :activate.
415 unsupported_media_type The content type is not application/json.
422 validation_failed A field is missing or invalid; errors[].pointer names it (for example /settings/client_secret for secret-like settings).
422 related_origin_not_verified A related origin is not a verified custom domain of the environment.
403 plan_feature_unavailable The plan does not include a setting you set (feature, required_plan members), for example attestation_required.
401 unauthenticated The credential is missing, invalid or revoked.
403 insufficient_permissions The credential lacks the required permission.
429 rate_limited The rate limit was exceeded; retry after the Retry-After period.
503 service_unavailable A dependency is temporarily unavailable; retry after the Retry-After period.

Example

curl -X POST https://api.eu.keenauth.com/v1/connections \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"key":"google","type":"social","strategy":"google","name":"Google"}'