# Inbound OAuth

> Inbound OAuth - title: "Authenticate with an external IdP token (OAuth 2.0 token exchange)"
> description: Exchange an external identity provider (IdP) access token for a DataRobot access token
> using OAuth 2.0 token exchange (RFC 8693). The external OAuth developer workflow for inbound OAuth:
> bring your own IdP (Okta, Microsoft Entra ID, Ping, Auth0) for user authentication to the DataRobot
> API.

This Markdown file sits beside the HTML page at the same path (with a `.md` suffix). It summarizes the topic and lists links for tools and LLM context.

Companion generated at `2026-08-13T14:19:04.980130+00:00` (UTC).

## Primary page

- [Inbound OAuth](https://docs.datarobot.com/en/docs/api/dev-learning/inbound-oauth-tokens.html.md): Full documentation for this topic (Markdown sidecar).

## Sections on this page

- [Prerequisites](https://docs.datarobot.com/en/docs/api/dev-learning/inbound-oauth-tokens.html.md#prerequisites): In-page section heading.
- [Workflow overview](https://docs.datarobot.com/en/docs/api/dev-learning/inbound-oauth-tokens.html.md#workflow-overview): In-page section heading.
- [Step 1: Get an IdP access token](https://docs.datarobot.com/en/docs/api/dev-learning/inbound-oauth-tokens.html.md#step-1-get-an-idp-access-token): In-page section heading.
- [Step 2: Exchange for a DataRobot access token](https://docs.datarobot.com/en/docs/api/dev-learning/inbound-oauth-tokens.html.md#step-2-exchange-for-a-datarobot-access-token): In-page section heading.
- [Step 3: Call the DataRobot API](https://docs.datarobot.com/en/docs/api/dev-learning/inbound-oauth-tokens.html.md#step-3-call-the-datarobot-api): In-page section heading.
- [Token lifetime](https://docs.datarobot.com/en/docs/api/dev-learning/inbound-oauth-tokens.html.md#token-lifetime): In-page section heading.
- [Error reference](https://docs.datarobot.com/en/docs/api/dev-learning/inbound-oauth-tokens.html.md#error-reference): In-page section heading.
- [FAQ](https://docs.datarobot.com/en/docs/api/dev-learning/inbound-oauth-tokens.html.md#faq): In-page section heading.
- [How do I authenticate to the DataRobot API using my Okta or Microsoft Entra ID token?](https://docs.datarobot.com/en/docs/api/dev-learning/inbound-oauth-tokens.html.md#authenticate-okta-entra): In-page section heading.
- [Related](https://docs.datarobot.com/en/docs/api/dev-learning/inbound-oauth-tokens.html.md#related): In-page section heading.

## Related documentation

- [Developer documentation](https://docs.datarobot.com/en/docs/api/index.html.md): Linked from this page.
- [Developer learning](https://docs.datarobot.com/en/docs/api/dev-learning/index.html.md): Linked from this page.
- [Inbound OAuth](https://docs.datarobot.com/en/docs/platform/admin/inbound-oauth.html.md): Linked from this page.
- [Retrieve the API endpoint](https://docs.datarobot.com/en/docs/api/dev-learning/api-quickstart.html.md#retrieve-the-api-endpoint): Linked from this page.

## Documentation content

title: "Authenticate with an external IdP token (OAuth 2.0 token exchange)"
description: Exchange an external identity provider (IdP) access token for a DataRobot access token using OAuth 2.0 token exchange (RFC 8693). The external OAuth developer workflow for inbound OAuth: bring your own IdP (Okta, Microsoft Entra ID, Ping, Auth0) for user authentication to the DataRobot API.

With inbound OAuth, you authenticate to the DataRobot API using an access token from your own identity provider (IdP) instead of a DataRobot API key. You exchange your IdP access token for a short-lived DataRobot access token using OAuth 2.0 token exchange ( [RFC 8693](https://datatracker.ietf.org/doc/html/rfc8693)), then send that DataRobot token as a bearer token on API requests. This external OAuth workflow lets your users authenticate with credentials they already have.

This page covers the developer workflow. For the administrator setup (registering a trusted IdP, provisioning, and mapping), see [Inbound OAuth](https://docs.datarobot.com/en/docs/platform/admin/inbound-oauth.html.md).

## Prerequisites

- An administrator has configured inbound OAuth for your organization or application and given you the token-exchange endpoint.
- You can obtain an OAuth 2.0 access token from your IdP (for example, Okta, Microsoft Entra ID, Ping, or Auth0).
- Your IdP issues access tokens that include the dr.impersonation scope and carry the DataRobot audience ( aud ) your administrator provides. DataRobot validates both during the exchange; a missing scope or mismatched audience is rejected. See Step 1 .
- You have the DataRobot API endpoint for your region (see Retrieve the API endpoint ).

## Workflow overview

1. Get an access token from your IdP.
2. Exchange it for a DataRobot access token.
3. Call the DataRobot API with the DataRobot token.

## Step 1: Get an IdP access token

Obtain an OAuth 2.0 access token from your IdP using your organization's standard flow (for example, the authorization code flow). The token must be a JWT access token issued by the IdP your administrator registered.

> [!NOTE] Important
> The token must include the `dr.impersonation` scope. DataRobot validates this scope during the exchange and rejects tokens without it. If your IdP doesn't add the scope by default, request it when you obtain the token, or ask your administrator to configure the IdP to include it.

Refer to your IdP's documentation for how to obtain a token. The following sections refer to that token as `IDP_ACCESS_TOKEN`.

> [!NOTE] Important
> The IdP access token must include the `dr.impersonation` scope, in the claim your administrator mapped (typically `scp` or `scope`). DataRobot validates this scope during the exchange and rejects the request with `invalid_scope` if the token carries scopes but not `dr.impersonation`. Configure your IdP's authorization server (or app and scope registration) to add `dr.impersonation` to the tokens it issues.

## Step 2: Exchange for a DataRobot access token

Exchange the IdP token at the token-exchange endpoint. The endpoint is served at your DataRobot application root, not under `/api/v2`:

| Configuration scope | Endpoint |
| --- | --- |
| Global | https://YOUR_DATAROBOT_HOST/oauth2/token |
| Organization | https://YOUR_DATAROBOT_HOST/oauth2/token/ORGANIZATION_ID |

> [!NOTE] Note
> Use the DataRobot host you sign in with (for example, `https://app.datarobot.com`), not the `/api/v2` endpoint. Confirm the exact token-exchange URL for your environment with your administrator.

Send a `POST` request with the [RFC 8693](https://datatracker.ietf.org/doc/html/rfc8693) token-exchange parameters, form-encoded:

| Parameter | Value |
| --- | --- |
| grant_type | urn:ietf:params:oauth:grant-type:token-exchange |
| subject_token | Your IDP_ACCESS_TOKEN. |
| subject_token_type | urn:ietf:params:oauth:token-type:access_token |

**cURL:**
```
export IDP_ACCESS_TOKEN="YOUR_IDP_ACCESS_TOKEN"

curl --location -X POST \
  "https://YOUR_DATAROBOT_HOST/oauth2/token/ORGANIZATION_ID" \
  --header "Accept: application/json" \
  --header "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
  --data-urlencode "subject_token=${IDP_ACCESS_TOKEN}" \
  --data-urlencode "subject_token_type=urn:ietf:params:oauth:token-type:access_token"
```

**Python:**
```
import requests

DATAROBOT_HOST = "https://YOUR_DATAROBOT_HOST"
ORGANIZATION_ID = "ORGANIZATION_ID"  # your organization's ID
idp_access_token = "YOUR_IDP_ACCESS_TOKEN"

response = requests.post(
    f"{DATAROBOT_HOST}/oauth2/token/{ORGANIZATION_ID}",
    headers={"Accept": "application/json"},
    data={
        "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
        "subject_token": idp_access_token,
        "subject_token_type": "urn:ietf:params:oauth:token-type:access_token",
    },
)
response.raise_for_status()
datarobot_access_token = response.json()["access_token"]
```


A successful exchange returns a DataRobot access token:

```
{
  "access_token": "<DATAROBOT_ACCESS_TOKEN>",
  "issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "dr.impersonation"
}
```

| Field | Description |
| --- | --- |
| access_token | The DataRobot access token to use on API requests. |
| token_type | Always Bearer. |
| expires_in | Lifetime of the token, in seconds. |
| scope | The granted scope. Inbound OAuth tokens carry the dr.impersonation scope. |

## Step 3: Call the DataRobot API

Send the DataRobot access token as a bearer token, the same as you would a DataRobot API key. Use the `/api/v2` endpoint for your region.

**cURL:**
```
export DATAROBOT_ENDPOINT="https://YOUR_DATAROBOT_HOST/api/v2"
export DATAROBOT_ACCESS_TOKEN="DATAROBOT_ACCESS_TOKEN_FROM_STEP_2"

curl --location -X GET "${DATAROBOT_ENDPOINT}/projects/" \
  --header "Authorization: Bearer ${DATAROBOT_ACCESS_TOKEN}"
```

**Python:**
```
import datarobot as dr

client = dr.Client(
    endpoint="https://YOUR_DATAROBOT_HOST/api/v2",
    token=datarobot_access_token,  # from Step 2
)
print(dr.Project.list())
```


## Token lifetime

DataRobot access tokens from inbound OAuth are short-lived (typically one hour). Read `expires_in` from the exchange response rather than hard-coding a value. When a token expires, repeat [Step 2](https://docs.datarobot.com/en/docs/api/dev-learning/inbound-oauth-tokens.html.md#step-2-exchange-for-a-datarobot-access-token) to get a new one. Tokens can't be revoked individually.

## Error reference

The token-exchange endpoint returns errors defined by [RFC 6749](https://datatracker.ietf.org/doc/html/rfc6749) and [RFC 8693](https://datatracker.ietf.org/doc/html/rfc8693):

```
{
  "error": "<ERROR_CODE>",
  "error_description": "<ERROR_DESCRIPTION>"
}
```

| Error code | HTTP status | Description |
| --- | --- | --- |
| invalid_request | 400 | The request is missing a parameter, has an unsupported parameter, or is otherwise malformed. |
| invalid_client | 401 | Unknown client, missing client details, or invalid bearer token. |
| invalid_grant | 400 | The provided subject token is invalid or expired. |
| unauthorized_client | 400 | The client isn't authorized to use the token-exchange grant type. |
| unsupported_grant_type | 400 | The server doesn't support the requested grant type. |
| invalid_scope | 400 | The token's scopes are invalid or don't include the required dr.impersonation scope. |
| invalid_target | 400 | The audience is invalid. |
| access_denied | 403 | Token exchange isn't available or enabled for this configuration. |

> [!TIP] Tip
> An `invalid_scope` error (HTTP 400) with the message "The token does not contain the required scope: dr.impersonation" means your IdP token doesn't carry the `dr.impersonation` scope. Configure your IdP to include it, then confirm the [scope mapping](https://docs.datarobot.com/en/docs/platform/admin/inbound-oauth.html.md#scope-mapping) with your administrator.

## FAQ

### How do I authenticate to the DataRobot API using my Okta or Microsoft Entra ID token?

Get an access token from Okta or Microsoft Entra ID, exchange it for a DataRobot access token ( [Step 2](https://docs.datarobot.com/en/docs/api/dev-learning/inbound-oauth-tokens.html.md#step-2-exchange-for-a-datarobot-access-token)), and call the API with the DataRobot token ( [Step 3](https://docs.datarobot.com/en/docs/api/dev-learning/inbound-oauth-tokens.html.md#step-3-call-the-datarobot-api)). Your administrator must first register the IdP through [Inbound OAuth](https://docs.datarobot.com/en/docs/platform/admin/inbound-oauth.html.md).

## Related

- Inbound OAuth —administrator configuration for the trusted IdP, provisioning, and mapping.
- Developer quickstart —API keys, endpoints, and credential setup.
