openapi: 3.0.3
info:
title: Anecdotes API
version: 1.0.0
description: 'The Anecdotes API provides programmatic access to the Anecdotes GRC platform. Use it to manage frameworks,
requirements, risks, controls, policies, evidence, findings, and more.
Authentication is two-step: create an API key in the Anecdotes platform, exchange it at GET /identity/v1/apikey/exchange
for a short-lived JWT (1 hour), then send that JWT as `Authorization: Bearer <token>` on all other calls. A descriptive
User-Agent header is required.'
contact:
name: Anecdotes
url: https://help.anecdotes.ai/api/overview
email: hello@anecdotes.ai
servers:
- url: https://api.anecdotes.ai
description: Production
externalDocs:
description: Anecdotes API reference
url: https://help.anecdotes.ai/api/overview
security:
- Bearer: []
tags:
- name: Analysis Rules
description: '**Analysis rules** evaluate evidence table rows for **gaps or warnings**; configure query, scoping, and alert
levels, and read **execution results** per instance. [Analysis rules (product)](https://help.anecdotes.ai/product-tour/frameworks/evidence/evidence-monitoring/analysis-rules)'
- name: Create Controls
description: Create one or more **custom controls** in a framework.
- name: Create Evidence
description: Create custom **Evidence Collections**, **attach** JSON/CSV files to a collection, and upload **manual** evidence
of any type. Customer-pushed evidence can also carry **IPE** (Information Produced by Entity) — the structured queries
that produced the data — supplied inline (`evidence_api_query`) or as a JSON file (`ipe_file`) on create/attach, or added
later to an existing collection via the `/ipe` endpoint. IPE can only be written to API (customer-pushed) evidence.
- name: Custom Fields
description: '**Custom fields** extend platform resources (including **requirements**) with your own **dropdown**, **multi-select**,
or **free-text** values. These endpoints manage the field **definitions** — create one, list them, and read a single definition
to discover its **`field_metadata.values`** (the `{option_id: label}` map used when setting dropdown / multi-select values).
Field definitions are shared across resource types; scope a field to requirements with **`resource_types: ["REQUIREMENT"]`**.'
- name: Download Evidence
description: Download **raw** evidence payloads, processed **evidence tables**, combined full-or-raw streams, and latest
binary payloads.
- name: Findings
description: '**Findings** record compliance gaps and issues, including links to controls, evidence, and policies.'
- name: Framework
description: A **framework** in anecdotes is a compliance program built from a formally written standard or regulation (e.g.
ISO/IEC 27001, SOC 2, HIPAA, CSA STAR). It is organized into **control categories** and **control titles** with control
statements. **API:** list frameworks and export framework data. [Terminology](https://help.anecdotes.ai/product-tour/frameworks/anecdotes-terminology-and-framework-hierarchy)
- name: Policy Manager
description: '**Policy Manager** allows you to create, edit, and manage policies for your organization. List customer-owned
policies, library templates, policy versions, and configure approval cycles.'
- name: Read Controls
description: List all controls or fetch by framework or id.
- name: Read Evidence Metadata
description: List and retrieve **evidence definitions**, **instance metadata**, and multi-instance **run history**.
- name: Requirements
description: '**Requirements** tie **controls** to expected **evidence** and framework scoping. These endpoints cover listing
customer requirements, simple **create / read / update / delete** for a single requirement id (`requirement_…`), and reading
/ updating **custom field** values on requirements.'
- name: Risk
description: '**Risks** live in **risk registers** in Risk Manager: inherent/residual dimensions, treatment, custom fields,
and links to evidence. **API:** create, list (full), get, update. [Risk Manager](https://help.anecdotes.ai/product-tour/risk-manager)
· [Getting started](https://help.anecdotes.ai/product-tour/risk-manager/getting-started-risk-management)'
- name: Token
description: 'Exchange your **API key** for a **short-lived JWT** (1 hour). Send the JWT as `Authorization: Bearer <token>`
on all subsequent requests.'
- name: Update Control Metadata
description: Update or delete a **custom control**'s name, description, category, and implementation.
paths:
/analysis-rules/v1/analysis-rules:
get:
tags:
- Analysis Rules
summary: Get Analysis Rules
description: 'Gets analysis rules of the specified analysis rules ids if provided, otherwise get all analysis rules
instances.
Each rule includes its query definition, alert level, origin, active state, and account scoping configuration. The
list is a merge of global (library) rules and customer-specific rules, with customer overrides taking precedence.'
operationId: getAnalysisRules
responses:
'200':
description: List of analysis rule objects.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/AnalysisRuleModel'
'401':
description: Unauthorized - JWT is missing, invalid, or expired. Exchange a new API key for a fresh JWT.
'422':
description: Validation Error - The request body or parameters failed validation.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
post:
tags:
- Analysis Rules
summary: Create Analysis Rule
description: 'Creates a new custom analysis rule.
Define the rule query, alert level, and scoping to control how evidence data is analyzed. The rule will be applied
during subsequent evidence collection runs.'
operationId: createAnalysisRule
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateCustomAnalysisRuleModel'
responses:
'201':
description: Analysis rule created successfully.
content:
application/json:
schema:
$ref: '#/components/schemas/AnalysisRuleModel'
'401':
description: Unauthorized - JWT is missing, invalid, or expired. Exchange a new API key for a fresh JWT.
'422':
description: Validation Error - The request body or parameters failed validation.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
/analysis-rules/v1/analysis-rules/rule_results_by_filter:
get:
tags:
- Analysis Rules
summary: Get rules and their results
description: This endpoint returns a list of tuples of rules and evidence instances, including the results of the analysis.
operationId: getAnalysisRulesResults
parameters:
- name: rule_type
in: query
required: false
schema:
$ref: '#/components/schemas/AnalysisRuleType'
description: Filter by analysis rule type.
- name: rule_state
in: query
required: false
schema:
$ref: '#/components/schemas/AnalysisRuleActiveState'
description: Filter by whether the rule is active or not.
responses:
'200':
description: List of analysis rule result objects.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/AnalysisRuleResultModel'
'401':
description: Unauthorized - JWT is missing, invalid, or expired. Exchange a new API key for a fresh JWT.
'422':
description: Validation Error - The request body or parameters failed validation.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
/api/v1/framework:
get:
tags:
- Framework
summary: Get frameworks
description: 'Returns a JSON **array** of frameworks in the customer environment. Optional query parameters `limit`
and `offset` slice the result; the response body does **not** include a separate total-count or pagination envelope—only
the array of framework objects.
Each item includes its ID, name, folder, and metadata. See [Anecdotes terminology and framework hierarchy](https://help.anecdotes.ai/product-tour/frameworks/anecdotes-terminology-and-framework-hierarchy).'
operationId: getFrameworks
parameters:
- name: limit
in: query
schema:
type: integer
description: Maximum number of frameworks to return per page.
description: Maximum number of frameworks to return per page.
- name: offset
in: query
schema:
type: integer
description: Number of frameworks to skip (for pagination).
description: Number of frameworks to skip (for pagination).
responses:
'200':
description: Paginated list of framework objects.
content:
application/json:
schema:
type: array
items:
type: object
properties:
id:
type: string
description: Framework unique identifier
name:
type: string
description: Framework name
folder_id:
type: string
description: Parent folder ID
description:
type: string
description: Framework description
'401':
description: Unauthorized - JWT is missing, invalid, or expired. Exchange a new API key for a fresh JWT.
'422':
description: Validation Error - The request body or parameters failed validation.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
/api/v1/framework/{framework_id}/download:
get:
tags:
- Framework
summary: Export a framework
description: Exports a framework and its controls. Actual **Content-Type** depends on tenant/export configuration—typically
structured **JSON** or **CSV** text, or a downloadable file stream.
operationId: exportFramework
parameters:
- name: framework_id
in: path
required: true
schema:
type: string
description: The unique identifier of the framework to export.
description: The unique identifier of the framework to export.
responses:
'200':
description: Export payload. Set the `Accept` header according to your integration. The response may be JSON, CSV,
or a binary export.
content:
application/json:
schema:
type: object
description: Framework export when returned as JSON.
text/csv:
schema:
type: string
description: CSV export when returned as comma-separated text.
application/octet-stream:
schema:
type: string
format: binary
description: Binary file export when the platform returns a non-text artifact.
'401':
description: Unauthorized - JWT is missing, invalid, or expired. Exchange a new API key for a fresh JWT.
'422':
description: Validation Error - The request body or parameters failed validation.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
/api/v1/requirement:
get:
tags:
- Requirements
summary: Get all requirements
description: 'Returns requirement objects for the authenticated tenant. Use optional **`limit`** and **`offset`** to
page through the catalog (typical page sizes are in the hundreds).
The response is a **JSON array** of requirement objects, or in some gateways a wrapper object; clients should accept
either an **array** or an object containing a **`requirements`** array.
For one id and the fullest payload (for example **`requirement_scoping_overrides`**), use **`GET /api/v1/requirement/{requirement_id}`**.'
operationId: listRequirements
parameters:
- name: limit
in: query
required: false
schema:
type: integer
minimum: 1
description: Maximum number of requirements to return in this response.
description: Maximum number of requirements to return in this response.
- name: offset
in: query
required: false
schema:
type: integer
minimum: 0
description: Number of requirements to skip before returning results (pagination).
description: Number of requirements to skip before returning results (pagination).
responses:
'200':
description: Array of **`Requirement`** objects, or a wrapper with a **`requirements`** array.
content:
application/json:
schema:
oneOf:
- type: array
items:
$ref: '#/components/schemas/Requirement'
- type: object
properties:
requirements:
type: array
items:
$ref: '#/components/schemas/Requirement'
additionalProperties: true
'401':
description: Unauthorized — JWT is missing, invalid, or expired.
'422':
description: Validation error — the request failed validation.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
/api/v1/requirement/:
post:
tags:
- Requirements
summary: Create a custom requirement
description: 'Creates a new **custom** requirement. Link it to **controls** and **frameworks** with optional arrays
of prefixed ids (`control_…`, `framework_…`).
**201** response body is often the new **`requirement_id`** string; some responses return a full **`Requirement`**
object instead — clients should accept either.'
operationId: createRequirement
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RequirementCreateRequest'
responses:
'201':
description: Created — body may be the new **`requirement_*`** id string or a **`Requirement`** object.
content:
application/json:
schema:
oneOf:
- type: string
description: New requirement id
- $ref: '#/components/schemas/Requirement'
'401':
description: Unauthorized — JWT is missing, invalid, or expired.
'422':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
/api/v1/requirement/{requirement_id}:
get:
tags:
- Requirements
summary: Get requirement by id
description: Returns one requirement. The body may be a single **`Requirement`** object or a **one-element array** —
clients should accept both shapes.
operationId: getRequirementById
responses:
'200':
description: Requirement record.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Requirement'
- type: array
minItems: 1
maxItems: 1
items:
$ref: '#/components/schemas/Requirement'
'401':
description: Unauthorized — JWT is missing, invalid, or expired.
'404':
description: Requirement not found.
'422':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
/api/v1/requirement/{requirement_id}/:
delete:
tags:
- Requirements
summary: Delete a requirement
description: Deletes the requirement identified by **`requirement_id`**.
operationId: deleteRequirement
responses:
'200':
description: Requirement deleted.
'204':
description: Requirement deleted (no body).
'401':
description: Unauthorized — JWT is missing, invalid, or expired.
'404':
description: Requirement not found.
'422':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
patch:
tags:
- Requirements
summary: Update a requirement
description: 'Partial update for a single requirement. Wrap mutable fields under **`requirement`**. Optional **`context`**
(e.g. **`control_id`**) may be required for certain scoping updates.
Successful responses typically return **200** with the updated resource or an empty body depending on gateway version
— re-**GET** the requirement if you need a guaranteed full payload.'
operationId: updateRequirement
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RequirementUpdateRequestEnvelope'
responses:
'200':
description: Requirement updated.
'201':
description: Requirement updated (some gateways return **201**).
'401':
description: Unauthorized — JWT is missing, invalid, or expired.
'404':
description: Requirement not found.
'422':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
/api/v1/requirement/{requirement_id}/fields/{field_id}:
patch:
tags:
- Requirements
summary: Set a custom field value on a requirement
description: 'Sets (or clears) the value of one **custom field** on one requirement.
The **`value`** shape depends on the field type:
- **Free text** — a plain string, e.g. **`"True"`**.
- **Dropdown** — a single **option id** (a key of the field''s **`field_metadata.values`** map), e.g. **`"option_…"`**
— not the label.
- **Multi-select** — an **array** of option ids.
- Send **`null`** to clear the value.
To turn a desired label (e.g. `Sync-To-Archer` = `True`) into the option id to send, read the field definition via
**`GET /custom-fields/v1/fields/{field_id}`** and look up the matching entry in **`field_metadata.values`**.
Returns **204 No Content** on success.'
operationId: setRequirementCustomFieldValue
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RequirementCustomFieldValueUpdate'
responses:
'204':
description: Value set (no body).
'401':
description: Unauthorized — JWT is missing, invalid, or expired.
'500':
description: Internal server error, including when the **`field_id`** does not exist or **`value`** does not match
the field type (for example a list sent to a **dropdown** or **free-text** field). Verify the field id via **`GET
/custom-fields/v1/fields/{field_id}`** and send a value matching the field type.
/api/v1/requirements/fields:
get:
tags:
- Requirements
summary: Get all requirement custom field values
description: 'Returns every **custom field value** set on requirements for the authenticated tenant, as a nested map:
**`{ requirement_id: { field_id: { "value": … } } }`**.
Values are stored as raw **option ids** for **dropdown** / **multi-select** fields — resolve the human-readable label
with **`GET /custom-fields/v1/fields/{field_id}`** (see **`field_metadata.values`**) — and as plain strings for **free-text**
fields. Requirements with no value set are omitted; when nothing is set at all the body is an empty object **`{}`**.
There is **no server-side filter by value**. To find requirements where a field equals a specific value, read this
map and filter client-side. Note the path is **plural** (`requirements`), unlike the single-requirement endpoints
above.'
operationId: listRequirementCustomFieldValues
responses:
'200':
description: 'Nested map of requirement id → field id → **`{ "value": … }`**. Empty object when no values are set.'
content:
application/json:
schema:
$ref: '#/components/schemas/RequirementCustomFieldValues'
'401':
description: Unauthorized — JWT is missing, invalid, or expired.
'422':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
/compliance/v1/findings:
get:
tags:
- Findings
summary: Get all findings
description: Returns **`findings`** and **`pagination`**. Use **`limit`** and **`offset`** to page results.
operationId: listFindings
parameters:
- name: limit
in: query
required: false
schema:
type: integer
minimum: 1
description: Maximum number of findings to return in this response.
description: Maximum number of findings to return in this response.
- name: offset
in: query
required: false
schema:
type: integer
minimum: 0
description: Number of findings to skip before returning results (pagination).
description: Number of findings to skip before returning results (pagination).
responses:
'200':
description: Findings and pagination.
content:
application/json:
schema:
$ref: '#/components/schemas/FindingsListResponse'
'401':
description: Unauthorized.
'422':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
post:
tags:
- Findings
summary: Create finding
description: Creates a finding. Send **`multipart/form-data`** with **`finding_data`** as a JSON string of finding fields.
operationId: createFinding
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required:
- finding_data
properties:
finding_data:
type: string
description: JSON string of finding fields (e.g. `title`, `description`, `severity`, `status`, `linked_entities`).
responses:
'201':
description: Created finding.
content:
application/json:
schema:
$ref: '#/components/schemas/Finding'
'401':
description: Unauthorized.
'422':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
delete:
tags:
- Findings
summary: Delete findings
description: 'Deletes findings by internal **`id`**. Request body: **`ids`** array. Response: **`deleted_count`**.'
operationId: deleteFindings
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- ids
properties:
ids:
type: array
items:
type: string
description: Internal finding ids to delete.
responses:
'200':
description: Delete result.
content:
application/json:
schema:
$ref: '#/components/schemas/FindingsDeleteResponse'
'401':
description: Unauthorized.
'422':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
/compliance/v1/findings/{finding_id}:
get:
tags:
- Findings
summary: Get finding by id
description: Returns one finding by **`finding_id`**.
operationId: getFindingById
responses:
'200':
description: Finding record.
content:
application/json:
schema:
$ref: '#/components/schemas/Finding'
'401':
description: Unauthorized.
'404':
description: Finding not found.
'422':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
patch:
tags:
- Findings
summary: Update finding status
description: 'Updates a finding. Send fields to change (e.g. **`status`**: `Open`, `In progress`, `Resolved`).'
operationId: patchFinding
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
status:
type: string
description: Workflow status.
enum:
- Open
- In progress
- Resolved
additionalProperties: true
responses:
'200':
description: Updated finding.
content:
application/json:
schema:
$ref: '#/components/schemas/Finding'
'401':
description: Unauthorized.
'404':
description: Finding not found.
'422':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
/controls/control:
post:
tags:
- Create Controls
summary: Create custom control
description: Creates a **custom control** in the framework from query parameter **`control_framework`**. Send one object
or an array for bulk create; **201** returns the created record(s).
operationId: createCustomControl
parameters:
- name: control_framework
in: query
required: false
schema:
type: string
description: Framework id (`framework_…`) the new control belongs to.
description: Framework id (`framework_…`) the new control belongs to.
- name: notify
in: query
required: false
schema:
type: boolean
default: true
description: Whether to notify the platform UI of the change.
description: Whether to notify the platform UI of the change.
requestBody:
required: true
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/PostCustomControl'
- type: array
items:
$ref: '#/components/schemas/PostCustomControl'
responses:
'201':
description: Created control object, or array of created controls for bulk requests.
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Control'
- type: array
items:
$ref: '#/components/schemas/Control'
'400':
description: Invalid control payload.
'401':
description: Unauthorized — JWT is missing, invalid, or expired.
'422':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
get:
tags:
- Read Controls
summary: Get all controls
description: Returns every applicable control in the tenant as a JSON **array**. Auditor tokens are scoped to the active
audit's frameworks.
operationId: listControls
responses:
'200':
description: Array of control objects.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Control'
'401':
description: Unauthorized — JWT is missing, invalid, or expired.
'422':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
/controls/control/framework/{framework_id}:
get:
tags:
- Read Controls
summary: Get controls by framework
description: Returns all controls in **`framework_id`** as a JSON array.
operationId: getControlsByFramework
responses:
'200':
description: Array of control objects for the framework.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Control'
'401':
description: Unauthorized.
'403':
description: Forbidden — caller cannot access this framework.
/controls/control/read:
post:
tags:
- Read Controls
summary: Get controls by ids
description: Returns full control objects for **`controls_ids`** without listing the entire catalog.
operationId: getControlsByIds
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GetControlsBody'
responses:
'200':
description: Array of matching control objects.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Control'
'401':
description: Unauthorized.
'404':
description: One or more controls not found.
'422':
description: Validation error.
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
/controls/control/{control_id}:
get:
tags:
- Read Controls
summary: Get control by id
description: Returns one control by **`control_id`**. Returns **403** when the caller lacks framework access.
operationId: getControlById
responses:
'200':
description: Control object.
content:
application/json:
schema:
$ref: '#/components/schemas/Control'
'401':
description: Unauthorized — JWT is missing, invalid, or expired.
'403':
description: Forbidden — caller cannot access this control.
'404':
description: Control not found.
put:
tags:
- Update Control Metadata
summary: Update custom control
description: Updates name, description, category, implementation, and related-control links on a **custom control**.
operationId: updateCustomControl
requestBody:
# --- truncated at 32 KB (141 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/anecdotes/refs/heads/main/openapi/anecdotes-grc-openapi.yml
ⓘ
Where this information came from
This is an independent, third-party profile of Anecdotes GRC API, published by
API Evangelist. We do not operate, host, resell, or
support these APIs, and we are not affiliated with or endorsed by the company unless stated above.
Everything here is built from publicly available information — the company's own site,
developer portal, documentation, public repositories, and the specifications it publishes for public use.
Nothing is obtained by breaching a system, defeating an access control, or using credentials.
The Kin Score and Agent Readiness rating are independently calculated assessments of a company's
public API artifacts, scored against a published rubric. They are not certifications,
endorsements, security assessments, or audits.
Corrections, re-scores, and removal are free — no partnership or purchase required, and
you do not need to justify the request. A removed company is recorded as unrated, never scored
zero for having asked. Acknowledgement within one business day; removal within two.
info@apievangelist.com
·
Read the full data-sourcing policy →
On a security or compliance team? Put security in the subject line and
you will get a person, not a form — we will tell you exactly which public URLs this profile was built from.