REST API  v1

Developer Documentation

Integrate governance, risk and compliance data directly into your own tools. The VerityLayer REST API gives programmatic access to your organization's risks, vulnerabilities, assets, incidents, compliance evidence and more.

Introduction

The VerityLayer API is organized around REST. It uses resource-oriented URLs, accepts and returns JSON, and relies on standard HTTP verbs and response codes. Every request is scoped to a single organization and executed as a specific user, so responses only ever include data that user is permitted to see.

  • All requests must be made over HTTPS.
  • Request and response bodies are JSON (Content-Type: application/json).
  • Most resources follow a uniform pattern — list, read, create, update, delete — described under Resources.

Base URL

All endpoints are relative to the versioned base URL:

https://veritylayer.com/api/v1

Endpoint paths are appended directly, e.g. https://veritylayer.com/api/v1/risks.

Authentication

The API authenticates with an API key sent as a bearer token, plus a tenant header identifying your organization. Both headers are required on every request.

Required headers

HeaderValueDescription
AuthorizationBearer vl_ai_…Your secret API key.
X-VerityLayer-Tenantyour-org-slugYour organization slug. Must match the key's organization.

Getting a key

An organization administrator generates API keys inside the application under Settings → API Keys. Each key is tied to the organization and to the user who created it — API calls inherit exactly that user's module access and permissions.

Keep keys secret. A key is shown only once at creation. Treat it like a password: never embed it in client-side code or commit it to source control. If a key is exposed, revoke it in Settings and issue a new one.

Example

curl https://veritylayer.com/api/v1/risks \
  -H "Authorization: Bearer vl_ai_your_api_key_here" \
  -H "X-VerityLayer-Tenant: your-org-slug"

Making requests

The API maps HTTP verbs to actions on a resource:

VerbPathAction
GET/{resource}List records (paginated)
GET/{resource}/{id}Retrieve a single record
POST/{resource}Create a record
PUT/{resource}/{id}Update a record (PATCH also accepted)
DELETE/{resource}/{id}Delete a record

Send JSON bodies for POST, PUT and PATCH. Whether a given verb is available on a resource depends on your permissions; a verb you cannot use returns 403 or 404.

Pagination & filtering

List endpoints are paginated. Control the page and size with query parameters:

ParameterDefaultNotes
page11-based page number.
per_page25Records per page. Maximum 100.

Some resources also accept filter parameters that match a field to an allowed value — for example /risks?risk_category=Operational&treatment_status=In%20Progress. Unsupported or invalid filter values are ignored.

curl "https://veritylayer.com/api/v1/vulnerabilities?page=2&per_page=50" \
  -H "Authorization: Bearer vl_ai_your_api_key_here" \
  -H "X-VerityLayer-Tenant: your-org-slug"

Response format

Every response is a JSON object with a success boolean. The shape depends on the operation.

List

{
  "success": true,
  "page": 1,
  "per_page": 25,
  "count": 2,
  "data": [
    { "id": 41, "title": "Unpatched web server", "risk_category": "Technical", "treatment_status": "In Progress" },
    { "id": 42, "title": "Weak vendor access controls", "risk_category": "Operational", "treatment_status": "Not Started" }
  ]
}

Single record

{
  "success": true,
  "data": { "id": 41, "title": "Unpatched web server", "risk_category": "Technical" }
}

Create / update

Create returns 201 Created with the new record's primary key; update returns 200 with the key.

{ "success": true, "id": 43 }

Errors

Errors use standard HTTP status codes and return { "success": false, "error": "…" }.

StatusMeaningExample message
400Bad request — validation failedField 'title' is required
401Missing or invalid API keyInvalid or revoked API key
403Not permitted / tenant mismatchThe acting user does not have the "risk_register_create" permission
404Unknown resource or recordNot found
405Verb not supported for resourceThis resource does not support delete
500Server errorInternal server error

A 403 tells you exactly which permission or entitlement is missing. If a whole module is disabled for your organization you'll see "This module is not enabled for your organization" — enable it in the app, or ask an administrator.

Resources

These resources all follow the uniform pattern in Making requests. The available verbs on each are gated by your permissions.

ResourceDescriptionOperations
/risks Risk register entries GET, POST, PUT, DELETE
/vulnerabilities Tracked vulnerabilities GET, POST, PUT, DELETE
/assessments Project / security assessments GET, POST, PUT, DELETE
/assets Asset inventory GET, POST, PUT, DELETE
/incidents Security incidents GET, POST, PUT, DELETE
/changes Change-management records GET, POST, PUT, DELETE
/patches Patch-management records GET, POST, PUT, DELETE
/vendors Third-party vendors GET, POST, PUT, DELETE
/forms Custom forms GET, POST, PUT, DELETE
/evidence Compliance evidence items GET, POST, PUT, DELETE

Worked example — create a risk

POST /risks requires title, risk_category, likelihood and impact. Enum fields must use an allowed value (e.g. likelihood/impact are one of Very Low, Low, Medium, High, Very High).

curl -X POST https://veritylayer.com/api/v1/risks \
  -H "Authorization: Bearer vl_ai_your_api_key_here" \
  -H "X-VerityLayer-Tenant: your-org-slug" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Unpatched web server",
    "risk_category": "Technical",
    "likelihood": "High",
    "impact": "High",
    "treatment_status": "Not Started"
  }'

Compliance & policies

A few areas expose purpose-built endpoints in addition to the generic resources above.

VerbPathDescription
GET/compliance/frameworksList compliance frameworks
GET/compliance/frameworks/{code}List a framework's controls
PUT/compliance/frameworks/{code}/controls/{id}Update a control's status
POST/evidence/mapMap an evidence item to a control
GET/policiesList policy documents
GET/policies/{id}Read a policy document
POST/policiesCreate a policy document
PUT/policies/{id}Update a policy document
DELETE/policies/{id}Delete a policy document
POST/audit/exportGenerate a compliance audit export

Code samples

The same authenticated GET /risks request in several languages.

PHP

$ch = curl_init('https://veritylayer.com/api/v1/risks');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer vl_ai_your_api_key_here',
        'X-VerityLayer-Tenant: your-org-slug',
    ],
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($response['data']);

JavaScript (fetch)

const res = await fetch('https://veritylayer.com/api/v1/risks', {
  headers: {
    'Authorization': 'Bearer vl_ai_your_api_key_here',
    'X-VerityLayer-Tenant': 'your-org-slug',
  },
});
const body = await res.json();
console.log(body.data);

Python (requests)

import requests

res = requests.get(
    'https://veritylayer.com/api/v1/risks',
    headers={
        'Authorization': 'Bearer vl_ai_your_api_key_here',
        'X-VerityLayer-Tenant': 'your-org-slug',
    },
)
print(res.json()['data'])

Support

Need help integrating? Reach out through the contact page or the in-app support center. Include the endpoint, the HTTP status you received and the error message — but never share your API key.