IdP Configuration API Reference¶
Complete API reference for Partner Identity Provider (IdP) configuration endpoints. These endpoints allow partners to configure OIDC-based single sign-on for their users.
API Overview¶
The IdP Configuration API is part of the Partner Admin API and requires API key authentication. Each partner app can have one IdP configuration for OIDC-based SSO.
Base URL¶
| Environment | Base URL |
|---|---|
| Production | https://api.contio.ai |
| Beta | https://beta.api.contio.ai |
Authentication¶
All IdP configuration endpoints require authentication using your Partner API Key and Client ID:
| Header | Description |
|---|---|
X-API-Key | Your partner app's API key |
X-Client-ID | Your partner app's client ID |
const headers = {
'X-API-Key': process.env.CONTIO_API_KEY,
'X-Client-ID': process.env.CONTIO_CLIENT_ID,
'Content-Type': 'application/json'
};
Rate Limits¶
Admin API endpoints are rate-limited to 500 requests per 5 minutes (approximately 100 requests per minute). When you exceed the rate limit, the API returns a 429 Too Many Requests response.
Endpoints¶
Create IdP Configuration¶
Creates a new OIDC identity provider configuration for the authenticated partner app.
Endpoint: POST /v1/partner/admin/idp
Request Body:
{
"name": "Acme Corporate SSO",
"discovery_url": "https://login.acme.com/.well-known/openid-configuration",
"idp_client_id": "contio-integration-prod",
"idp_client_secret": "secret-from-idp-admin-console",
"scopes": ["openid", "email", "profile"],
"claim_mappings": {
"email": "email",
"name": "name"
},
"mode": "strict",
"allowed_email_domains": ["acme.com", "acme.co.uk"]
}
Request Fields:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Display name for the IdP configuration (1-255 characters) |
discovery_url | string | Yes | OIDC discovery endpoint URL (must be HTTPS) |
idp_client_id | string | Yes | OAuth Client ID from your Identity Provider. Not your Contio Partner client_id. |
idp_client_secret | string | Yes | OAuth Client Secret from your Identity Provider. Not your Contio Partner client_secret. Encrypted at rest. |
scopes | string[] | No | OIDC scopes to request. Default: ["openid", "email", "profile"] |
claim_mappings | object | No | Map IdP claims to Contio fields. Default: {"email": "email", "name": "name"} |
mode | string | Yes | Domain validation mode: strict or partner_managed |
allowed_email_domains | string[] | Conditional | Required if mode=strict; optional if mode=partner_managed |
OAuth Connection Required
Users must establish a connection to your partner app via OAuth before they can use SSO. SSO provides authentication convenience, not user provisioning.
Response (201 Created):
{
"id": "01234567-89ab-cdef-0123-456789abcdef",
"partner_app_id": "98765432-10ab-cdef-0123-456789abcdef",
"name": "Acme Corporate SSO",
"type": "oidc",
"discovery_url": "https://login.acme.com/.well-known/openid-configuration",
"idp_client_id": "contio-integration-prod",
"scopes": ["openid", "email", "profile"],
"claim_mappings": {
"email": "email",
"name": "name"
},
"mode": "strict",
"allowed_email_domains": ["acme.com", "acme.co.uk"],
"is_active": true,
"issuer": "https://login.acme.com",
"authorization_endpoint": "https://login.acme.com/oauth2/authorize",
"token_endpoint": "https://login.acme.com/oauth2/token",
"userinfo_endpoint": "https://login.acme.com/oauth2/userinfo",
"jwks_uri": "https://login.acme.com/.well-known/jwks.json",
"discovery_last_fetched_at": "2024-01-01T00:00:00Z",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
Error Responses:
| Status | Error Code | Description |
|---|---|---|
| 400 | invalid_request_body | Request body validation failed |
| 400 | invalid_idp_credentials | You provided your Contio Partner credentials instead of your IdP credentials |
| 400 | invalid_idp_credentials | You provided your Contio Partner credentials instead of your IdP credentials |
| 400 | invalid_idp_credentials | You provided your Contio Partner credentials instead of your IdP credentials |
| 400 | invalid_idp_credentials | You provided your Contio Partner credentials instead of your IdP credentials |
| 400 | invalid_idp | Public IdP (Google, Microsoft consumer, Zoho) not allowed |
| 400 | domain_is_generic | Generic email domain not allowed |
| 400 | strict_mode_requires_domains | Strict mode requires at least one allowed domain |
| 400 | discovery_fetch_failed | Failed to fetch OIDC discovery document |
| 401 | unauthorized | Invalid or missing API credentials |
| 409 | idp_config_exists | IdP configuration already exists for this partner |
| 409 | domain_already_claimed | Domain claimed by another partner |
Example:
// Note: IdP configuration methods coming soon to SDK
// For now, use direct API calls:
const response = await fetch('https://api.contio.ai/v1/partner/admin/idp', {
method: 'POST',
headers: {
'X-API-Key': process.env.CONTIO_API_KEY,
'X-Client-ID': process.env.CONTIO_CLIENT_ID,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Company SSO',
discovery_url: 'https://company.okta.com/.well-known/openid-configuration',
idp_client_id: '0oa1234567890abcdef',
idp_client_secret: process.env.IDP_CLIENT_SECRET,
mode: 'strict',
allowed_email_domains: ['company.com']
})
});
if (!response.ok) {
const error = await response.json();
console.error('Failed to create IdP config:', error.code, error.error);
throw new Error(error.error);
}
const config = await response.json();
console.log('Created IdP config:', config.id);
Get IdP Configuration¶
Retrieves the current IdP configuration for the authenticated partner app.
Endpoint: GET /v1/partner/admin/idp
Response (200 OK):
{
"id": "01234567-89ab-cdef-0123-456789abcdef",
"partner_app_id": "98765432-10ab-cdef-0123-456789abcdef",
"name": "Acme Corporate SSO",
"type": "oidc",
"discovery_url": "https://login.acme.com/.well-known/openid-configuration",
"idp_client_id": "contio-integration-prod",
"scopes": ["openid", "email", "profile"],
"claim_mappings": {
"email": "email",
"name": "name"
},
"mode": "strict",
"allowed_email_domains": ["acme.com", "acme.co.uk"],
"is_active": true,
"issuer": "https://login.acme.com",
"authorization_endpoint": "https://login.acme.com/oauth2/authorize",
"token_endpoint": "https://login.acme.com/oauth2/token",
"userinfo_endpoint": "https://login.acme.com/oauth2/userinfo",
"jwks_uri": "https://login.acme.com/.well-known/jwks.json",
"discovery_last_fetched_at": "2024-01-01T00:00:00Z",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-01T00:00:00Z"
}
Error Responses:
| Status | Error Code | Description |
|---|---|---|
| 401 | unauthorized | Invalid or missing API credentials |
| 404 | idp_config_not_found | No IdP configuration exists for this partner |
Example:
const response = await fetch('https://api.contio.ai/v1/partner/admin/idp', {
method: 'GET',
headers: {
'X-API-Key': process.env.CONTIO_API_KEY,
'X-Client-ID': process.env.CONTIO_CLIENT_ID
}
});
if (response.status === 404) {
console.log('No IdP configuration found');
return null;
}
const config = await response.json();
console.log('IdP config:', config.name, '- Active:', config.is_active);
Update IdP Configuration¶
Updates the IdP configuration for the authenticated partner app. All fields are optional; only include fields you want to change.
Endpoint: PUT /v1/partner/admin/idp
Request Body:
{
"name": "Updated SSO Name",
"discovery_url": "https://new-idp.acme.com/.well-known/openid-configuration",
"idp_client_id": "new-client-id",
"idp_client_secret": "new-client-secret",
"scopes": ["openid", "email", "profile", "groups"],
"claim_mappings": {
"email": "email",
"name": "displayName"
},
"mode": "partner_managed",
"allowed_email_domains": ["acme.com", "subsidiary.com"],
"is_active": true
}
Request Fields:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Display name (1-255 characters) |
discovery_url | string | No | OIDC discovery endpoint URL |
idp_client_id | string | No | OAuth Client ID from your Identity Provider |
idp_client_secret | string | No | OAuth Client Secret from your Identity Provider |
scopes | string[] | No | OIDC scopes to request |
claim_mappings | object | No | Claim to field mappings |
mode | string | No | Domain validation mode: strict or partner_managed |
allowed_email_domains | string[] | No | Allowed email domains |
is_active | boolean | No | Enable or disable the IdP configuration |
Response (200 OK):
Returns the updated IdP configuration (same schema as GET response).
Error Responses:
| Status | Error Code | Description |
|---|---|---|
| 400 | invalid_request_body | Request body validation failed |
| 400 | invalid_idp_credentials | You provided your Contio Partner credentials instead of your IdP credentials |
| 400 | invalid_idp | Public IdP not allowed |
| 400 | domain_is_generic | Generic email domain not allowed |
| 400 | strict_mode_requires_domains | Strict mode requires domains |
| 400 | discovery_fetch_failed | Failed to fetch discovery document |
| 401 | unauthorized | Invalid or missing API credentials |
| 404 | idp_config_not_found | No IdP configuration exists |
| 409 | domain_already_claimed | Domain claimed by another partner |
Example:
// Disable the IdP configuration temporarily
const response = await fetch('https://api.contio.ai/v1/partner/admin/idp', {
method: 'PUT',
headers: {
'X-API-Key': process.env.CONTIO_API_KEY,
'X-Client-ID': process.env.CONTIO_CLIENT_ID,
'Content-Type': 'application/json'
},
body: JSON.stringify({
is_active: false
})
});
const config = await response.json();
console.log('IdP config active:', config.is_active);
Delete IdP Configuration¶
Deletes the IdP configuration for the authenticated partner app. This action cannot be undone.
Endpoint: DELETE /v1/partner/admin/idp
Response (204 No Content):
No response body on success.
Error Responses:
| Status | Error Code | Description |
|---|---|---|
| 401 | unauthorized | Invalid or missing API credentials |
| 404 | idp_config_not_found | No IdP configuration exists |
Example:
const response = await fetch('https://api.contio.ai/v1/partner/admin/idp', {
method: 'DELETE',
headers: {
'X-API-Key': process.env.CONTIO_API_KEY,
'X-Client-ID': process.env.CONTIO_CLIENT_ID
}
});
if (response.status === 204) {
console.log('IdP configuration deleted successfully');
} else if (response.status === 404) {
console.log('No IdP configuration to delete');
}
Data Schemas¶
IdPConfigResponse¶
The complete IdP configuration object returned by GET and POST/PUT endpoints.
| Field | Type | Description |
|---|---|---|
id | string (UUID) | Unique identifier for the IdP configuration |
partner_app_id | string (UUID) | ID of the partner app this configuration belongs to |
name | string | Display name for the IdP configuration |
type | string | IdP type, always "oidc" |
discovery_url | string | OIDC discovery endpoint URL |
idp_client_id | string | OAuth Client ID from your Identity Provider (secret is never returned) |
scopes | string[] | OIDC scopes requested during authentication |
claim_mappings | object | Map of Contio fields to IdP claim names |
mode | string | Domain validation mode: "strict" or "partner_managed" |
allowed_email_domains | string[] | List of allowed email domains (may be empty) |
is_active | boolean | Whether the IdP configuration is active |
issuer | string | Cached IdP issuer from discovery document |
authorization_endpoint | string | Cached authorization endpoint URL |
token_endpoint | string | Cached token endpoint URL |
userinfo_endpoint | string | Cached userinfo endpoint URL |
jwks_uri | string | Cached JWKS endpoint URL |
discovery_last_fetched_at | string (ISO 8601) | When discovery document was last fetched |
created_at | string (ISO 8601) | When the configuration was created |
updated_at | string (ISO 8601) | When the configuration was last updated |
ClaimMappings¶
The claim_mappings object maps Contio user fields to IdP claim names. This allows customization for IdPs that use non-standard claim names.
| Contio Field | Purpose | Required | Default IdP Claim |
|---|---|---|---|
email | User's email address for account linking | Yes | email |
name | User's display name | No | name |
given_name | User's first name | No | given_name |
family_name | User's last name | No | family_name |
Standard OIDC Example:
Azure AD Example:
{
"email": "preferred_username",
"name": "name",
"given_name": "given_name",
"family_name": "family_name"
}
Custom IdP Example:
{
"email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
"name": "displayName",
"given_name": "firstName",
"family_name": "lastName"
}
DomainValidationMode¶
The mode field controls how user email domains are validated during SSO.
| Mode | Description |
|---|---|
strict | Requires allowed_email_domains to be specified with at least one domain. Only users with matching email domains can authenticate. Generic domains are blocked and cross-partner exclusivity is enforced. All users require prior OAuth connection. |
partner_managed | Domain list is optional. If provided, same validation rules apply. If empty, the partner's IdP controls access entirely. All users require prior OAuth connection. |
OAuth Connection Required
All users must establish a connection to your partner app via OAuth before they can use SSO. SSO provides authentication convenience using corporate IdP credentials, not user provisioning.
ErrorResponse¶
All error responses follow this format:
{
"code": "error_code",
"error": "Human-readable error message",
"request_id": "unique-request-id"
}
| Field | Type | Description |
|---|---|---|
code | string | Machine-readable error code |
error | string | Human-readable error description |
request_id | string | Unique identifier for the request (useful for support) |
Error Reference¶
Complete list of error codes for IdP configuration endpoints.
| Error Code | HTTP Status | Description | Recovery Action |
|---|---|---|---|
invalid_request_body | 400 | Request body failed validation | Check required fields and data types |
invalid_idp | 400 | Public IdP (Google, Microsoft consumer, Zoho) not allowed | Use a corporate/organizational IdP |
domain_is_generic | 400 | Generic email domain (gmail.com, etc.) in allowed_email_domains | Use corporate domains only |
strict_mode_requires_domains | 400 | Strict mode selected but no allowed_email_domains provided | Add at least one allowed email domain |
discovery_fetch_failed | 400 | Could not fetch OIDC discovery document | Verify discovery_url is correct and accessible |
unauthorized | 401 | Invalid or missing API key/client ID | Check X-API-Key and X-Client-ID headers |
idp_config_not_found | 404 | No IdP configuration exists for this partner | Create an IdP configuration first |
idp_config_exists | 409 | IdP configuration already exists | Use PUT to update or DELETE to remove |
domain_already_claimed | 409 | Email domain claimed by another partner | Contact Contio support if you own this domain |
internal_server_error | 500 | Unexpected server error | Retry the request; contact support if persistent |
Partner SSO Flow Endpoints¶
These public endpoints handle the SSO authentication flow. They are documented here for reference but are typically not called directly by partner applications.
Get Partner SSO Info¶
Returns partner branding and SSO configuration status for landing pages.
Endpoint: GET /v1/partner/sso/info/{slug}
Path Parameters:
| Parameter | Type | Description |
|---|---|---|
slug | string | Partner app slug |
Response (200 OK):
{
"slug": "acme",
"name": "Acme Inc",
"co_brand_name": "Acme Meetings",
"co_brand_logo_url": "https://cdn.acme.com/logo.png",
"has_idp_config": true,
"is_active": true
}
Rate Limit: 30 requests per minute per IP address.
Initiate SSO Flow¶
Starts the SSO authentication flow for a partner's identity provider.
Endpoint: GET /v1/partner/sso/initiate
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
slug | string | Yes | Partner app slug |
target | string | No | Target platform: web (default) or desktop |
auto | boolean | No | If true, redirect directly to IdP |
Response (200 OK):
Response (302 Found): When auto=true, redirects directly to the authorization URL.
SSO Callback¶
Handles the OIDC callback from the partner's identity provider. This endpoint is called by the IdP after user authentication.
Endpoint: GET /v1/partner/sso/callback
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
code | string | Authorization code from IdP |
state | string | State parameter for session validation |
error | string | Error code if authentication failed |
error_description | string | Error description if authentication failed |
Response: Redirects to the target application (web or desktop deep link) after processing.
Session Status¶
Returns the current status of a partner SSO session for polling.
Endpoint: GET /v1/partner/sso/session/{session_id}
Response (200 OK):
Status Values:
| Status | Description |
|---|---|
pending | Session is active, waiting for authentication |
expired | Session has expired (10 minute timeout) |
not_found | Session not found or already processed |
SDK Support¶
SDK Methods Coming Soon
IdP configuration methods are not yet available in the TypeScript SDK. Use direct API calls as shown in the examples above. SDK support will be added in a future release.
When SDK support is available, the methods will follow this pattern:
// Future SDK usage (not yet available)
const { admin } = ContioPartnerSDK.forAdmin({
apiKey: process.env.CONTIO_API_KEY,
clientId: process.env.CONTIO_CLIENT_ID
});
// Create IdP configuration
const config = await admin.idp.create({
name: 'Company SSO',
discovery_url: 'https://company.okta.com/.well-known/openid-configuration',
idp_client_id: 'client-id-from-your-idp',
idp_client_secret: 'client-secret-from-your-idp',
mode: 'strict',
allowed_email_domains: ['company.com']
});
// Get IdP configuration
const config = await admin.idp.get();
// Update IdP configuration
const updated = await admin.idp.update({ is_active: false });
// Delete IdP configuration
await admin.idp.delete();
Next Steps¶
- SSO Integration Guide - Step-by-step integration walkthrough
- OAuth Flow Guide - Standard OAuth for user data access
- Authentication - Authentication overview
- Credential Management - API key rotation