openapi: 3.1.0
info:
version: 1.0.0
title: Doppel
description: APIs to interface with Doppel's core system for social engineering defense — Brand Protection
alerts, URL scanning, reports, protected assets, and Human Risk Management campaigns.
contact:
name: Doppel API Support
url: https://doppel.readme.io/
servers:
- url: https://api.doppel.com/v1
x-readme:
parameter-ordering:
- path
- header
- query
- body
- cookie
- form
paths:
/alert:
post:
description: 'Creates an alert for a specific entity (URL or phone number) within Doppel''s Brand
Protection product.
**Behavior:**
- If an alert already exists for the entity, the existing alert is returned (HTTP 200).
- If the alert exists but with a different brand than requested, returns HTTP 409.
- After creation, the alert is automatically processed through Doppel''s triage workflow.
- If `source` is provided, it must exactly match the "API value" field of an external source configured
in your organization''s settings in Doppel Vision.
**Returns HTTP 400 when:**
- `entity` is missing, not a valid URL, or not a valid phone number.
- `entity` is a protected asset (e.g. google.com).
- `tags` is not a list of non-empty strings.
- `source` does not match any configured external source for the organization.
- `files` contains more than 10 items, duplicate file names, or is missing `file_to_upload`.
'
summary: Create Alert
operationId: create_alert
tags:
- alerts
x-google-backend:
address: https://external-api-gateway-725058953679.us-west1.run.app
jwt_audience: https://external-api-gateway-725058953679.us-west1.run.app
path_translation: APPEND_PATH_TO_ADDRESS
deadline: 180
parameters:
- $ref: '#/components/parameters/XOrganizationCodeHeader'
- name: Content-Type
in: header
required: true
description: ''
schema:
type: string
enum:
- application/json
requestBody:
content:
application/json:
schema:
type: object
required:
- entity
properties:
entity:
type: string
description: URL or phone number to be alerted.
example: https://suspicious-site.example.com
brand:
type: string
description: The brand name to associate with the alert. Must match an active (non-archived)
brand in your organization. Case-insensitive.
example: Acme Corp
tags:
type: array
items:
type: string
description: 'Array of tag names to associate with the alert. Tags must already exist
for your organization or be global tags.
Tags that don''t exist will be silently ignored.
'
example:
- Credential Theft
- NSFW
- Malicious
- Spam
source:
type: string
description: Custom API source identifier configured in organization settings in Doppel
Vision. Must exactly match the "API value" field of the desired source.
example: slack-integration
files:
type: array
maxItems: 10
description: 'Optional list of files to upload with the alert. Each file must include
base64-encoded content. Maximum 10 files per request.
For Telco alerts, uploaded image files may also be used as the alert''s canonical
screenshot. If an uploaded Telco image is selected as the screenshot, Doppel stores
a separate screenshot copy for alert review and downstream enforcement workflows while
preserving the original Uploaded Files copy. Only upload image files that are appropriate
to display as alert evidence.'
items:
$ref: '#/components/schemas/FileInput'
required: true
responses:
'200':
description: Alert already exists
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/AlertCreatedResponse'
'201':
description: Submitted report successfully
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/AlertCreatedResponse'
'400':
description: Invalid input
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Brand not found or archived for this organization
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Alert already exists with a different brand
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/AlertCreatedResponse'
'429':
description: Rate limit exceeded
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
security:
- api_key: []
user_api_key: []
x-google-quota:
metricCosts:
create-alert-request: 1
get:
description: 'Retrieves the details of a single alert by its ID or entity value.
**You must provide exactly one of `id` or `entity`**. Providing neither or both returns HTTP 400.
Returns the full alert object including audit logs, tags, entity content, and a signed screenshot
URL (expires in 1 hour).
'
summary: Get Alert
operationId: get-alert
tags:
- alerts
x-google-backend:
address: https://external-api-gateway-725058953679.us-west1.run.app
jwt_audience: https://external-api-gateway-725058953679.us-west1.run.app
path_translation: APPEND_PATH_TO_ADDRESS
parameters:
- $ref: '#/components/parameters/XOrganizationCodeHeader'
- name: id
in: query
required: false
description: The alert ID (format ORG-1234). Mutually exclusive with `entity`.
example: ACM-1234
schema:
type: string
- name: entity
in: query
required: false
description: The URL, phone number, or email of the alert to retrieve. Mutually exclusive with
`id`.
example: https://suspicious-site.example.com
schema:
type: string
responses:
'200':
description: Alert successfully retrieved
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/AlertResponse'
'400':
description: Invalid input
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Alert not found
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate limit exceeded
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
security:
- api_key: []
user_api_key: []
x-google-quota:
metricCosts:
get-alert-request: 1
put:
description: 'Updates an alert''s information in Doppel''s system. Works across all modules.
**You must provide exactly one of `id` or `entity`** to identify the alert. At least one field
to update must be provided in the request body.
**Paired parameters:**
- `tag_action` and `tag_name` must both be provided together.
- `file_action` and `files` must both be provided together.
'
summary: Update Alert
operationId: update_alert
tags:
- alerts
x-google-backend:
address: https://external-api-gateway-725058953679.us-west1.run.app
jwt_audience: https://external-api-gateway-725058953679.us-west1.run.app
path_translation: APPEND_PATH_TO_ADDRESS
deadline: 30
parameters:
- $ref: '#/components/parameters/XOrganizationCodeHeader'
- name: Content-Type
in: header
required: true
description: ''
schema:
type: string
enum:
- application/json
- name: id
in: query
required: false
description: The alert ID (format ORG-1234). Mutually exclusive with `entity`.
example: ACM-1234
schema:
type: string
- name: entity
in: query
required: false
description: The URL, phone number, or email of the alert to update. Mutually exclusive with `id`.
example: https://suspicious-site.example.com
schema:
type: string
requestBody:
content:
application/json:
schema:
type: object
properties:
queue_state:
description: 'New queue state to update the alert with.
(Note: taken_down is equivalent to Resolved in the Doppel Vision App)
'
type: string
enum:
- doppel_review
- needs_confirmation
- actioned
- taken_down
- monitoring
- archived
example: actioned
entity_state:
$ref: '#/components/schemas/EntityState'
comment:
type: string
description: A new comment to add to the alert.
example: Confirmed phishing — proceeding with takedown.
tag_action:
$ref: '#/components/schemas/TagActionType'
tag_name:
type: string
description: Name of the tag to add or remove. Must be provided together with `tag_action`.
example: Credential Theft
file_action:
$ref: '#/components/schemas/FileActionType'
files:
type: array
maxItems: 10
description: 'List of files to upload or delete. Must be provided together with `file_action`.
Maximum 10 files per request. When file_action is "upload", each file must include
base64-encoded content in file_to_upload. When file_action is "delete", only file_name
is required.
For Telco alerts, uploaded image files may also be used as the alert''s canonical
screenshot. If an uploaded Telco image is selected as the screenshot, Doppel stores
a separate screenshot copy for alert review and downstream enforcement workflows while
preserving the original Uploaded Files copy. Deleting the uploaded-file copy does
not delete the canonical screenshot copy.'
items:
$ref: '#/components/schemas/FileInput'
description: 'Fields to update on the alert. At least one field is required.
`tag_action`/`tag_name` and `file_action`/`files` are paired — both in each pair must be provided
together.
'
responses:
'200':
description: Updated alert successfully
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/AlertResponse'
'400':
description: Invalid input
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Alert or tag not found
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate limit exceeded
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
security:
- api_key: []
user_api_key: []
x-google-quota:
metricCosts:
update-alert-request: 1
/alert/referrer:
post:
description: This endpoint submits referrer logs to Doppel for processing. These logs capture URLs
that direct visitors to a site and may help identify threats or suspicious activity. Submitting
a referrer log does not guarantee that an alert will be generated. Instead, the submitted URL
will be analyzed as part of Doppel's referrer log processing.
summary: Submit Referrer Logs
operationId: submit-referrer-logs
tags:
- alerts
x-google-backend:
address: https://external-api-gateway-725058953679.us-west1.run.app
jwt_audience: https://external-api-gateway-725058953679.us-west1.run.app
path_translation: APPEND_PATH_TO_ADDRESS
deadline: 30
security:
- api_key: []
user_api_key: []
parameters:
- $ref: '#/components/parameters/XOrganizationCodeHeader'
- name: Content-Type
in: header
required: true
description: ''
schema:
type: string
enum:
- application/json
requestBody:
content:
application/json:
schema:
type: object
required:
- referrer_url
properties:
referrer_url:
type: string
description: The referrer URL where the user came from (required). Must not be a known
protected asset for your organization.
example: https://suspicious-referrer.example.com/phish
destination_url:
type: string
description: The URL where the user navigated to (optional). If provided and not already
a known protected asset, it will be automatically added as a protected asset for your
organization.
example: https://your-company.com/login
description: Referrer log information to be submitted
required: true
x-google-quota:
metricCosts:
submit-referrer-logs-request: 1
responses:
'202':
description: Request accepted for processing - URL has been submitted for potential alert creation
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: Successful referrer log submission.
'400':
description: Bad request - missing required field, invalid URL format, or URL is a known internal
asset
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized - invalid or missing API key
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/alerts:
get:
description: 'Returns a paginated list of alerts across all modules, with support for filtering
and sorting.
**Sorting:** If `sort_type` is provided, `sort_order` must also be provided. If neither is provided,
defaults to `date_sourced` descending.
**Pagination:** Zero-indexed. Default page_size is 30, maximum is 200.
**Note:** In this endpoint''s response, the alert timestamp field is named `last_activity_timestamp`
(instead of `last_activity` as returned by GET /alert, PUT /alert, and POST /alert).
'
summary: Get Alerts
operationId: get-alerts
x-google-backend:
address: https://external-api-gateway-725058953679.us-west1.run.app
jwt_audience: https://external-api-gateway-725058953679.us-west1.run.app
path_translation: APPEND_PATH_TO_ADDRESS
deadline: 60
tags:
- alerts
parameters:
- $ref: '#/components/parameters/XOrganizationCodeHeader'
- name: search_key
in: query
description: Search alerts by URL. Currently only URL search is supported.
required: false
example: example.com
schema:
type: string
- $ref: '#/components/parameters/QueueStateFilter'
- $ref: '#/components/parameters/Product'
- name: created_before
in: query
description: Filter alerts created before this date (ISO 8601 format).
required: false
example: '2024-01-05T13:45:30'
schema:
type: string
format: date-time
- name: created_after
in: query
description: Filter alerts created after this date (ISO 8601 format).
required: false
example: '2024-01-01T00:00:00'
schema:
type: string
format: date-time
- name: last_activity_timestamp
in: query
description: Filter alerts with last activity at or after this date (ISO 8601 format).
required: false
example: '2024-01-05T13:45:30'
schema:
type: string
format: date-time
- $ref: '#/components/parameters/SortType'
- $ref: '#/components/parameters/SortOrder'
- name: page
in: query
description: Page number for pagination (zero-indexed). Defaults to 0.
required: false
schema:
type: integer
default: 0
- name: page_size
in: query
description: Number of alerts per page (default 30, max 200)
required: false
schema:
type: integer
minimum: 1
maximum: 200
default: 30
- name: tags
in: query
description: Comma-separated list of tag names to filter alerts by.
required: false
example: Credential Theft,Malicious
style: form
explode: false
schema:
type: array
items:
type: string
responses:
'200':
description: Successful operation
content:
application/json:
schema:
type: object
properties:
alerts:
type: array
items:
$ref: '#/components/schemas/AlertResponse'
metadata:
type: object
properties:
count:
type: integer
description: Total count of alerts
page:
type: integer
description: Current page number
total_pages:
type: integer
description: Total number of pages
page_size:
type: integer
description: Number of alerts per page
'400':
description: Invalid input
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
security:
- api_key: []
user_api_key: []
x-google-quota:
metricCosts:
get-alerts-request: 1
/brands:
get:
description: List active brands for the authenticated organization. Filter by brand_type (organization_brand
or personal_brand) and/or name, with pagination support. Only returns active brands (archived
brands are excluded).
summary: List Brands
operationId: list-brands
tags:
- brands
x-google-backend:
address: https://external-api-gateway-725058953679.us-west1.run.app
jwt_audience: https://external-api-gateway-725058953679.us-west1.run.app
path_translation: APPEND_PATH_TO_ADDRESS
parameters:
- $ref: '#/components/parameters/XOrganizationCodeHeader'
- name: brand_type
in: query
description: Filter by brand type (organization_brand or personal_brand)
required: false
schema:
type: string
enum:
- organization_brand
- personal_brand
- name: name
in: query
description: Search by brand name (case-insensitive contains)
required: false
schema:
type: string
- name: limit
in: query
description: Maximum number of results to return
required: false
schema:
type: integer
minimum: 1
maximum: 1000
default: 100
- name: offset
in: query
description: Number of results to skip for pagination
required: false
schema:
type: integer
minimum: 0
default: 0
responses:
'200':
description: Successfully retrieved brands
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/GetBrandResponse'
'400':
description: Invalid request parameters
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Invalid query parameter (e.g. out-of-range limit/offset, invalid brand_type)
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate limit exceeded
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
security:
- api_key: []
user_api_key: []
/brands/{brand_id}:
delete:
description: Delete (archive) a brand by ID. This soft-deletes the brand by setting its status to
archived, along with disabling related sourcing queries, trademarks, customer assets, and designated
takedown assets.
summary: Delete Brand
operationId: delete-brand
tags:
- brands
x-google-backend:
address: https://external-api-gateway-725058953679.us-west1.run.app
jwt_audience: https://external-api-gateway-725058953679.us-west1.run.app
path_translation: APPEND_PATH_TO_ADDRESS
parameters:
- $ref: '#/components/parameters/XOrganizationCodeHeader'
- name: brand_id
in: path
description: UUID of the brand to delete
required: true
schema:
type: string
format: uuid
responses:
'200':
description: Brand successfully deleted
headers: {}
content:
application/json:
schema:
type: object
properties:
id:
type: string
format: uuid
description: UUID of the deleted brand
'401':
description: Unauthorized
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden - insufficient permissions
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Brand not found
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'422':
description: Invalid request - malformed UUID in path
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate limit exceeded
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
headers: {}
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
security:
- api_key: []
user_api_key: []
/hrm/campaigns:
get:
description: List phishing simulation campaigns for the authenticated organization. Supports filtering
by status, campaign type, date range, and test flag. Returns paginated results.
summary: List Campaigns
operationId: list-hrm-campaigns
tags:
- hrm
x-google-backend:
address: https://external-api-gateway-725058953679.us-west1.run.app
jwt_audience: https://external-api-gateway-725058953679.us-west1.run.app
path_translation: APPEND_PATH_TO_ADDRESS
parameters:
- $ref: '#/components/parameters/XOrganizationCodeHeader'
- name: status
in: query
description: Filter by campaign status (e.g. pending, in_progress, finished)
schema:
type: string
- name: campaign_type
in: query
description: Filter by campaign type (e.g. simulation)
schema:
type: string
- name: launch_date_after
in: query
description: Filter campaigns launched after this ISO 8601 date
schema:
type: string
- name: launch_date_before
in: query
description: Filter campaigns launched before this ISO 8601 date
schema:
type: string
- name: is_test
in: query
description: Include test campaigns (defaults to false)
schema:
type: boolean
default: false
- name: sort_by
in: query
description: 'Sort field: launch_date, created_at, or name'
schema:
type: string
default: created_at
- name: sort_order
in: query
description: 'Sort order: asc or desc'
schema:
type: string
default: desc
- name: limit
in: query
description: Maximum number of results to return
schema:
type: integer
minimum: 1
maximum: 1000
default: 100
- name: offset
in: query
description: Number of results to skip for pagination
schema:
type: integer
minimum: 0
default: 0
responses:
'200':
description: List of campaigns
content:
application/json:
schema:
$ref: '#/components/schemas/ListCampaignsResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
security:
- api_key: []
user_api_key: []
/hrm/campaigns/{campaign_id}:
get:
description: Get a single phishing simulation campaign by ID for the authenticated organization.
summary: Get Campaign
operationId: get-hrm-campaign
tags:
- hrm
x-google-backend:
address: https://external-api-gateway-725058953679.us-west1.run.app
jwt_audience: https://external-api-gateway-725058953679.us-west1.run.app
path_translation: APPEND_PATH_TO_ADDRESS
parameters:
- $ref: '#/components/parameters/XOrganizationCodeHeader'
- name: campaign_id
in: path
required: true
description: Campaign ID
schema:
type: string
responses:
'200':
description: Campaign details
content:
application/json:
schema:
$ref: '#/components/schemas/HrmCampaignResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Campaign not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
security:
- api_
# --- truncated at 32 KB (111 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/doppel/refs/heads/main/openapi/doppel-openapi-original.yml