Skip to content

SAML Admin API

The SAML admin API manages SAML 2.0 Identity Provider (IdP) configurations for your tenant. Each IdP configuration stores the metadata the gateway needs to initiate SSO logins and validate SAML assertions from that IdP.

Admin CRUD endpoints require authentication (Authorization: Bearer <admin-api-key>). The SP metadata and SSO flow endpoints are unauthenticated (they are accessed by the IdP or the browser during the login handshake).

Base path: /api/v1/admin/saml


Method Path Auth required Description
POST /api/v1/admin/saml/idp Admin Create an IdP configuration
GET /api/v1/admin/saml/idp Admin List all IdP configurations
GET /api/v1/admin/saml/idp/{idp_id} Admin Get a single IdP configuration
PUT /api/v1/admin/saml/idp/{idp_id} Admin Update an IdP configuration
DELETE /api/v1/admin/saml/idp/{idp_id} Admin Delete an IdP configuration
GET /api/saml/metadata None SP SAML metadata XML
GET /api/saml/login None Initiate a SAML login
POST /api/saml/acs None Assertion Consumer Service (IdP callback)

Returned by all admin CRUD endpoints.

Field Type Description
id UUID Unique identifier for this IdP configuration
name string Human-readable name (e.g. "Okta Production", "Azure AD")
entity_id string The IdP issuer URI — must be globally unique per tenant. Matches the Issuer element in SAML responses from this IdP.
sso_url string The IdP Single Sign-On URL. The gateway redirects users here to initiate authentication.
slo_url string | null The IdP Single Logout URL. If set, the gateway sends logout requests here during SLO flows.
x509_cert string PEM-encoded X.509 certificate used to verify SAML assertion signatures. Omit the -----BEGIN CERTIFICATE----- header/footer when storing; the API accepts both forms.
attribute_mapping object | null Maps Arbitex user fields to the SAML attribute names your IdP uses. See below.
is_active boolean Whether this IdP is available for login. Inactive configurations are retained but cannot initiate SSO sessions.
created_at string (ISO 8601) Creation timestamp
updated_at string (ISO 8601) Last modification timestamp

The attribute_mapping object tells the gateway which SAML attributes in the assertion correspond to Arbitex user fields. Keys are Arbitex field names; values are the SAML attribute name or OID your IdP emits.

Arbitex field Purpose
email User’s email address (used as the primary identifier)
username Display name or username
groups Group membership — value should be a multi-valued attribute containing group names or IDs

If attribute_mapping is null, the gateway falls back to standard SAML 2.0 attribute names and the NameID element for email.

Example — Okta (OID-based)

{
"email": "urn:oid:0.9.2342.19200300.100.1.3",
"username": "urn:oid:2.16.840.1.113730.3.1.241",
"groups": "memberOf"
}

Example — Azure AD (friendly names)

{
"email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
"username": "http://schemas.microsoft.com/identity/claims/displayname",
"groups": "http://schemas.microsoft.com/ws/2008/06/identity/claims/groups"
}

Example — Generic / simple

{
"email": "email",
"username": "displayName",
"groups": "groups"
}

POST /api/v1/admin/saml/idp

Registers a new SAML IdP with the tenant. After creation, use the SP metadata endpoint to retrieve the XML you must upload to the IdP.

Request body

Field Type Required Description
name string yes Human-readable name for this IdP
entity_id string yes IdP issuer URI. Must be unique within this tenant.
sso_url string yes IdP SSO endpoint URL
slo_url string | null no IdP Single Logout URL
x509_cert string yes PEM-encoded signing certificate from the IdP metadata
attribute_mapping object | null no Attribute name mapping (see above)
is_active boolean no Default true
Terminal window
curl -X POST https://gateway.arbitex.ai/api/v1/admin/saml/idp \
-H "Authorization: Bearer $ARBITEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Okta Production",
"entity_id": "http://www.okta.com/exkAbc123XyZ",
"sso_url": "https://acme.okta.com/app/arbitex/exkAbc123XyZ/sso/saml",
"slo_url": "https://acme.okta.com/app/arbitex/exkAbc123XyZ/slo/saml",
"x509_cert": "MIIDpDCCAoygAwIBAgIGAV...",
"attribute_mapping": {
"email": "urn:oid:0.9.2342.19200300.100.1.3",
"username": "urn:oid:2.16.840.1.113730.3.1.241",
"groups": "memberOf"
},
"is_active": true
}'

Response 201 Created

