Migrating from V1

Migrating from V1

The Doppel V2 API preserves the V1 path and request/response contract for
equivalent, non-deprecated endpoints, with a new authentication model. It also
adds V2-only asset endpoints and deprecates the older V2 protected-asset list
and create routes.

For routes that exist in both versions and are not deprecated, migration is
primarily an authentication and path-prefix change. Integrations that use
report routes or protected-asset list/create routes should also make the
resource changes below.

What changed

V1V2
Auth headersx-api-key (organization-wide), or x-api-key + x-user-api-key (user-specific)Authorization: Bearer <access_token>
Token issuanceStatic keys: organization-wide keys are issued by your Doppel sales representative; user-specific keys are self-service from Doppel Vision API settings.OAuth 2.0 client credentials at POST /oauth/token; access_token expires after expires_in seconds (24 hours at the time of writing)
Org scope headerx-organization-code: <ORG> (optional; per the V1 OpenAPI spec, required only when your user belongs to multiple organizations)Not part of the V2 contract — organization is derived from the org_id claim in the JWT
Path prefix/v1/<resource>/v2/<resource>
Request/response bodiesUnchanged for equivalent non-deprecated endpoints; V2-only asset routes have their own contracts

If your code uses only routes present in both versions and no deprecated
endpoints (see below), the required code changes are: (1) exchange your client
credentials for a token, (2) replace the V1 auth headers with
Authorization: Bearer ..., (3) drop the x-organization-code header if you
were sending one, and (4) change /v1/ to /v2/ in those request URLs.

Deprecated endpoints

The following V1 endpoints are deprecated in V2 and are documented as deprecated: true in the V2 OpenAPI spec. They still work, but new integrations should not depend on them.

  • POST /v2/report — use POST /v2/alert instead
  • GET /v2/report — use GET /v2/alert instead
  • PUT /v2/report — use PUT /v2/alert instead
  • GET /v2/reports — use GET /v2/alerts instead
  • GET /v2/protected-assets — use GET /v2/assets with the required
    asset_type
  • POST /v2/protected-asset — use POST /v2/assets with the required
    asset_type

The report resource and the alert resource refer to the same underlying
object. The migration is a rename: replace report with alert (and reports
with alerts) in the path. Request bodies and response shapes are otherwise
identical.

The deprecated protected-asset routes also continue to work. The old list
returns owned and associated assets together, and the old create route creates
owned assets only. DELETE /v2/protected-asset/{id} is not deprecated.

V2-only asset workflows

V2 adds:

  • GET /v2/assets to list one required asset_type
  • POST /v2/assets to create an owned or associated asset
  • POST /v2/alert/assets to create an asset using the value and brand from an
    alert

See Manage assets for examples and migration guidance.

Step 1: Get an OAuth access token

An organization admin or super admin can create a Client ID and Client Secret from the Version 2 tab on the API Settings page in Doppel Vision. Credentials are self-service, and each organization can have up to 10 clients.

Save the Client Secret when you create the client. It is shown only once and cannot be retrieved later. Exchange the credentials for an access token via POST /oauth/token.

For the full token-exchange flow (including refresh handling), see the Authentication guide.

Step 2: Replace your auth headers

V1 (before)

The example below shows the user-specific V1 mode (x-api-key + x-user-api-key) with an explicit x-organization-code. If you were authenticating with x-api-key alone (organization-wide), simply drop the other two headers from the V1 request.

cURL

curl --request GET \
  --url "https://api.doppel.com/v1/alerts?queue_state=needs_confirmation" \
  --header "x-api-key: <YOUR_ORG_API_KEY>" \
  --header "x-user-api-key: <YOUR_USER_API_KEY>" \
  --header "x-organization-code: ACM"

Python

import requests

response = requests.get(
    "https://api.doppel.com/v1/alerts",
    headers={
        "x-api-key": "<YOUR_ORG_API_KEY>",
        "x-user-api-key": "<YOUR_USER_API_KEY>",
        "x-organization-code": "ACM",
    },
    params={"queue_state": "needs_confirmation"},
)

Node.js

const url = new URL("https://api.doppel.com/v1/alerts");
url.searchParams.set("queue_state", "needs_confirmation");

const response = await fetch(url, {
  headers: {
    "x-api-key": "<YOUR_ORG_API_KEY>",
    "x-user-api-key": "<YOUR_USER_API_KEY>",
    "x-organization-code": "ACM",
  },
});

V2 (after)

cURL

curl --request GET \
  --url "https://api.doppel.com/v2/alerts?queue_state=needs_confirmation" \
  --header "Authorization: Bearer <YOUR_ACCESS_TOKEN>"

Python

import requests

response = requests.get(
    "https://api.doppel.com/v2/alerts",
    headers={"Authorization": f"Bearer {access_token}"},
    params={"queue_state": "needs_confirmation"},
)

Node.js

const url = new URL("https://api.doppel.com/v2/alerts");
url.searchParams.set("queue_state", "needs_confirmation");

const response = await fetch(url, {
  headers: { Authorization: `Bearer ${access_token}` },
});

For this alert-list request, the query string, response shape, and pagination
behavior are identical to V1; only the auth headers and path prefix change.

Step 3: Handle token expiration

V2 access tokens expire after the expires_in window returned by POST /oauth/token (24 hours at the time of writing). Your client must refresh on 401 Unauthorized, or proactively before expiration. A typical pattern:

import time
import requests

_token = None
_token_expires_at = 0


def get_token() -> str:
    global _token, _token_expires_at
    if _token and time.time() < _token_expires_at - 60:
        return _token
    response = requests.post(
        "https://api.doppel.com/oauth/token",
        json={
            "client_id": CLIENT_ID,
            "client_secret": CLIENT_SECRET,
            "audience": "doppel-external",
            "grant_type": "client_credentials",
        },
    )
    response.raise_for_status()
    data = response.json()
    _token = data["access_token"]
    _token_expires_at = time.time() + data["expires_in"]
    return _token

Migration checklist

  • Have an organization admin or super admin create a Client ID and Client Secret in Doppel Vision API Settings.
  • Implement the OAuth token-exchange flow (see Authentication).
  • Replace x-api-key (and, if you were sending it, x-user-api-key) with Authorization: Bearer <token>.
  • Drop the x-organization-code header if you were sending one — V2 derives the organization from the token.
  • Confirm each route exists in V2, then change its /v1/ prefix to /v2/.
  • Add token-refresh handling on 401 Unauthorized.
  • If you call /v1/report* or /v1/reports, switch to /v2/alert* or /v2/alerts.
  • If you list or create protected assets, switch to /v2/assets and send
    asset_type.
  • Run your existing integration tests against /v2/ to confirm response shapes are unchanged.

Need help?

If you hit a difference between V1 and V2 that is not covered here, contact your Doppel representative — please include the request URL, the V1 vs V2 response, and any HTTP status codes you observed.


Did this page help you?