> ## Documentation Index
> Fetch the complete documentation index at: https://docs.openlayer.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Use the governance API

> Create frameworks and rules, attach evidence, and pull compliance status and audit-ready exports from Openlayer

Use the REST API to work with the compliance data shown in **Governance**, including frameworks,
requirements, rule results, and evidence. You can use this data in audit reports, internal dashboards,
or governance, risk, and compliance tools, and you can create and activate frameworks
programmatically.

## Authentication

Authenticate each request with a workspace API key:

```bash theme={null}
curl --request GET \
  --url https://api.openlayer.com/v1/projects \
  --header 'Authorization: Bearer <YOUR_API_KEY>'
```

See [Find your API key](https://docs.openlayer.com/workspace-and-projects/find-your-api-key.md) if you don't have one. Governance
list endpoints use a workspace ID. Each project returned by
[List projects](https://docs.openlayer.com/api-reference/rest/projects/list-projects.md) includes its `workspaceId`.

## Pull your compliance state

**1. List your frameworks**

Start with the frameworks in your workspace. Pass `enabled=true` to return only active
frameworks.

```bash theme={null}
curl --request GET \
  --url 'https://api.openlayer.com/v1/workspaces/<WORKSPACE_ID>/frameworks?enabled=true' \
  --header 'Authorization: Bearer <YOUR_API_KEY>'
```

Each framework includes an `id` that you use in subsequent requests. Its `projectSelector`
identifies the projects it covers.

See [List frameworks](https://docs.openlayer.com/api-reference/rest/governance/list-frameworks.md).

**2. Read workspace statistics**

Retrieve a compliance roll-up instead of counting rule results yourself. Add `frameworkId` to
limit the response to one framework or `projectId` to limit it to one project.

```bash theme={null}
curl --request GET \
  --url 'https://api.openlayer.com/v1/workspaces/<WORKSPACE_ID>/rule-stats?frameworkId=<FRAMEWORK_ID>' \
  --header 'Authorization: Bearer <YOUR_API_KEY>'
```

See [Retrieve workspace compliance statistics](https://docs.openlayer.com/api-reference/rest/governance/retrieve-rule-stats.md).

**3. Break down compliance by project**

Retrieve one row per project for a framework. The example sorts projects by the number of failing
rule results.

```bash theme={null}
curl --request GET \
  --url 'https://api.openlayer.com/v1/frameworks/<FRAMEWORK_ID>/project-rule-stats?sortColumn=totalFailing&asc=false' \
  --header 'Authorization: Bearer <YOUR_API_KEY>'
```

See [List a framework's per-project compliance](https://docs.openlayer.com/api-reference/rest/governance/list-project-rule-stats.md).

**4. Retrieve individual requirements**

A rule is one requirement. A rule result is that requirement's status for a project, or for the
workspace when `projectId` is `null`.

List rule results and filter them by framework, project, rule, or `status`:

```bash theme={null}
curl --request GET \
  --url 'https://api.openlayer.com/v1/workspaces/<WORKSPACE_ID>/rule-results?frameworkId=<FRAMEWORK_ID>&status=failing&perPage=100' \
  --header 'Authorization: Bearer <YOUR_API_KEY>'
```

A result's `status` is `running`, `passing`, `failing`, `skipped`, `error`, `pending`, or
`due_soon`. Its `statusMessage` provides a human-readable explanation, and its `ruleId` identifies
the associated rule.

You can also list rules with their results included:

```bash theme={null}
curl --request GET \
  --url 'https://api.openlayer.com/v1/workspaces/<WORKSPACE_ID>/rules?frameworkId=<FRAMEWORK_ID>&includeResults=true&perPage=100' \
  --header 'Authorization: Bearer <YOUR_API_KEY>'
```

See [List rule results](https://docs.openlayer.com/api-reference/rest/governance/list-rule-results.md) and
[List rules](https://docs.openlayer.com/api-reference/rest/governance/list-rules.md).

**5. Include framework document text**

A framework document contains the source standard's text, sections, subsections, and mapped rules.
List the documents first, then retrieve the document you need:

```bash theme={null}
curl --request GET \
  --url https://api.openlayer.com/v1/frameworks/<FRAMEWORK_ID>/documents \
  --header 'Authorization: Bearer <YOUR_API_KEY>'

curl --request GET \
  --url https://api.openlayer.com/v1/frameworks/<FRAMEWORK_ID>/documents/<DOCUMENT_ID> \
  --header 'Authorization: Bearer <YOUR_API_KEY>'
```

To retrieve the rules and statuses for a specific part of the document, use its section or
subsection endpoint with `includeResults=true`.

See [Retrieve a framework document](https://docs.openlayer.com/api-reference/rest/governance/retrieve-framework-document.md),
[List a section's rules](https://docs.openlayer.com/api-reference/rest/governance/list-section-rules.md), and
[List a subsection's rules](https://docs.openlayer.com/api-reference/rest/governance/list-subsection-rules.md).

**6. Collect supporting evidence**

For an evidence-based rule, retrieve the evidence attached to its rule result:

```bash theme={null}
curl --request GET \
  --url https://api.openlayer.com/v1/rule-results/<RULE_RESULT_ID>/evidence \
  --header 'Authorization: Bearer <YOUR_API_KEY>'
```

The evidence uses `storageUri` for an uploaded document, `text` for a written statement, or `url`
for a link, according to the rule's `evidenceType`.

See [List a rule result's evidence](https://docs.openlayer.com/api-reference/rest/governance/list-rule-result-evidence.md).

## Create and activate a framework

Openlayer ships with built-in frameworks such as the EU AI Act and ISO/IEC 42001, and you can add
your own. Both are managed through the API.

**1. Create a custom framework**

Create a framework to track compliance against an internal policy, or against a standard
Openlayer does not ship as a built-in framework. Only `name` is required:

```bash theme={null}
curl --request POST \
  --url https://api.openlayer.com/v1/workspaces/<WORKSPACE_ID>/frameworks \
  --header 'Authorization: Bearer <YOUR_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "Internal AI Policy",
    "description": "Our internal requirements for AI systems in production.",
    "enabled": true,
    "tags": ["internal", "policy"]
  }'
```

The response is the new framework, including the `id` you use in subsequent requests. A new
framework has no rules — add them from the Openlayer app.

Use `projectSelector.includeProjectIds` to choose existing projects. To include matching
projects created after you save the selector, set `applyToFutureProjects` to `true` and add
`match` criteria:

```json theme={null}
{
  "name": "High-risk systems policy",
  "projectSelector": {
    "includeProjectIds": ["<PROJECT_ID>"],
    "applyToFutureProjects": true,
    "match": [{ "property": "riskLevel", "value": ["high", "critical"] }]
  }
}
```

The included project IDs remain covered regardless of later property changes. Existing
projects not listed in `includeProjectIds` stay out, even when they match the criteria.
Set `applyToFutureProjects` to `false` to cover only the included projects. A response's
`matchProjectsCreatedAfter` value records the cutoff for future matches. The server resets
this cutoff whenever you send `includeProjectIds` and ignores any `matchProjectsCreatedAfter`
value you send, so the API accepts a framework response written back with this field unchanged.

> [!WARNING]
>
> To keep the current selection, omit `projectSelector` from the update. Sending it replaces
> the entire selector. A response's `includeProjectIds` contains only explicit picks, not
> projects that joined through `match`. Before writing the selector back, set
> `includeProjectIds` to the complete list of existing projects you want to keep, including
> those that joined through `match`; omitted projects are unpinned. If you omit
> `includeProjectIds` from the selector, stored picks and the cutoff are cleared, so `match`
> applies to every project.

See [Create a framework](https://docs.openlayer.com/api-reference/rest/governance/create-framework.md).

**2. Activate or deactivate a framework**

A framework only counts towards compliance while it is enabled. Rules of a disabled framework
are not evaluated. Activate one — built-in or custom — by setting `enabled`:

```bash theme={null}
curl --request PUT \
  --url https://api.openlayer.com/v1/frameworks/<FRAMEWORK_ID> \
  --header 'Authorization: Bearer <YOUR_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{"enabled": true}'
```

Only the fields you send are changed. You can also update `tags`, `projectSelector`,
`autoCreateTests`, `autoCreateTestRuleIds`, `name`, `avatar`, `href`, and
`extendedDescription`. When `autoCreateTests` is `true`, omit `autoCreateTestRuleIds` or set
it to `null` to use every eligible test-setup rule, or provide rule IDs to use a subset. An
empty list is not accepted.

> [!NOTE]
>
> Frameworks that ship with Openlayer report `immutable: true`. For those, only `enabled`,
> `tags`, `projectSelector`, `autoCreateTests`, and `autoCreateTestRuleIds` can be changed —
> their name and definition are managed by Openlayer.

See [Update a framework](https://docs.openlayer.com/api-reference/rest/governance/update-framework.md).

## Manage rules and evidence

A rule is one requirement. A rule result is that requirement's status for a project, or for the
workspace when `projectId` is `null`.

**1. Create a rule**

A rule's `type` decides how it is satisfied, and the two types accept different fields.

An **evidence** rule is satisfied by attaching evidence. Set `evidenceType` to the kind of
evidence that satisfies it, and optionally `renewalCadenceDays` to require periodic renewal:

```bash theme={null}
curl --request POST \
  --url https://api.openlayer.com/v1/workspaces/<WORKSPACE_ID>/rules \
  --header 'Authorization: Bearer <YOUR_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "Annual model risk review",
    "description": "Each high-risk project is reviewed and signed off once a year.",
    "scope": "project",
    "type": "evidence",
    "evidenceType": "document",
    "renewalCadenceDays": 365
  }'
```

A **platform** rule is evaluated automatically from the state of your workspace. Set
`automationType` to the signal to check. Its `scope` must be `project`, and `evidenceType` and
`renewalCadenceDays` must be omitted:

```json theme={null}
{
  "name": "Monitoring enabled",
  "scope": "project",
  "type": "platform",
  "automationType": "monitoring_mode_enabled"
}
```

`name`, `scope`, and `type` are required. A new rule belongs to no framework — map it to one
from the Openlayer app.

See [Create a rule](https://docs.openlayer.com/api-reference/rest/governance/create-rule.md).

**2. Update or delete a rule**

Only the fields you send are changed. A rule's `scope`, `type`, `evidenceType`, and automation
are fixed once it exists.

```bash theme={null}
curl --request PUT \
  --url https://api.openlayer.com/v1/rules/<RULE_ID> \
  --header 'Authorization: Bearer <YOUR_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{"deactivated": true, "assigneeId": "<USER_ID>"}'
```

Deleting a rule also deletes its rule results:

```bash theme={null}
curl --request DELETE \
  --url https://api.openlayer.com/v1/rules/<RULE_ID> \
  --header 'Authorization: Bearer <YOUR_API_KEY>'
```

> [!NOTE]
>
> Rules that ship with Openlayer report `immutable: true` and can be neither edited nor
> deleted. To exclude one from compliance, set `deactivated` on its rule result instead.

See [Update a rule](https://docs.openlayer.com/api-reference/rest/governance/update-rule.md) and
[Delete a rule](https://docs.openlayer.com/api-reference/rest/governance/delete-rule.md).

**3. Assign or exclude a rule result**

Assign an owner, or exclude a single result from compliance without deactivating the rule
everywhere. `deactivatedReason` is required when deactivating:

```bash theme={null}
curl --request PATCH \
  --url https://api.openlayer.com/v1/rule-results/<RULE_RESULT_ID> \
  --header 'Authorization: Bearer <YOUR_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "deactivated": true,
    "deactivatedReason": "Not applicable to this project."
  }'
```

A result's `status` is computed by Openlayer and cannot be set directly.

See [Update a rule result](https://docs.openlayer.com/api-reference/rest/governance/update-rule-result.md).

**4. Attach evidence**

Send the field that matches the rule's `evidenceType`: `text` for a written statement, `url`
for a link, or `storageUri` for an uploaded document.

```bash theme={null}
curl --request POST \
  --url https://api.openlayer.com/v1/rule-results/<RULE_RESULT_ID>/evidence \
  --header 'Authorization: Bearer <YOUR_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "2026 model risk review",
    "description": "Signed off by the risk committee.",
    "url": "https://example.com/reviews/2026-model-risk.pdf"
  }'
```

For a document, upload the file first with
[Create a presigned URL](https://docs.openlayer.com/api-reference/rest/development/presigned-url.md) and send the resulting
storage URI as `storageUri`.

Attaching evidence re-evaluates the rule result. If the rule sets `renewalCadenceDays`, the
renewal window restarts from this evidence.

See [Attach evidence to a rule result](https://docs.openlayer.com/api-reference/rest/governance/create-rule-result-evidence.md).

## Export an audit-ready archive

You can export a framework's evidence and progress as a zip archive. The archive contains uploaded
evidence files, a Markdown progress report, and CSV manifests of rules and evidence with SHA-256
checksums.

**1. Queue the export**

To export the workspace-wide view across every project in the framework, omit the request body:

```bash theme={null}
curl --request POST \
  --url https://api.openlayer.com/v1/frameworks/<FRAMEWORK_ID>/export \
  --header 'Authorization: Bearer <YOUR_API_KEY>'
```

To export one project, include its `projectId`:

```bash theme={null}
curl --request POST \
  --url https://api.openlayer.com/v1/frameworks/<FRAMEWORK_ID>/export \
  --header 'Authorization: Bearer <YOUR_API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{"projectId": "<PROJECT_ID>"}'
```

The API returns `202` with the path and ID of the background task:

```json theme={null}
{
  "taskResultUrl": "/v1/background-tasks/<TASK_ID>",
  "taskResultId": "<TASK_ID>"
}
```

Export requests are limited to two per minute for each framework. If an identical export is
already queued, the API returns that task instead of starting another one.

See [Export a framework](https://docs.openlayer.com/api-reference/rest/governance/export-framework.md).

**2. Wait for the archive**

Poll the background task using `taskResultId`:

```bash theme={null}
curl --request GET \
  --url https://api.openlayer.com/v1/background-tasks/<TASK_ID> \
  --header 'Authorization: Bearer <YOUR_API_KEY>'
```

Continue until `complete` is `true`. If `error` is not `null`, it explains why the task failed.
A completed export returns `outputs.storageUri` and also includes `filename`, `controlCount`,
`evidenceCount`, and `missingEvidenceCount`.

See [Retrieve a background task](https://docs.openlayer.com/api-reference/rest/background-tasks/retrieve-background-task.md).

**3. Download the archive**

Exchange `outputs.storageUri` for a short-lived download URL. Use URL encoding because a storage
URI contains reserved characters:

```bash theme={null}
curl --request GET \
  --get https://api.openlayer.com/v1/storage/presigned-url \
  --data-urlencode 'storageUri=<STORAGE_URI>' \
  --header 'Authorization: Bearer <YOUR_API_KEY>'
```

The response contains a `url`. Download it promptly:

```bash theme={null}
curl --location --output <FILENAME>.zip '<DOWNLOAD_URL>'
```

See [Retrieve a download URL](https://docs.openlayer.com/api-reference/rest/development/retrieve-download-url.md).

## Pagination

List endpoints accept `page` and `perPage`, with up to 100 items per page. Request successive pages
until a response contains fewer items than `perPage`.

> [!NOTE]
>
> Mapping a rule to a framework, and editing a framework's document text, are
> not yet part of the public API — do those in the Openlayer app. See [Set up a
> framework](https://docs.openlayer.com/governance/activate-framework.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.