{
"id": "idp_01hx4k2m9n-...",
"name": "Okta Production",
"entity_id": "http://www.okta.com/exkAbc123XyZ",
"sso_url": "https://acme.okta.com/app/arbitex/exkAbc123XyZ/sso/saml",
"slo_url": "https://acme.okta.com/app/arbitex/exkAbc123XyZ/slo/saml",
"x509_cert": "MIIDpDCCAoygAwIBAgIGAV...",
"attribute_mapping": {
"email": "urn:oid:0.9.2342.19200300.100.1.3",
"username": "urn:oid:2.16.840.1.113730.3.1.241",
"groups": "memberOf"
},
"is_active": true,
"created_at": "2026-03-12T10:00:00Z",
"updated_at": "2026-03-12T10:00:00Z"
}

Response 409 Conflict — an IdP with that entity_id already exists for this tenant.


GET /api/v1/admin/saml/idp

Returns all IdP configurations registered for the tenant.

Terminal window
curl https://gateway.arbitex.ai/api/v1/admin/saml/idp \
-H "Authorization: Bearer $ARBITEX_API_KEY"

Response 200 OK

{
"idps": [
{
"id": "idp_01hx4k2m9n-...",
"name": "Okta Production",
"entity_id": "http://www.okta.com/exkAbc123XyZ",
"sso_url": "https://acme.okta.com/app/arbitex/exkAbc123XyZ/sso/saml",
"slo_url": "https://acme.okta.com/app/arbitex/exkAbc123XyZ/slo/saml",
"x509_cert": "MIIDpDCCAoygAwIBAgIGAV...",
"attribute_mapping": { "email": "urn:oid:0.9.2342.19200300.100.1.3", "username": "urn:oid:2.16.840.1.113730.3.1.241", "groups": "memberOf" },
"is_active": true,
"created_at": "2026-03-12T10:00:00Z",
"updated_at": "2026-03-12T10:00:00Z"
},
{
"id": "idp_01hx4k2m9p-...",
"name": "Azure AD Staging",
"entity_id": "https://sts.windows.net/tenant-id-staging/",
"sso_url": "https://login.microsoftonline.com/tenant-id-staging/saml2",
"slo_url": null,
"x509_cert": "MIIDAjCCAeqgAwIBAgI...",
"attribute_mapping": null,
"is_active": false,
"created_at": "2026-02-01T09:00:00Z",
"updated_at": "2026-03-01T14:20:00Z"
}
],
"total": 2
}

GET /api/v1/admin/saml/idp/{idp_id}

Path parameters

Parameter Type Description
idp_id UUID The IdP configuration UUID
Terminal window
curl https://gateway.arbitex.ai/api/v1/admin/saml/idp/idp_01hx4k2m9n-... \
-H "Authorization: Bearer $ARBITEX_API_KEY"

Response 200 OK — single SAMLIdPConfig object.

Response 404 Not Found — IdP configuration does not exist for this tenant.


PUT /api/v1/admin/saml/idp/{idp_id}

Partial update — only fields included in the request body are modified. Use this to rotate a certificate, update the SSO URL after an IdP migration, or toggle is_active.

Path parameters

Parameter Type Description
idp_id UUID The IdP configuration UUID

Request body (all fields optional)

Field Type Description
name string New display name
entity_id string New issuer URI. Must remain unique within the tenant.
sso_url string New SSO endpoint URL
slo_url string | null New SLO URL. Pass null to clear.
x509_cert string New PEM-encoded certificate (certificate rotation)
attribute_mapping object | null Updated attribute mapping. Pass null to revert to defaults.
is_active boolean Enable or disable this IdP
Terminal window
# Rotate the signing certificate
curl -X PUT https://gateway.arbitex.ai/api/v1/admin/saml/idp/idp_01hx4k2m9n-... \
-H "Authorization: Bearer $ARBITEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"x509_cert": "MIIDqDCCApCgAwIBAgIGAWnew..."
}'
Terminal window
# Disable an IdP without deleting it
curl -X PUT https://gateway.arbitex.ai/api/v1/admin/saml/idp/idp_01hx4k2m9p-... \
-H "Authorization: Bearer $ARBITEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"is_active": false}'

Response 200 OK — the updated SAMLIdPConfig object.

Response 404 Not Found — IdP configuration does not exist.

Response 409 Conflict — the new entity_id conflicts with another existing configuration.


DELETE /api/v1/admin/saml/idp/{idp_id}

Permanently removes the IdP configuration. Any active SSO sessions established through this IdP are not affected, but subsequent logins via this IdP will fail.

