Start here
Quickstart
This guide takes you from a new OrbitID team to a verified user profile in your app. Everything below works against the free Sandbox environment.
With your coding agent
Claude Code, Cursor or Codex makes the change in your repo and tells you what it touched.
Add enterprise SSO to this app with OrbitID. Follow https://orbitid.com/docs/quickstart.md 1. Read the key from ORBITID_API_KEY and the product id from ORBITID_PRODUCT_ID. 2. Add a sign-in route that redirects to https://app.orbitid.com/api/oauth/authorize with client_id=tenant=<tenant>&product=<product>, our callback URL and a random state. 3. In the callback, check state, swap the code at /api/oauth/token, read /api/oauth/userinfo. 4. Find or create the user by email and start a session the way this app already does. 5. Test with the Sandbox key (orb_test_) and the tenant "acme". 6. Run the tests, then list the files you changed and the env vars I need to set.
Create a team
Sign up at app.orbitid.com/signup and create a team. Every team gets two environments:
- Sandbox – free, up to 5 connections, for development and testing.
- Production – $25 per connection per month, for your customers.
Each environment has its own connections, API keys, logs and a product id. You will need the product id when you start a login; it is shown on the environment's Configuration page. See Environments.
Create an API key
Open the environment, go to API keys and create a key. Sandbox keys start with orb_test_; production keys start with orb_live_. The full key is shown once, so copy it straight away.
Send it as a bearer token on every request to https://app.orbitid.com/api/v1:
curl https://app.orbitid.com/api/v1/sso \-H "Authorization: Bearer orb_test_..."
A key is scoped to its environment: the product of every request is set from the key, so you never pass it yourself. See API keys.
Create a connection
A connection links one of your customers (a tenant, identified by any string you choose, such as acme) to their identity provider. There are three ways to create one.
In the dashboard
Open Connections, click New connection, enter the tenant and paste the IdP metadata URL or XML. The SSO setup guides show where to find the metadata for each provider.
With an Admin Portal link
Let your customer's IT admin do it themselves. Create a link and send it to them:
curl -X POST https://app.orbitid.com/api/v1/portal/links \-H "Authorization: Bearer orb_test_..." \-H "Content-Type: application/json" \-d '{"tenant": "acme","tenantName": "Acme Inc.","redirectUrl": "https://yourapp.com/settings/sso","domains": ["acme.com"]}'
The response contains a url that the admin opens:
{"data": {"id": "6f1c0b2d…","url": "https://app.orbitid.com/portal/6f1c0b2d…","tenant": "acme","tenantName": "Acme Inc.","redirectUrl": "https://yourapp.com/settings/sso","domains": ["acme.com"],"verifiedDomains": [],"expiresAt": 1727000000000}}
domains is optional. When you pass it, the admin has to verify the domains before the connection goes live. See Admin Portal.
With the API
If you already have the metadata, create the connection directly:
curl -X POST https://app.orbitid.com/api/v1/sso \-H "Authorization: Bearer orb_test_..." \-H "Content-Type: application/json" \-d '{"name": "Acme Okta","tenant": "acme","defaultRedirectUrl": "https://yourapp.com/auth/callback","redirectUrl": ["https://yourapp.com/auth/callback"],"metadataUrl": "https://acme.okta.com/app/abc123/sso/saml/metadata"}'
Use rawMetadata instead of metadataUrl to pass the XML inline. For an OIDC provider send oidcDiscoveryUrl, oidcClientId and oidcClientSecret instead of the metadata fields. redirectUrl lists every URL you will use as redirect_uri later.
Start a login
Send the user to the authorize endpoint. client_id is the string tenant=<tenant>&product=<product>, URL-encoded, where product is the product id from the Configuration page:
https://app.orbitid.com/api/oauth/authorize?client_id=tenant%3Dacme%26product%3D<product>&redirect_uri=https%3A%2F%2Fyourapp.com%2Fauth%2Fcallback&response_type=code&state=<random-state>
OrbitID looks up the tenant's connection, redirects the user to their IdP, and once they have signed in redirects them back to redirect_uri with code and state in the query string. Check that state matches what you sent.
Exchange the code
Exchange the code for an access token. When client_id carries the tenant and product, pass dummy as the client_secret:
curl -X POST https://app.orbitid.com/api/oauth/token \-H "Content-Type: application/x-www-form-urlencoded" \--data-urlencode "grant_type=authorization_code" \--data-urlencode "client_id=tenant=acme&product=<product>" \--data-urlencode "client_secret=dummy" \--data-urlencode "code=<code>" \--data-urlencode "redirect_uri=https://yourapp.com/auth/callback"
{"access_token": "5b1a…","token_type": "bearer","expires_in": 300}
If you prefer, use the clientID and clientSecret that the API returned when the connection was created instead of the tenant/product pair.
Fetch the profile
curl https://app.orbitid.com/api/oauth/userinfo \-H "Authorization: Bearer <access_token>"
{"id": "00u1abc…","firstName": "Jane","lastName": "Doe","requested": { "tenant": "acme", "product": "<product>" },"raw": { "…": "all attributes the IdP sent" }}
The email and id were verified by the customer's identity provider. Look the user up (or create them) in your app, start a session, and you are done.
Next steps
- Move a customer to Production and set up Billing.
- Add Directory Sync to provision users and groups automatically.
- Read the SSO setup guides for the exact steps in each identity provider.

