Migrating from V1

Migrating from V1

The Doppel V2 API preserves the V1 path and request and response contract for
equivalent, non-deprecated endpoints. V2 uses a new authentication model.

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 must 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 bodies—Compatible for equivalent non-deprecated endpoints. V2 adds optional operations and fields.

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.

V2-only DRP capabilities

V2 adds these Digital Risk Protection capabilities:

  • Read one brand with GET /v2/brand.
  • Filter alert lists by brand, queue state, severity, entity state, and platform.
  • Update alert brand and assignee with PUT /v2/alert. See Update an alert.
  • Find alerts that share threat infrastructure. See Find related alerts.
  • List takedown requests and read one request with its activity. See Track takedown requests.
  • List, create, read, and update typed assets. See Manage assets.

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

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.

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.
  • 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?