Path parameters

Parameter Type Description
idp_id UUID The IdP configuration UUID
Terminal window
curl -X DELETE https://gateway.arbitex.ai/api/v1/admin/saml/idp/idp_01hx4k2m9n-... \
-H "Authorization: Bearer $ARBITEX_API_KEY"

Response 204 No Content — IdP configuration deleted.

Response 404 Not Found — IdP configuration does not exist.


The Service Provider (SP) metadata endpoint returns the Arbitex gateway’s SAML metadata XML. Upload this document to your IdP to configure the trust relationship — it contains the SP entity ID, ACS URL, and the SP’s signing certificate.

GET /api/saml/metadata

No authentication required. The IdP typically fetches this URL automatically during initial configuration, or you can download it and upload it manually.

Terminal window
curl https://gateway.arbitex.ai/api/saml/metadata

Response 200 OK — XML document with Content-Type: application/xml.

<?xml version="1.0" encoding="UTF-8"?>
<EntityDescriptor
xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
entityID="https://gateway.arbitex.ai/saml/sp">
<SPSSODescriptor
AuthnRequestsSigned="true"
WantAssertionsSigned="true"
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>MIIDpDCCAoygAwIBAgI...</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</KeyDescriptor>
<SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="https://gateway.arbitex.ai/api/saml/slo" />
<AssertionConsumerService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="https://gateway.arbitex.ai/api/saml/acs"
index="1"
isDefault="true" />
</SPSSODescriptor>
</EntityDescriptor>

Use the values in this document when configuring the IdP:

SP value Where to use it in your IdP
entityID attribute SP Entity ID / Audience URI
AssertionConsumerService Location ACS URL / Reply URL / Callback URL
SingleLogoutService Location SLO URL (optional)
X509Certificate SP signing certificate (import if IdP verifies AuthnRequests)

GET /api/saml/login?idp_id={idp_id}

Initiates a SAML SP-initiated SSO login. The gateway constructs a signed AuthnRequest and returns a redirect to the IdP SSO URL.

Query parameters

Parameter Type Required Description
idp_id UUID yes The IdP configuration to use for this login
relay_state string no Optional opaque value returned unchanged by the IdP after authentication. Use to preserve the URL the user was trying to reach.
Terminal window
# In a browser or front-end redirect:
https://gateway.arbitex.ai/api/saml/login?idp_id=idp_01hx4k2m9n-...&relay_state=/dashboard

Response 302 Found — redirect to the IdP SSO URL with the encoded SAMLRequest and RelayState query parameters.

Response 400 Bad Request — idp_id is missing or malformed.

Response 404 Not Found — no active IdP configuration exists for the given idp_id.


POST /api/saml/acs

The Assertion Consumer Service (ACS) endpoint. The IdP POSTs the base64-encoded SAML response here after the user authenticates. This endpoint is not called directly by API clients — it is the callback target for the IdP.

Form parameters (sent by the IdP as application/x-www-form-urlencoded)

Parameter Description
SAMLResponse Base64-encoded, IdP-signed SAML response XML
RelayState The opaque value passed during login initiation (if any)

On success: The gateway validates the assertion signature against the stored x509_cert, extracts user identity from the configured attribute mapping, creates or updates the user session, and redirects to the portal (or the URL in RelayState).

On failure: Returns 400 Bad Request with a human-readable error. Common failure reasons:

Reason Likely cause
invalid_signature Certificate mismatch — check x509_cert in the IdP config
assertion_expired Clock skew between gateway and IdP is too large (> 5 minutes)
missing_email Email attribute not present; verify attribute_mapping.email matches IdP output
unknown_issuer The Issuer in the response does not match any configured entity_id

To rotate an IdP’s signing certificate without disrupting active sessions:

  1. Obtain the new certificate from the IdP.
  2. Call PUT /api/v1/admin/saml/idp/{idp_id} with only the new x509_cert value.
  3. Confirm with the IdP administrator that the IdP is now signing with the new certificate.
  4. Test by initiating a fresh login via /api/saml/login?idp_id={idp_id}.

The gateway validates new assertions against the updated certificate immediately after the PUT completes. There is no grace period for the old certificate — complete the rotation on the IdP side before or at the same time as the API update.


Status Meaning
400 Bad Request Malformed request body, invalid certificate format, or invalid SAML response at the ACS
403 Forbidden Caller is not an admin (admin CRUD endpoints only)
404 Not Found IdP configuration does not exist for this tenant
409 Conflict entity_id conflicts with an existing IdP configuration