NAV
javascript

Introduction

Welcome to the Devici API

Quick Start

Download the Postman collection and environment to get started quickly:

Import both files into Postman, set your tokenId and tokenSecret in the environment, and run the Auth > Authenticate request to obtain a token. All subsequent requests use the token automatically.

Access to our endpoints is managed via scoped API tokens.

Scopes are the mechanism used to define and control the specific resources and actions an API token can utilize. When creating a token, you assign scopes (e.g., collections:read, users:write) to enforce the principle of least privilege.

Every endpoint requires a specific, corresponding scope. Any request made without the necessary scope will be immediately denied, ensuring robust access control across your collections, threat models, and other critical resources.

API Token Prerequisites and Management

To create or manage API tokens, you must meet the following criteria:

The generated token must be assigned to an active user who possesses the appropriate permissions relevant to the required API actions.

Token Expiration and Renewal

The API token is short-lived and expires after the time specified in the expires_in field (typically 1 hour).

Upon expiration, you must obtain a new API token by re-initiating the authentication flow via the /auth endpoint.

Security Constraints

API Token Scopes

API tokens use a scope-based permission system to control access to resources. Each scope consists of a resource and a permission level.

Permissions

Permission Description
read Read access - view and retrieve data
write Write access - create, update, and delete data

Resources

Scopes can be assigned to various resources in the system. Common resources include:

Scope Validation

When making API requests:

Authentication

To authorize, use this code:

import axios from "axios";
axios.defaults.baseURL = "https://api.devici.com/api/v1/";

const response = await axios.post("/auth", {
  clientId: "{{TOKEN_ID}}",
  secret: "{{TOKEN_SECRET}}",
});

The above command returns JSON structured like this:

{
  "access_token": "{{access_token}}",
  "expires_in": 3600,
  "token_type": "Bearer"
}
const { token_type, access_token } = response.data;

axios.defaults.headers.common = {
  Authorization: `${token_type} ${access_token}`,
};

Devici uses API Tokens to allow access to the API. You can register a new Devici API token at our app.

TOKEN_ID = YOUR_TOKEN_ID
TOKEN_SECRET = YOUR_TOKEN_SECRET

Get token

POST https://api.devici.com/api/v1/auth

For the following requests, use this header:

Authorization: {{token_type}} {{access_token}}

Roles

Get Roles

To get All Roles use this code:

axios.get("/roles");
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: public, max-age=86400, stale-while-revalidate=600
ETag: {{ETag}}
Last-Modified: Thu, 11 Sep 2025 00:00:00 GMT
{
  "version": "2025-09-11-1",
  "updatedAt": "2025-09-11T00:00:00Z",
  "roles": [
    {
      "key": "user",
      "description": "Access to the content only; limited by permissions.",
      "name": "User"
    },
    {
      "key": "admin",
      "description": "Access to the content only; limited by scopes.",
      "name": "Admin"
    },
    {
      "key": "super_admin",
      "description": "Full access except payments and branding.",
      "name": "Super-admin"
    },
    {
      "key": "owner",
      "description": "Account owner; full control.",
      "name": "Owner"
    }
  ]
}

This endpoint retrieves the complete list of available roles and a version identifier. Use this endpoint to fetch the initial catalog or to get an updated version when your local cache is stale. See the Caching & Change Detection section for details on revalidation.

owner - The account creator. An account can have only one owner. The owner has unrestricted access to all resources and functionality without limitations.

super-admin have full access to all resources without requiring specific scopes or permissions.

admin require granular scope assignments.

HTTP Request

GET https://api.devici.com/api/v1/roles

Check for Role List Changes

To Check for Role List Changes use this code:

axios.head("/roles");
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: public, max-age=86400, stale-while-revalidate=600
ETag: {{ETag}}
Last-Modified: Thu, 11 Sep 2025 00:00:00 GMT

(No response body)

This endpoint with method HEAD returns only the response headers (without a body). This is useful for checking if the resource has been updated by examining key headers, such as ETag or Last-Modified, allowing for efficient caching and avoiding the transfer of unnecessary data.

HTTP Request

HEAD https://api.devici.com/api/v1/roles

Caching & Change Detection

Example Request

axios.get("/roles", {
  headers: {
    "If-None-Match": "{{ETag}}",
    "If-Modified-Since": Thu, 11 Sep 2025 00:00:00 GMT,
  },
});
HTTP/1.1 304 Not Modified

(No response body)

To improve performance, clients are strongly encouraged to cache the roles response. The server provides ETag and Last-Modified headers to facilitate this.

Revalidating with Headers

When you make a subsequent GET request, include the appropriate headers to ask the server if the resource has changed.

If-None-Match (Preferred): This is the primary method for revalidation. Use the ETag value from your cached response.

If-Modified-Since (Fallback): Use the Last-Modified date from your cached response. Note: The value must be a valid HTTP-date string, not the version string.

If your cached version is still current, the server will respond with 304 Not Modified and an empty body. This signals that you should continue to use your cached copy. If the data has changed, you will receive a standard 200 OK response with the new data.

HTTP Request

HEAD https://api.devici.com/api/v1/roles

Headers

Key Value Description
If-None-Match {{ETag}} This is the method for revalidation.
If-Modified-Since Thu, 11 Sep 2025 00:00:00 GMT Fallback Method.

Users

Get Users

To get All Users use this code:

axios.get("/users/?limit=20&page=0");
{
  "items": [
    {
      "id": "{{user_id}}",
      "role": "owner",
      "first_name": "First",
      "last_name": "Last",
      "email": "{{user_email}}",
      "status": "confirmed",
      "is_enabled": true
    },
    {
      "id": "{{user_id}}",
      "role": "user",
      "first_name": "First",
      "last_name": "Last",
      "email": "{{user_email}}",
      "status": "confirmed",
      "is_enabled": true
    },
    {
      "id": "{{user_id}}",
      "role": "super_admin",
      "first_name": "First",
      "last_name": "Last",
      "email": "{{user_email}}",
      "status": "confirmed",
      "is_enabled": true
    },
    {
      "id": "{{user_id}}",
      "role": "admin",
      "first_name": "First",
      "last_name": "Last",
      "email": "{{user_email}}",
      "status": "confirmed",
      "is_enabled": true,
      "scopes": [
        { "resource": "users", "permission": "read" },
        { "resource": "users", "permission": "write" },
      ]
    },
  ],
  "count": 4
}

This endpoint retrieves Users.

HTTP Request

GET https://api.devici.com/api/v1/users/?limit=20&page=0

Query Parameters

Parameter Default Description
limit 20 Count of items per request
page 1 Page

Get a Specific User

To get specific user use this code:

axios.get("/users/:id");

The above command returns JSON structured like this:

{
  "id": "{{user_id}}",
  "role": "user",
  "first_name": "First",
  "last_name": "Last",
  "email": "{{user_email}}",
  "avatar_uploaded_at": "2025-03-11T09:29:23.072Z",
  "avatarUrl": "{{img_url}}"
}

When receiving a user with the admin role:

{
  "id": "{{user_id}}",
  "role": "admin",
  "first_name": "First",
  "last_name": "Last",
  "email": "{{user_email}}",
  "status": "confirmed",
  "is_enabled": true,
  "scopes": [
    { "resource": "users", "permission": "read" },
    { "resource": "users", "permission": "write" },
  ]
},

This endpoint retrieves a specific user.

HTTP Request

GET https://api.devici.com/api/v1/users/:id

Search Users

To search users use this code:

axios.get("/users/search/?field=email&text=johndoe@mail.com");

The above command returns JSON structured like this:

[
  {
    "id": "{{user_id}}",
    "created_at": "2025-02-10T14:26:04.248Z",
    "updated_at": "2025-03-11T09:29:23.081Z",
    "email": "johndoe@mail.com",
    "first_name": "John",
    "last_name": "Doe",
    "is_active": true,
    "role": "user"
  },
  {
    "id": "{{user_id}}",
    "created_at": "2025-02-10T14:26:04.248Z",
    "updated_at": "2025-03-11T09:29:23.081Z",
    "email": "johndoe+2@mail.com",
    "first_name": "First",
    "last_name": "Last",
    "role": "admin",
    "is_enabled": true,
    "scopes": [
      { "resource": "users", "permission": "read" },
      { "resource": "users", "permission": "write" },
    ]
  }
]

This endpoint retrieves a users.

HTTP Request

GET https://api.devici.com/api/v1/users/search/?field=email&text=johndoe@mail.com

Query Parameters

Parameter Description
field must be on of first_name, last_name, email
text must be string

Admin Scopes

Catalog of scope resources, permissions, and presets for assigning admin scopes to users. Requires Enterprise tier and Public API authentication (client credentials).

Get Resources Catalog

To get the list of scope resources use this code:

axios.get("/users/admin-scopes/resources", {
  headers: {
    "Authorization": "Bearer {{ACCESS_TOKEN}}"
  }
});
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: public, max-age=86400, stale-while-revalidate=600
ETag: {{ETag}}
Last-Modified: Thu, 11 Sep 2025 00:00:00 GMT
{
  "version": "2026-01-15-1",
  "updatedAt": "2026-01-15T00:00:00Z",
  "resources": [
    {
      "key": "users",
      "description": "Users management",
      "name": "Users",
      "readOnly": false,
      "writeOnly": false
    },
    {
      "key": "users-operations",
      "description": "User operations (invite, enable/disable, change role)",
      "name": "Users-operations",
      "readOnly": false,
      "writeOnly": false
    },
    {
      "key": "teams",
      "description": "Teams management",
      "name": "Teams",
      "readOnly": false,
      "writeOnly": false
    },
    {
      "key": "roles",
      "description": "Roles information",
      "name": "Roles",
      "readOnly": true,
      "writeOnly": false
    },
    {
      "key": "codex",
      "description": "Codex resources (threats, attributes, mitigations)",
      "name": "Codex",
      "readOnly": false,
      "writeOnly": false
    },
    {
      "key": "dashboard",
      "description": "Dashboard data and chart types",
      "name": "Dashboard",
      "readOnly": true,
      "writeOnly": false
    },
    {
      "key": "reports",
      "description": "Reports",
      "name": "Reports",
      "readOnly": true,
      "writeOnly": false
    },
    {
      "key": "report-export",
      "description": "Export reports (PDF, CSV)",
      "name": "Report-export",
      "readOnly": true,
      "writeOnly": false
    },
    {
      "key": "audit-logs",
      "description": "Audit logs",
      "name": "Audit-logs",
      "readOnly": true,
      "writeOnly": false
    },
    {
      "key": "audit-log-export",
      "description": "Export audit logs (CSV)",
      "name": "Audit-log-export",
      "readOnly": true,
      "writeOnly": false
    },
    {
      "key": "categories",
      "description": "Categories management",
      "name": "Categories",
      "readOnly": false,
      "writeOnly": false
    },
    {
      "key": "app-integrations",
      "description": "App integrations (Jira, Azure DevOps, etc.)",
      "name": "App-integrations",
      "readOnly": true,
      "writeOnly": false
    },
    {
      "key": "workflows",
      "description": "Workflows management",
      "name": "Workflows",
      "readOnly": false,
      "writeOnly": false
    },
    {
      "key": "api-tokens",
      "description": "API tokens management (view and manage personal tokens)",
      "name": "Api-tokens",
      "readOnly": false,
      "writeOnly": false
    }
  ]
}

Returns the list of scope resources that can be assigned to admin users, including their readOnly and writeOnly flags. Use this endpoint to fetch the initial catalog or to get an updated version when your local cache is stale. See the Caching & Change Detection section below for details on revalidation.

HTTP Request

GET https://api.devici.com/api/v1/users/admin-scopes/resources

Get Permissions Catalog

To get the list of permissions use this code:

axios.get("/users/admin-scopes/permissions", {
  headers: {
    "Authorization": "Bearer {{ACCESS_TOKEN}}"
  }
});
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: public, max-age=86400, stale-while-revalidate=600
ETag: {{ETag}}
Last-Modified: Thu, 11 Sep 2025 00:00:00 GMT
{
  "version": "2025-02-11-1",
  "updatedAt": "2025-02-11T00:00:00Z",
  "permissions": [
    {
      "key": "read",
      "description": "Read access - view and retrieve data",
      "name": "Read"
    },
    {
      "key": "write",
      "description": "Write access - create, update, and delete data",
      "name": "Write"
    }
  ]
}

Returns the list of permissions (e.g. read, write) used in scope assignment. Use this endpoint to fetch the initial catalog or to get an updated version when your local cache is stale. See the Caching & Change Detection section below for details on revalidation.

HTTP Request

GET https://api.devici.com/api/v1/users/admin-scopes/permissions

Get Presets Catalog

To get the list of scope presets use this code:

axios.get("/users/admin-scopes/presets", {
  headers: {
    "Authorization": "Bearer {{ACCESS_TOKEN}}"
  }
});
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: public, max-age=86400, stale-while-revalidate=600
ETag: {{ETag}}
Last-Modified: Thu, 11 Sep 2025 00:00:00 GMT
{
  "version": "2026-01-15-1",
  "updatedAt": "2026-01-15T00:00:00Z",
  "presets": [
    {
      "key": "full-access",
      "description": "Full access to all admin resources.",
      "name": "Full-access",
      "scopes": [
        { "resource": "users", "permission": "read" },
        { "resource": "users", "permission": "write" },
        { "resource": "users-operations", "permission": "read" },
        { "resource": "users-operations", "permission": "write" },
        { "resource": "teams", "permission": "read" },
        { "resource": "teams", "permission": "write" },
        { "resource": "roles", "permission": "read" },
        { "resource": "codex", "permission": "read" },
        { "resource": "codex", "permission": "write" },
        { "resource": "dashboard", "permission": "read" },
        { "resource": "reports", "permission": "read" },
        { "resource": "report-export", "permission": "read" },
        { "resource": "audit-logs", "permission": "read" },
        { "resource": "audit-log-export", "permission": "read" },
        { "resource": "categories", "permission": "read" },
        { "resource": "categories", "permission": "write" },
        { "resource": "app-integrations", "permission": "read" },
        { "resource": "workflows", "permission": "read" },
        { "resource": "workflows", "permission": "write" },
        { "resource": "api-tokens", "permission": "read" },
        { "resource": "api-tokens", "permission": "write" }
      ]
    },
    {
      "key": "users-management",
      "description": "Manage users, and teams.",
      "name": "Users-management",
      "scopes": [
        { "resource": "users", "permission": "read" },
        { "resource": "users", "permission": "write" },
        { "resource": "users-operations", "permission": "read" },
        { "resource": "users-operations", "permission": "write" },
        { "resource": "teams", "permission": "read" },
        { "resource": "teams", "permission": "write" },
        { "resource": "roles", "permission": "read" }
      ]
    },
    {
      "key": "codex",
      "description": "Full access to codex management.",
      "name": "Codex",
      "scopes": [
        { "resource": "codex", "permission": "read" },
        { "resource": "codex", "permission": "write" }
      ]
    },
    {
      "key": "analytics",
      "description": "Access to dashboard and reports.",
      "name": "Analytics",
      "scopes": [
        { "resource": "dashboard", "permission": "read" },
        { "resource": "reports", "permission": "read" },
        { "resource": "report-export", "permission": "read" }
      ]
    },
    {
      "key": "audit-logs",
      "description": "View and export audit logs.",
      "name": "Audit-logs",
      "scopes": [
        { "resource": "audit-logs", "permission": "read" },
        { "resource": "audit-log-export", "permission": "read" }
      ]
    },
    {
      "key": "admin-settings",
      "description": "Manage categories, integrations, and workflows.",
      "name": "Admin-settings",
      "scopes": [
        { "resource": "categories", "permission": "read" },
        { "resource": "categories", "permission": "write" },
        { "resource": "app-integrations", "permission": "read" },
        { "resource": "workflows", "permission": "read" },
        { "resource": "workflows", "permission": "write" }
      ]
    }
  ]
}

Returns the list of scope presets (e.g. full-access, users-management, codex, analytics, audit-logs, admin-settings) with their included scopes. Each preset has key, description, name, and scopes (array of { resource, permission }). Use this endpoint to fetch the initial catalog or to get an updated version when your local cache is stale. See the Caching & Change Detection section below for details on revalidation.

HTTP Request

GET https://api.devici.com/api/v1/users/admin-scopes/presets

Check for Admin Scopes catalog changes

Each of the three catalog endpoints supports HEAD for change detection. Use this to check if the resource has been updated without transferring the full response body.

Example: check if the resources catalog has changed

axios.head("/users/admin-scopes/resources", {
  headers: {
    "Authorization": "Bearer {{ACCESS_TOKEN}}"
  }
});
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: public, max-age=86400, stale-while-revalidate=600
ETag: {{ETag}}
Last-Modified: Thu, 11 Sep 2025 00:00:00 GMT

(No response body)

This endpoint returns only the response headers (without a body). Examine ETag or Last-Modified to see if your cached copy is still current.

HTTP Request

Catalog HEAD endpoint
Resources HEAD https://api.devici.com/api/v1/users/admin-scopes/resources
Permissions HEAD https://api.devici.com/api/v1/users/admin-scopes/permissions
Presets HEAD https://api.devici.com/api/v1/users/admin-scopes/presets

Caching & Change Detection (Admin Scopes)

Example: revalidate the resources catalog with conditional headers

axios.get("/users/admin-scopes/resources", {
  headers: {
    "Authorization": "Bearer {{ACCESS_TOKEN}}",
    "If-None-Match": "{{ETag}}",
    "If-Modified-Since": "Thu, 11 Sep 2025 00:00:00 GMT"
  }
});
HTTP/1.1 304 Not Modified

(No response body)

To improve performance, cache admin scopes catalog responses. The server returns ETag and Last-Modified on each catalog GET. The same behavior applies to all three endpoints: resources, permissions, and presets.

Revalidating with headers

On a subsequent GET, send the appropriate headers to ask if the resource has changed:

If the catalog is unchanged, the server responds with 304 Not Modified and no body; keep using your cached copy. If it has changed, you get 200 OK with the new data.

Headers

Key Value Description
If-None-Match {{ETag}} Preferred method for revalidation.
If-Modified-Since Thu, 11 Sep 2025 00:00:00 GMT Fallback method.

Bulk invite users

To send invitations to multiple users use this code:

axios.post("/users/bulk-invite", {
  payload: [
    {
      email: "johndoe@mail.com",
      firstName: "John",
      lastName: "Doe",
      role: "user"
    }
  ]
});

// bulk invite including a user with role "admin" (scopes required per admin)
axios.post("/users/bulk-invite", {
  payload: [
    {
      email: "johndoe@mail.com",
      firstName: "John",
      lastName: "Doe",
      role: "user"
    },
    {
      email: "jane@email.com",
      firstName: "Jane",
      lastName: "Admin",
      role: "admin",
      scopes: [
        { resource: "roles", permission: "read" },
        { resource: "users", permission: "read" },
        { resource: "users", permission: "write" },
        { resource: "users-operations", permission: "read" },
        { resource: "users-operations", permission: "write" }
      ]
    }
  ]
});

The above command returns JSON structured like this:

[
  {
    "id": "{{user_id}}",
    "email": "johndoe@mail.com",
    "first_name": "John",
    "last_name": "Doe",
    "role": "user",
    "is_enabled": true,
    "status": "invited",
    "created_at": "2025-02-10T14:26:04.248Z"
  }
]

Use this endpoint to send invitations to multiple users at once.

role field can be one of admin | user | super_admin, default is user.

HTTP Request

POST https://api.devici.com/api/v1/users/bulk-invite

Invite specific user

To invite specific user use this code:

axios.post("/users/invite", {
  email: "johndoe@mail.com",
  firstName: "John",
  lastName: "Doe",
  role: "user"
});

// invite user with role "admin"
axios.post("/users/invite", {
  email: "jane@email.com",
  firstName: "Jane",
  lastName: "Admin",
  role: "admin",
  scopes: [
    { resource: "roles", permission: "read" }
    { resource: "users", permission: "read" },
    { resource: "users", permission: "write" },
    { resource: "users-operations", permission: "read" },
    { resource: "users-operations", permission: "write" },
  ]
})

The above command returns JSON structured like this:

{
  "id": "{{user_id}}",
  "email": "johndoe@mail.com",
  "first_name": "John",
  "last_name": "Doe",
  "role": "user",
  "is_enabled": true,
  "status": "invited",
  "created_at": "2025-02-10T14:26:04.248Z",
}

Use this endpoint to invite specific user

role field can be one of admin | user | super_admin, default is user.

HTTP Request

POST https://api.devici.com/api/v1/users/invite

Bulk re-invite users

To resend invitations to multiple users use this code:

axios.post("/users/bulk-re-invite", {
  emails: ["johndoe@mail.com"]
});

The above command returns JSON structured like this:

[
  {
    "id": "{{user_id}}",
    "email": "johndoe@mail.com",
    "first_name": "John",
    "last_name": "Doe",
    "role": "user",
    "is_enabled": true,
    "status": "invited",
    "created_at": "2025-02-10T14:26:04.248Z",
  }
]

Use this endpoint to resend invitations to multiple users who have not yet accepted or whose invitations have expired.

HTTP Request

POST https://api.devici.com/api/v1/users/bulk-re-invite

Re-invite specific user

To re-invite specific user use this code:

axios.post("/users/re-invite", {
  email: "johndoe@mail.com",
  firstName: "John",
  lastName: "Doe",
  role: "user"
});

The above command returns JSON structured like this:

{
  "id": "{{user_id}}",
  "email": "johndoe@mail.com",
  "first_name": "John",
  "last_name": "Doe",
  "role": "user",
  "is_enabled": true,
  "status": "invited",
  "created_at": "2025-02-10T14:26:04.248Z",
}

Use this endpoint to re-invite a user who has not yet accepted the invitation or whose invitation has expired.

HTTP Request

POST https://api.devici.com/api/v1/users/re-invite

Bulk enable users

To enable multiple user accounts use this code:

axios.post("/users/bulk-enable", {
  ids: ["{{user_id}}", "{{user_id}}"]
});

Use this endpoint to enable multiple user accounts at once.

HTTP Request

POST https://api.devici.com/api/v1/users/bulk-enable

Enable specific user

To enable specific user account use this code:

axios.post("/users/enable/{{user_id}}");

Use this endpoint to enable specific user account.

HTTP Request

POST https://api.devici.com/api/v1/users/enable/{{userId}}

Bulk disable users

To disable multiple user accounts use this code:

axios.post("/users/bulk-disable", {
  ids: ["{{user_id}}", "{{user_id}}"]
});

Use this endpoint to disable multiple user accounts at once.

HTTP Request

POST https://api.devici.com/api/v1/users/bulk-disable

Disable specific users

To disable specific user account use this code:

axios.post("/users/disable/{{user_id}}");

Use this endpoint to disable specific user account.

HTTP Request

POST https://api.devici.com/api/v1/users/disable/{{user_id}}

Bulk change role for users

To update the roles of multiple users use this code:

axios.post("/users/bulk-change-role", {
  payload: [
    {
      id: "{{user_id}}",
      role: "user"
    }
  ]
});

The above command returns JSON structured like this:

[
  {
    "id": "{{user_id}}",
    "email": "johndoe@mail.com",
    "first_name": "John",
    "last_name": "Doe",
    "role": "user",
  }
]

Use this endpoint to update the roles of multiple users in one request.

role field can be one of admin | user | super_admin, default is user

HTTP Request

POST https://api.devici.com/api/v1/users/bulk-change-role

Change role for specific user

To update the role for specific user use this code:

axios.post("/users/change-role", {
  id: "{{user_id}}",
  role: "user"
});

// change role to "admin"
axios.post("/users/change-role", {
  id: "{{user_id}}",
  role: "admin",
  scopes: [
    { resource: "roles", permission: "read" }
    { resource: "users", permission: "read" },
  ]
});

The above command returns JSON structured like this:

{
  "id": "{{user_id}}",
  "email": "johndoe@mail.com",
  "first_name": "John",
  "last_name": "Doe",
  "role": "user",
}

Use this endpoint to update the role for specific user.

role field can be one of admin | user | super_admin, default is user.

HTTP Request

POST https://api.devici.com/api/v1/users/change-role

Import users

To import users use this code:

axios.post("/users/bulk-import", {
  payload: [
    {
      firstName: "John",
      lastName: "Doe",
      email: "johndoe@mail.com",
      role: "user"
    }
  ]
});

The above command returns JSON structured like this:

[
  {
    "id": "{{user_id}}",
    "email": "johndoe@mail.com",
  }
]

Use this endpoint to import users by providing their details in bulk.

role field can be one of admin | user | super_admin, default is user

HTTP Request

POST https://api.devici.com/api/v1/users/bulk-import

Delete Specific User

To delete specific user use this code:

axios.delete("/users/:id/:recipientId");

This endpoint deletes a specific user.

HTTP Request

DELETE https://api.devici.com/api/v1/users/:id/:recipientId

Params

Parameter Description
:id ID of the user to be deleted
:recipientId ID of the user will inherit the collections of the user being deleted

Collections

Get All Collections

To get all collections use this code:

axios.get("/collections");

The above command returns JSON structured like this:

{
  "items": [
    {
      "id": "{{collection_id}}",
      "created_at": "2024-03-28T11:12:06.960Z",
      "updated_at": "2024-03-28T11:12:06.960Z",
      "title": "Default collection",
      "description": null,
      "color": null,
      "created_by": {
        "id": "{{owner_id}}"
      }
    },
    {
      "id": "{{collection_id}}",
      "created_at": "2024-05-05T20:17:34.201Z",
      "updated_at": "2024-05-05T20:17:34.201Z",
      "title": "Test collection",
      "description": null,
      "color": null,
      "created_by": {
        "id": "{{owner_id}}"
      }
    }
  ],
  "count": 2
}

This endpoint retrieves collections. By default only active (non-archived) collections are returned.

HTTP Request

GET https://api.devici.com/api/v1/collections

Query Parameters

Parameter Default Description
limit 20 Count of items per request
page 1 Page
sort created_at Order by created at
order ASC Sort by ASC
activeOnly — When true, returns only active (non-archived) collections (default behaviour)
archivedOnly — When true, returns only archived collections. If both activeOnly and archivedOnly are true, defaults to active only.

Get a Specific Collection

To get specific collection use this code:

axios.get("/collections/:id");

The above command returns JSON structured like this:

{
  "id": "{{collection_id}}",
  "created_at": "2024-03-28T11:12:06.960Z",
  "updated_at": "2024-03-28T11:12:06.960Z",
  "title": "Default collection",
  "description": null,
  "color": null,
  "created_by": {
    "id": "{{owner_id}}"
  }
}

This endpoint retrieves a specific collection.

HTTP Request

GET https://api.devici.com/api/v1/collections/:id

Create Collection

To create collection use this code:

axios.post("/collections", {
  title: "New Collection from Public API",
  description: "This Collection created form public api",
  threatModelsData: [
    {
      title: "Threat model",
      description: "this is the Threat model desctiption",
      canvasData: [
        {
          nodes: [],
          edges: [],
          title: "Canvas title",
        },
      ],
    },
  ],
});

This endpoint create a specific collection.

HTTP Request

POST https://api.devici.com/api/v1/collections

Update a Specific Collection

To update specific collection use this code:

axios.patch("/collections/:id", {
  title: "New Title",
  description: "New description",
  color: "#ffffff",
});

This endpoint update a specific collection.

HTTP Request

PATCH https://api.devici.com/api/v1/collections/:id

Get Users with granted access to a specific Collection

To get users who have access to a specific collection use this code:

axios.get("/collections/users-access/{{collection_id}}");

The above command returns JSON structured like this:

[
  {
    "id": "{{user_id}}",
    "email": "johndoe@mail.com",
    "first_name": "John",
    "last_name": "Doe"
    "permission": "read"
  },
  ...
]

Use this endpoint to retrieve all users who have been granted access to a specific collection.

HTTP Request

GET https://api.devici.com/api/v1/collections/users-access/{{collection_id}}

Bulk Grant Users Access

To bulk grant access to multiple users for one or more collections, use this code:

axios.post("/collections/users-access/bulk-grant", {
  payload: [
    {
      collectionId: "{{collection_id}}",
      usersPermissions: [
        {
          userId: "{{user_id}}",
          permission: "read"
        },
        {
          userId: "{{user_id}}",
          permission: "write"
        }
      ]
    }
  ]
});

Use this endpoint to grant access to multiple users for one or more collections in bulk

permission field must be one of read | write | manage

HTTP Request

POST https://api.devici.com/api/v1/collections/users-access/bulk-grant

Grant User Access

To grant access to a specific collection to one or more users, use this code:

axios.post("/collections/users-access/grant", {
  collectionId: "{{collection_id}}",
  usersPermissions: [
    {
      userId: "{{user_id}}",
      permission: "read"
    },
    {
      userId: "{{user_id}}",
      permission: "write"
    }
  ]
});

Use this endpoint to grant access to specific collection

permission field must be one of read | write | manage

HTTP Request

POST https://api.devici.com/api/v1/collections/users-access/grant

Bulk Revoke Users Access

To bulk revoke access for multiple users from one or more collections, use this code:

axios.post("/collections/users-access/bulk-revoke", {
  payload: [
    {
      collectionId: "{{collection_id}}",
      usersIds: ["user_id", "user_id"]
    }
  ]
});

Use this endpoint to revoke access for multiple users from one or more collections in bulk.

HTTP Request

POST https://api.devici.com/api/v1/collections/users-access/bulk-revoke

Revoke User Access

To revoke access to a specific collection from one or more users, use this code:

axios.post("/collections/users-access/revoke", {
  collectionId: "{{collection_id}}",
  usersIds: ["user_id", "user_id"]
});

Use this endpoint to revoke access to a specific collection

HTTP Request

POST https://api.devici.com/api/v1/collections/users-access/revoke

Get Teams with granted access to a specific Collection

To get teams that have been granted access to a specific collection use this code:

axios.get("/collections/teams-access/{{collection_id}}");

The above command returns JSON structured like this:

[
  {
    "id": "{{team_id}}",
    "title": "Alpha",
    "users": [
      {
        "id": "{{user_id}}",
        "email": "johndoe@mail.com",
        "first_name": "John",
        "last_name": "Doe"
      }
    ],
    "permission": "read"
  },
  ...
]

Use this endpoint to retrieve all teams that have been granted access to a specific collection.

HTTP Request

GET https://api.devici.com/api/v1/collections/teams-access/{{collection_id}}

Bulk Grant Teams Access

To grant access to multiple teams for one or more collections, use this code:

axios.post("/collections/teams-access/bulk-grant", {
  payload: [
    {
      collectionId: "{{collection_id}}",
      teamsPermissions: [
        {
          teamId: "{{team_id}}",
          permission: "read"
        },
        {
          teamId: "{{team_id}}",
          permission: "write"
        }
      ]
    }
  ]
});

Use this endpoint to grant access to multiple teams for one or more collections in bulk.

permission field must be one of read | write | manage

HTTP Request

POST https://api.devici.com/api/v1/collections/teams-access/bulk-grant

Grant Team Access

To grant access to multiple teams for specific collection, use this code:

axios.post("/collections/teams-access/grant", {
  collectionId: "{{collection_id}}",
  teamsPermissions: [
    {
      teamId: "{{team_id}}",
      permission: "read"
    },
    {
      teamId: "{{team_id}}",
      permission: "write"
    }
  ]
});

Use this endpoint to grant access to multiple teams for specific collection.

permission field must be one of read | write | manage

HTTP Request

POST https://api.devici.com/api/v1/collections/teams-access/grant

Bulk Revoke Teams Access

To revoke access for multiple teams from one or more collections, use this code:

axios.post("/collections/teams-access/bulk-revoke", {
  payload: [
    {
      collectionId: "{{collection_id}}",
      teamsIds: ["team_id", "team_id"]
    }
  ]
});

Use this endpoint to revoke access for multiple teams from one or more collections in bulk.

HTTP Request

POST https://api.devici.com/api/v1/collections/teams-access/bulk-revoke

Revoke Teams Access

To revoke access for multiple teams from specific collection, use this code:

axios.post("/collections/teams-access/revoke", {
  collectionId: "{{collection_id}}",
  teamsIds: ["team_id", "team_id"]
});

Use this endpoint to revoke access for multiple teams from specific collection.

HTTP Request

POST https://api.devici.com/api/v1/collections/teams-access/revoke

Delete a Specific Collection

To delete specific collection use this code:

axios.delete("/collections/:id");

This endpoint deletes a specific collection.

HTTP Request

DELETE https://api.devici.com/api/v1/collections/:id

Threat Models

Get All Threat Models

To get all Threat Models use this code:

axios.get("/threat-models");

The above command returns JSON structured like this:

{
  "items": [
    {
      "id": "{{threat_model_id}}",
      "created_at": "2024-05-08T16:27:08.765Z",
      "updated_at": "2024-05-10T07:51:01.753Z",
      "title": "Last created tm",
      "description": "hello",
      "status": "Threats & Mitigations",
      "priority": "medium",
      "due_to_date": null,
      "retro_completed_at": null,
      "time_invested": null,
      "quality_of_model": null,
      "when_to_revisit": null,
      "archived_at": null,
      "owner": {
        "id": "{{owner_id}}",
        "email": "owner.i@mail.com",
        "first_name": "Temirlan",
        "last_name": "sdf"
      },
      "collection": {
        "id": "{{collection_id}}",
        "title": "Hello22"
      },
      "tags": [
        { "id": "{{tag_id}}", "title": "compliance", "color": "#004EAD" }
      ]
    },
    {
      "id": "{{threat_model_id}}",
      "created_at": "2024-05-06T09:33:03.817Z",
      "updated_at": "2024-05-06T09:33:03.817Z",
      "title": "hello one",
      "description": "test",
      "status": "Representation",
      "priority": "medium",
      "due_to_date": null,
      "retro_completed_at": null,
      "time_invested": null,
      "quality_of_model": null,
      "when_to_revisit": null,
      "archived_at": null,
      "owner": {
        "id": "{{owner_id}}",
        "email": "owner.i@mail.com",
        "first_name": "Temirlan",
        "last_name": "sdf"
      },
      "collection": {
        "id": "{{collection_id}}",
        "title": "New Title 222"
      },
      "tags": []
    }
  ],
  "count": 2
}

This endpoint retrieves all threat models.

HTTP Request

GET https://api.devici.com/api/v1/threat-models

Query Parameters

Parameter Default Description
limit 20 Count of items per request
page 1 Page
sort created_at Order by created at
order ASC Sort by ASC
include_archived false Include archived Threat Models
tagsIds Optional. Filter to threat models having any of the supplied tag IDs.

Get All Threat Models by Collection

To get all Threat Models by Collection id use this code:

axios.get("/threat-models/collection/:collectionId");

The above command returns JSON structured like this:

{
  "items": [
    {
      "id": "{{threat_model_id}}",
      "created_at": "2024-05-08T16:27:08.765Z",
      "updated_at": "2024-05-10T07:51:01.753Z",
      "title": "Draft Threat Model",
      "description": "hello",
      "status": "Threats & Mitigations",
      "priority": "medium",
      "due_to_date": null,
      "retro_completed_at": null,
      "time_invested": null,
      "quality_of_model": null,
      "when_to_revisit": null,
      "archived_at": null,
      "owner": {
        "id": "{{owner_id}}",
        "email": "owner.i@mail.com",
        "first_name": "Temirlan",
        "last_name": "sdf"
      },
      "canvases": [
        { "id": "{{canvas_id}}" },
        { "id": "{{canvas_id}}" }
      ],
      "collection": {
        "id": "{{collection_id}}",
        "title": "Collection title",
        "description": null,
        "color": null,
        "type": "default"
      },
      "tags": [
        { "id": "{{tag_id}}", "title": "compliance", "color": "#004EAD" }
      ]
    },
    {
      "id": "{{threat_model_id}}",
      "created_at": "2024-05-06T09:33:03.817Z",
      "updated_at": "2024-05-06T09:33:03.817Z",
      "title": "Draft Threat Model 2",
      "description": "description",
      "status": "Representation",
      "priority": "medium",
      "due_to_date": null,
      "retro_completed_at": null,
      "time_invested": null,
      "quality_of_model": null,
      "when_to_revisit": null,
      "archived_at": null,
      "owner": {
        "id": "{{owner_id}}",
        "email": "owner.i@mail.com",
        "first_name": "Temirlan",
        "last_name": "sdf"
      },
            "canvases": [
        { "id": "{{canvas_id}}" },
        { "id": "{{canvas_id}}" }
      ],
      "collection": {
        "id": "{{collection_id}}",
        "title": "Collection title",
        "description": null,
        "color": null,
        "type": "default"
      },
      "tags": []
    }
  ],
  "count": 2
}

This endpoint retrieves all threat models that belong to provided collection.

HTTP Request

GET https://api.devici.com/api/v1/threat-models/collection/:collectionId

Query Parameters

Parameter Default Description
limit 20 Count of items per request
page 1 Page
sort created_at Order by created at
order ASC Sort by ASC
include_archived false Include archived Threat Models

Get a Specific Threat Model

To get specific threat model use this code:

axios.get("/threat-models/:id");

The above command returns JSON structured like this:

{
  "id": "{{threat_model_id}}",
  "title": "hello one",
  "description": "test",
  "status": "Representation",
  "priority": "medium",
  "due_to_date": null,
  "retro_completed_at": null,
  "time_invested": null,
  "quality_of_model": null,
  "when_to_revisit": null,
  "owner": {
    "id": "{{owner_id}}"
  },
  "canvases": [],
  "tags": [
    { "id": "{{tag_id}}", "title": "compliance", "color": "#004EAD" }
  ]
}

This endpoint retrieves a specific threat model.

HTTP Request

GET https://api.devici.com/api/v1/threat-models/:id

Create Threat Model

To create threat model use this code:

axios.post("/threat-models", {
  title: "New Threat Model",
  description: "This Threat model created form public api",
  collectionId: "{{collection-id}}",
  canvasData: [{ title: "New Canvas", nodes: [], edges: [] }],
});

This endpoint create a specific threat model.

HTTP Request

POST https://api.devici.com/api/v1/threat-models

Create Many Threat Models

To create many threat models use this code:

axios.post("/threat-models/many", {
  collectionId: "{{collection-id}}",
  threatModelsData: [
    {
      title: "New First Threat Model",
      description: "This Threat model created form public api",
      canvasData: [{ title: "New Canvas", nodes: [], edges: [] }],
    },
    {
      title: "New Second Threat Model",
      description: "This Threat model created form public api",
      canvasData: [{ title: "New Canvas", nodes: [], edges: [] }],
    },
  ],
});

This endpoint create a many threat models.

HTTP Request

POST https://api.devici.com/api/v1/threat-models/many

Update a Specific Threat Model

To update specific threat model use this code:

axios.patch("/threat-models/:id", {
  title: "New Title",
  description: "New description",
  status: "new status",
  priority: "new priority",
  due_to_date: "due_to_date",
  time_invested: 1,
  quality_of_model: 1,
  when_to_revisit: 1,
  source_threats_methodologies: ["{{methodology_id_1}}"],
  include_custom_codex: true,
  tagsIds: ["{{tag_id_1}}", "{{tag_id_2}}"],
});

This endpoint updates a specific threat model.

Body Parameters

Parameter Type Description
title string Optional. New title.
description string Optional. New description.
status string Optional. New status.
priority string Optional. New priority.
due_to_date string Optional. ISO due date.
time_invested number Optional. Hours invested (1-100).
quality_of_model number Optional. Quality of model (1-10).
when_to_revisit number Optional. Revisit cadence (1-3).
source_threats_methodologies string[] Optional. Override flow — methodology UUIDs that restrict which threats Devici auto-syncs onto components when attributes are assigned. Discover valid IDs via GET /codex/built-in/threats/catalog. Empty array clears the filter (auto-sync all methodologies). Omit to leave unchanged. Unknown IDs return 400 Methodology <id> not found. Affects future attribute assignments only — threats already on components are not retroactively pruned.
include_custom_codex boolean Optional. Override flow — when true, the auto-sync also includes threats defined in your organisation's custom codex (in addition to any built-in methodologies set above); when false, the custom codex is excluded. Omit to leave unchanged.
tagsIds string[] Optional. Override flow — replaces the threat model's tag list with exactly the supplied IDs. Empty array clears all tags. Omit the field to leave tags unchanged. All IDs must belong to the caller's customer.

HTTP Request

PATCH https://api.devici.com/api/v1/threat-models/:id

Response shape

GET / PATCH responses surface methodology data in an enriched form:

{
  "id": "...",
  "title": "...",
  "source_threats_methodologies": [
    {"id": "9b...", "title": "STRIDE"}
  ],
  "include_custom_codex": false,
  "tags": [],
  "canvases": ["..."]
}

The source_threats_methodologies array contains the methodology entities currently scoping auto-sync. An empty array means auto-sync is unrestricted (all methodologies). The include_custom_codex boolean reflects whether the customer's custom codex is also included.

Common methodology / custom-codex patterns

Both source_threats_methodologies and include_custom_codex use override semantics — whatever value you send replaces the current value entirely. There is no merge.

Goal PATCH body
Set a single methodology {"source_threats_methodologies": ["<stride_id>"]}
Set multiple methodologies {"source_threats_methodologies": ["<stride_id>", "<linddun_id>"]}
Add a methodology to the current list First GET /threat-models/:id, read the existing IDs from source_threats_methodologies[].id, append the new one, then PATCH with the merged array. Sending only the new ID replaces the current list — STRIDE will be dropped.
Replace one methodology with another {"source_threats_methodologies": ["<new_id>"]} — the old ones are dropped
Clear the methodology filter only (keep custom codex as is) {"source_threats_methodologies": []}
Clear ALL framing (no methodologies, no custom codex) {"source_threats_methodologies": [], "include_custom_codex": false}
Toggle custom codex on/off without touching methodologies {"include_custom_codex": true} or {"include_custom_codex": false}

Affects future attribute assignments only — threats already on components are not retroactively pruned when the methodology filter changes.

Delete a Specific Threat Model

To delete specific threat model use this code:

axios.delete("/threat-models/:id");

This endpoint deletes a specific threat model.

HTTP Request

DELETE https://api.devici.com/api/v1/threat-models/:id

Export a PDF Report

To export a specific threat model PDF report, use this code:

axios.get("/threat-models/report/:id/canvas/:canvasId");

This endpoint exports a specific threat model PDF report.

HTTP Request

GET https://api.devici.com/api/v1/threat-models/report/:threatModelId/canvas/:canvasId

Export an Image

To export a specific canvas as an image, use this code:

axios.get("/threat-models/image/:canvasId");

This endpoint exports a specific canvas as an image.

HTTP Request

GET https://api.devici.com/api/v1/threat-models/image/:canvasId

Export a Neo4j

To export a specific canvas in Neo4j JSON format, use this code:

axios.get("/threat-models/neo4j/:canvasId");

The result will be json with the following data:

{
    "nodes": [
        {
            "id": "{{component_id}}",
            "labels": [
                "Process"
            ],
            "properties": {
                "color": "#00BFFF",
                "size": 3,
                "type": "processNode"
            }
        },
        {
            "id": "{{component_id}}",
            "labels": [
                "Process"
            ],
            "properties": {
                "color": "#00BFFF",
                "size": 3,
                "type": "processNode"
            }
        }
    ],
    "relationships": [
        {
            "id": "{{component_id}}",
            "type": "Dataflow",
            "start": "{{component_id}}",
            "end": "{{component_id}}",
            "properties": {
                "color": "#6F767E"
            }
        }
    ]
}

This endpoint exports a specific canvas in Neo4j JSON format.

HTTP Request

GET https://api.devici.com/api/v1/threat-models/neo4j/:canvasId

Export an OTM

To export a specific threat model in OTM format.

To export a specific threat model in OTM format, use this code:

axios.get("/threat-models/otm/:id");

In response, a JSON file with the following fields will be received:

{
    "parentProjectId": "{{parent_collection_id}}",
    "otmVersion": "0.2.0",
    "project": {
        "name": "Draft threat model",
        "id": "{{project_id}}",
        "description": null,
        "owner": "Tom End",
        "ownerContact": "tom.e@gmail.com",
        "tags": [],
        "attributes": null
    },
    "representations": [
        {
            "name": "Canvas 1",
            "id": "{{canvas_id}}",
            "type": "diagram",
            "size": null,
            "attributes": null
        }
    ],
    "assets": [],
    "components": [
        {
            "representationId": "{{canvas_id}}",
            "name": "Process",
            "id": "{{component_id}}",
            "description": "",
            "metaData": {
                "user": {
                    "id": "{{user_id}}",
                    "role": "admin",
                    "email": "tom.e@gmail.com",
                    "tierData": {
                        "tier": "business",
                        "seats": {
                            "limit": 5,
                            "available": 3,
                            "isSeatsLimitExceeded": false
                        },
                        "codeGenius": {
                            "limit": 100,
                            "available": 100
                        },
                        "isBetaUser": false,
                        "billingPeriod": "year"
                    },
                    "last_name": "Tom",
                    "first_name": "End",
                    "productFruitsHash": "{{product_fruits_hash}}",
                    "isOnboardingCompleted": true
                },
                "label": "Process",
                "selectedBy": [],
                "representation": "{{component_id}}"
            },
            "parent": {
                "trustZone": "{{component_id}}"
            },
            "type": "processNode",
            "tags": [],
            "representations": [
                {
                    "representation": "{{canvas_id}}",
                    "id": "{{component_id}}",
                    "position": {
                        "x": -72.6225961538461,
                        "y": 665.6923076923076
                    },
                    "size": {
                        "width": -1,
                        "height": -1
                    },
                    "positionAbsolute": {
                        "x": -72.6225961538461,
                        "y": 661.8461538461538
                    }
                }
            ],
            "assets": null,
            "threats": [],
            "attributes": {}
        }
    ],
    "dataflows": [
        {
            "name": "Dataflow",
            "id": "{{dataflow_id}}",
            "bidirectional": false,
            "source": "{{component_id}}",
            "destination": "{{component_id}}",
            "metaData": {
                "color": "#6F767E",
                "label": "Dataflow",
                "points": [],
                "fontSize": 12,
                "algorithm": "linear",
                "fontColor": "#ffffff",
                "textStyle": {
                    "isBold": false
                },
                "markerType": "end",
                "selectedBy": [],
                "representation": "{{component_id}}"
            },
            "tags": null,
            "assets": null,
            "representations": null,
            "threats": [],
            "attributes": {},
            "sourceHandle": "sourceRight",
            "targetHandle": "sourceLeft",
            "type": "default",
            "markerEnd": {
                "type": "arrowclosed",
                "color": "#6F767E"
            }
        }
    ],
    "trustZones": [],
    "threats": [],
    "mitigations": []
}

HTTP Request

GET https://api.devici.com/api/v1/threat-models/otm/:id

Import an OTM

To import OTM for creating the threat model, use this code:

axios.post("/threat-models/otm/:collectionId");

The following result will be received:

{
  "id": "{{threat_model_id}}"
}

This endpoint imports an OTM file for creating a threat model in a specific collection.

HTTP Request

POST https://api.devici.com/api/v1/threat-models/otm/:collectionId

Tags

Tags are organization-level labels (scoped per customer) that you can attach to threat models, codex attributes, codex threats, and codex mitigations. Every tag belongs to exactly one customer; the API only ever returns and mutates tags owned by the caller's customer.

List Tags

To list tags use this code:

axios.get("/tags");

The above command returns JSON structured like this:

{
  "items": [
    {
      "id": "{{tag_id}}",
      "title": "compliance",
      "color": "#004EAD",
      "created_at": "2026-04-15T12:00:00.000Z"
    }
  ],
  "count": 1
}

This endpoint retrieves all tags belonging to the caller's customer.

HTTP Request

GET https://api.devici.com/api/v1/tags

Query Parameters

Parameter Default Description
limit 20 Items per page (max 100)
page 0 Page number (0-based)
order ASC Sort direction by title (ASC or DESC)
text Optional case-insensitive substring filter on title

Get a Specific Tag

To fetch a single tag use this code:

axios.get("/tags/:id");

The above command returns JSON structured like this:

{
  "id": "{{tag_id}}",
  "title": "compliance",
  "color": "#004EAD",
  "created_at": "2026-04-15T12:00:00.000Z"
}

This endpoint retrieves a single tag by ID.

HTTP Request

GET https://api.devici.com/api/v1/tags/:id

Create Tag

To create a tag use this code:

axios.post("/tags", {
  title: "compliance",
  color: "#004EAD",
});

The above command returns JSON structured like this:

{
  "id": "{{tag_id}}",
  "title": "compliance",
  "color": "#004EAD",
  "created_at": "2026-04-15T12:00:00.000Z"
}

This endpoint creates a tag.

HTTP Request

POST https://api.devici.com/api/v1/tags

Body Parameters

Parameter Type Description
title string Required. Up to 100 characters. Allowed: alphanumerics, hyphens, single spaces (no leading/trailing spaces).
color string Required. Hex color string (#RGB or #RRGGBB).

Update a Specific Tag

To update a tag use this code:

axios.patch("/tags/:id", {
  title: "compliance-v2",
  color: "#8B3BB2",
});

This endpoint updates a tag. Both fields are optional — pass only what you want to change.

HTTP Request

PATCH https://api.devici.com/api/v1/tags/:id

Delete a Specific Tag

To delete a tag use this code:

axios.delete("/tags/:id");

This endpoint deletes a tag. The tag is detached from any resources it was attached to (threat models, codex items).

HTTP Request

DELETE https://api.devici.com/api/v1/tags/:id

Canvases

Get All Canvases

To get all Canvases use this code:

axios.get("/canvases/threat-model/:threatModelId");
{
  "items": [
    {
      "id": "{{canvas_id}}",
      "created_at": "2024-05-08T16:27:08.765Z",
      "updated_at": "2024-05-08T16:27:08.765Z",
      "title": "Canvas title",
      "format": "diagram",
      "data": {
        "edges": [],
        "nodes": []
      },
      "threat_model": {
        "id": "{{threat_model_id}}"
      }
    }
  ],
  "count": 1
}

This endpoint retrieves all canvases for provided threat model.

HTTP Request

GET https://api.devici.com/api/v1/canvases/threat-model/:threatModelId

Query Parameters

Parameter Default Description
limit 20 Count of items per request
page 1 Page
sort created_at Order by created at
order ASC Sort by ASC

Get a Specific Canvas

To get specific canvas use this code:

axios.get("/canvases/:id");

The above command returns JSON structured like this:

{
  "id": "{{canvas_id}}",
  "created_at": "2024-05-08T16:27:08.765Z",
  "updated_at": "2024-05-08T16:27:08.765Z",
  "title": "Canvas",
  "format": "diagram",
  "data": {
    "edges": [],
    "nodes": []
  },
  "threat_model": {
    "id": "{{threat_model_id}}"
  }
}

This endpoint retrieves a specific canvas.

HTTP Request

GET https://api.devici.com/api/v1/canvases/:id

Create Canvas

To create canvases use this code:

axios.post("/canvases", {
  title: "New Canvas",
  threatModelId: "{{threat_model_id}}"
  format: "diagram",
  data: {
    nodes: [],
    edges: [],
  },
});

This endpoint create a specific canvas.

HTTP Request

POST https://api.devici.com/api/v1/canvases

Update a Specific Canvas

To update specific canvas use this code:

axios.patch("/canvases/:id", {
  title: "New title",
  threatModelId: "{{threat_model_id}}",
  format: "diagram",
  data: {
    nodes: [],
    edges: [],
  },
});

This endpoint update a specific canvas.

HTTP Request

PATCH https://api.devici.com/api/v1/canvases/:id

Delete a Specific Canvas

To delete specific canvas use this code:

axios.delete("/canvases/:id");

This endpoint deletes a specific canvas.

HTTP Request

DELETE https://api.devici.com/api/v1/canvases/:id

Components

Get All Components

To get all Components use this code:

axios.get("/components");

The above command returns JSON structured like this:

{
  "items": [
    {
      "id": "{{component_id}}",
      "created_at": "2024-05-17T16:54:05.143Z",
      "updated_at": "2024-05-17T16:54:05.143Z",
      "title": "Dataflow",
      "description": "",
      "canvas": {
        "id": "{{canvas_id}}"
      }
    },
    {
      "id": "{{component_id}}",
      "created_at": "2024-05-17T16:54:11.682Z",
      "updated_at": "2024-05-17T16:54:11.682Z",
      "title": "Process",
      "description": "",
      "canvas": {
        "id": "{{canvas_id}}"
      }
    }
  ],
  "count": 2
}

This endpoint retrieves all threat models.

HTTP Request

GET https://api.devici.com/api/v1/components

Query Parameters

Parameter Default Description
limit 20 Count of items per request
page 1 Page
sort created_at Order by created at
order ASC Sort by ASC

Get a Specific Component

To get specific component use this code:

axios.get("/components/:id");

The above command returns JSON structured like this:

{
  "id": "{{component_id}}",
  "created_at": "2024-05-17T16:54:11.682Z",
  "updated_at": "2024-05-17T16:54:11.682Z",
  "title": "Process",
  "description": "",
  "canvas": {
    "id": "{{canvas_id}}"
  },
  "attributes": [],
  "threats": []
}

This endpoint retrieves a specific component.

HTTP Request

GET https://api.devici.com/api/v1/components/:id

Get All Components for specific Canvas

To get all Components for specific canvas use this code:

axios.get("/components/for-canvas/:canvasId");

The above command returns JSON structured like this:

[
  {
    "id": "{{component_id}}",
    "created_at": "2024-05-17T09:59:56.914Z",
    "updated_at": "2024-05-17T09:59:56.914Z",
    "title": "Datastore",
    "description": "",
    "attributes": [],
    "threats": []
  },
  {
    "id": "{{component_id}}",
    "created_at": "2024-05-17T09:59:56.914Z",
    "updated_at": "2024-05-17T09:59:56.914Z",
    "title": "Dataflow",
    "description": "",
    "attributes": [],
    "threats": []
  }
]

This endpoint retrieves all components for specific canvas.

HTTP Request

GET https://api.devici.com/api/v1/components/for-canvas/:canvasId

Attributes

Attributes can be added to components from three distinct sources, clearly separated in the request body:

When built-in or custom codex attributes are added, related threats are automatically synced to the component.

Rate Limits & Constraints

Limit Value
Max attributes per source per request (built_in, custom_codex, custom) 20
Max operations per bulk-add request 20
Max IDs per bulk-remove request 100

Add Attribute(s) to Component

To add attributes to a component use this code:

axios.post("/attributes", {
  component_id: "{{component_id}}",
  built_in: [
    { id: "{{built_in_attribute_id}}" }
  ],
  custom_codex: [
    { id: "{{codex_attribute_id}}" }
  ],
  custom: [
    { title: "New custom attribute", description: "A custom description" },
    { id: "{{existing_custom_attr_id}}" }
  ]
});

The above command returns JSON structured like this:

{
  "built_in": [
    {
      "id": "{{attribute_id}}",
      "ref_id": "{{built_in_attribute_id}}",
      "title": "Authentication",
      "description": "Validates the identity of a user or system.",
      "type": "functional",
      "assignable_to_components": ["process", "external_entity"]
    }
  ],
  "custom_codex": [
    {
      "id": "{{attribute_id}}",
      "ref_id": "{{codex_attribute_id}}",
      "title": "My Codex Attribute",
      "description": "From organisation codex.",
      "type": "data",
      "assignable_to_components": ["datastore", "process"]
    }
  ],
  "custom": [
    {
      "id": "{{attribute_id}}",
      "title": "New custom attribute",
      "description": "A custom description",
      "created_by": "{{user_id}}"
    }
  ]
}

This endpoint adds one or more attributes to a component from any combination of sources. At least one of built_in, custom_codex, or custom must be provided and non-empty.

HTTP Request

POST https://api.devici.com/api/v1/attributes

Request Body

Field Required Description
component_id Yes UUID of the target component
built_in No Built-in library attributes. Each item requires id (the attribute primary UUID returned by GET /v1/codex/built-in/attributes). Max 20 items.
custom_codex No Custom codex attributes. Each item requires id. Max 20 items.
custom No Canvas-scoped user-defined attributes. Each item requires either id (reuse an existing custom attribute from the same canvas) or title (create a new one). Max 20 items.

Custom Source Item Fields

Field Description
id UUID of an existing custom attribute to reuse — must belong to the same canvas as the target component
title Title for a new custom attribute (required when id is not provided)
description Optional description for new custom attributes

Built-in and Custom Codex Response Item Fields

Field Description
id UUID of the attribute instance attached to the component
ref_id UUID of the source attribute. For built_in items this is the library attribute primary id (the same one you sent in the request); for custom_codex items it's the codex attribute primary id. Use it to deduplicate or to look up the original definition.
title Attribute title
description Attribute description
type Attribute type: functional or data
assignable_to_components Component types this attribute can be applied to. Possible values: process, external_entity, datastore, dataflow, trust_boundary

Duplicate Prevention

The same library or codex attribute cannot be attached twice to the same component. If a request would attach the same attribute (matched by ref_id) more than once — either across built_in and custom_codex items in a single request, or against an attribute already present on the component — the call returns 400 Bad Request with a message like Attribute <ref_id> is already attached to component <component_id>. Custom (inline) attributes are unaffected and may have duplicate titles.

Bulk Add Attributes

To bulk add attributes to multiple components use this code:

axios.post("/attributes/bulk-add", {
  operations: [
    {
      component_id: "{{component_id_1}}",
      built_in: [{ id: "{{built_in_attribute_id_1}}" }],
      custom: [{ title: "Custom attr A" }]
    },
    {
      component_id: "{{component_id_2}}",
      built_in: [{ id: "{{built_in_attribute_id_2}}" }]
    }
  ]
});

The above command returns JSON structured like this:

[
  {
    "component_id": "{{component_id_1}}",
    "attributes": {
      "built_in": [
        { "id": "{{attribute_id}}", "ref_id": "{{built_in_attribute_id_1}}", "title": "Authentication", "description": "...", "type": "functional", "assignable_to_components": ["process", "external_entity"] }
      ],
      "custom_codex": [],
      "custom": [
        { "id": "{{attribute_id}}", "title": "Custom attr A", "description": null, "created_by": "{{user_id}}" }
      ]
    }
  },
  {
    "component_id": "{{component_id_2}}",
    "attributes": {
      "built_in": [
        { "id": "{{attribute_id}}", "ref_id": "{{built_in_attribute_id_2}}", "title": "Authorization", "description": "...", "type": "functional", "assignable_to_components": ["process"] }
      ],
      "custom_codex": [],
      "custom": []
    }
  }
]

This endpoint adds attributes to one or multiple components in a single request. Returns an array of { component_id, attributes } entries — one entry per affected component (operations targeting the same component are merged into a single entry).

HTTP Request

POST https://api.devici.com/api/v1/attributes/bulk-add

Request Body

Field Required Description
operations Yes Array of add-attribute operations. Each operation follows the same schema as POST /attributes. Min 1, max 20 operations.

Bulk Remove Attributes

To bulk remove attributes use this code:

axios.post("/attributes/bulk-remove", {
  ids: [
    "{{attribute_id_1}}",
    "{{attribute_id_2}}"
  ]
});

This endpoint removes multiple attributes by IDs in a single request. Any threats caused exclusively by a removed attribute are automatically deleted.

HTTP Request

POST https://api.devici.com/api/v1/attributes/bulk-remove

Request Body

Field Required Description
ids Yes Array of attribute UUIDs to remove. Min 1, max 100 IDs.

Get Attributes by Component

To get attributes for a specific component use this code:

axios.get("/attributes/component/{{component_id}}");

The above command returns JSON structured like this:

{
  "built_in": [
    { "id": "{{attribute_id}}", "ref_id": "{{built_in_attribute_id}}", "title": "Authentication", "description": "...", "type": "functional", "assignable_to_components": ["process", "external_entity"] }
  ],
  "custom_codex": [
    { "id": "{{attribute_id}}", "ref_id": "{{codex_attribute_id}}", "title": "My Codex Attribute", "description": "...", "type": "data", "assignable_to_components": ["datastore"] }
  ],
  "custom": [
    { "id": "{{attribute_id}}", "title": "My Custom Attribute", "description": "...", "type": null, "created_by": "{{user_id}}" }
  ]
}

This endpoint retrieves all attributes on a component, grouped by source.

HTTP Request

GET https://api.devici.com/api/v1/attributes/component/:componentId

Get Attributes by Canvas

To get attributes for all components in a canvas use this code:

// Nested by component (default)
axios.get("/attributes/canvas/{{canvas_id}}");

// Flat — all components merged, deduplicated by title per source
axios.get("/attributes/canvas/{{canvas_id}}?flat=true");

Default response (nested by component):

[
  {
    "component_id": "{{component_id}}",
    "component_title": "Process",
    "attributes": {
      "built_in": [
        { "id": "{{attribute_id}}", "ref_id": "{{built_in_attribute_id}}", "title": "Authentication", "description": "...", "type": "functional", "assignable_to_components": ["process", "external_entity"] }
      ],
      "custom_codex": [],
      "custom": []
    }
  }
]

Flat response (?flat=true):

{
  "built_in": [
    { "id": "{{attribute_id}}", "ref_id": "{{built_in_attribute_id}}", "title": "Authentication", "description": "...", "type": "functional", "assignable_to_components": ["process", "external_entity"] }
  ],
  "custom_codex": [],
  "custom": []
}

This endpoint retrieves attributes for all components in a canvas. By default returns a list nested by component. Use ?flat=true to receive a flat grouped response with attributes deduplicated by title.

HTTP Request

GET https://api.devici.com/api/v1/attributes/canvas/:canvasId

Query Parameters

Parameter Default Description
flat false When true, returns a flat grouped response instead of nesting by component

Get Attributes by Threat Model

To get attributes for all components in a threat model use this code:

// Nested by component (default)
axios.get("/attributes/threat-model/{{threat_model_id}}");

// Flat
axios.get("/attributes/threat-model/{{threat_model_id}}?flat=true");

Default response (nested by component):

[
  {
    "component_id": "{{component_id}}",
    "component_title": "Process",
    "attributes": {
      "built_in": [
        { "id": "{{attribute_id}}", "ref_id": "{{built_in_attribute_id}}", "title": "Authentication", "description": "...", "type": "functional", "assignable_to_components": ["process", "external_entity"] }
      ],
      "custom_codex": [],
      "custom": []
    }
  }
]

This endpoint retrieves attributes for all components across all canvases in a threat model. By default returns a list nested by component. Use ?flat=true to receive a flat grouped response with attributes deduplicated by title.

HTTP Request

GET https://api.devici.com/api/v1/attributes/threat-model/:threatModelId

Query Parameters

Parameter Default Description
flat false When true, returns a flat grouped response instead of nesting by component

Update Custom Attribute

To update a custom attribute use this code:

axios.patch("/attributes/{{attribute_id}}", {
  title: "Updated title",
  description: "Updated description"
});

This endpoint updates a custom attribute. Only attributes created by users (custom source) can be updated — built-in and codex attributes are read-only. The title must not conflict with another attribute on the same component or with a reserved built-in name.

HTTP Request

PATCH https://api.devici.com/api/v1/attributes/:id

Request Body

Field Required Description
title No New title for the attribute
description No New description
type No Attribute type: functional or data

Delete Attribute

To delete an attribute use this code:

axios.delete("/attributes/{{attribute_id}}");

This endpoint deletes an attribute from a component. Any threats caused exclusively by this attribute are automatically deleted as well.

HTTP Request

DELETE https://api.devici.com/api/v1/attributes/:id

Threats

Manage threats on diagram components. Threats can come from three distinct sources, mirroring how the diagram editor lets you drop a Devici-codex threat, an organisation-codex threat, or write a custom one.

Threat Rate Limits & Constraints

Limit Value
Max threats per source per request 20
Max operations per bulk-add request 20
Max IDs per bulk-remove request 100

Add Threat(s) to Component

To add threats to a component use this code:

axios.post("/threats/add-to-component", {
  component_id: "{{component_id}}",
  built_in: [
    { id: "{{built_in_threat_id}}" }
  ],
  custom_codex: [
    { id: "{{codex_threat_id}}" }
  ],
  custom: [
    {
      title: "Custom inline threat",
      description: "Free-form threat",
      priority: "medium",
      status: "open"
    }
  ]
});

This endpoint adds one or more threats to a component from any combination of sources. At least one of built_in, custom_codex, or custom must be provided and non-empty.

HTTP Request

POST https://api.devici.com/api/v1/threats/add-to-component

Request Body

Field Required Description
component_id Yes UUID of the target component
built_in No Built-in library threats. Each item requires id (library threat UUID). Max 20 items.
custom_codex No Custom codex threats. Each item requires id (codex threat UUID). Max 20 items.
custom No Inline custom threats. Each item requires title, description, priority. status is optional. Max 20 items.

Custom Source Item Fields

Field Required Description
title Yes Title of the inline custom threat
description Yes Description of the threat
priority Yes One of low, medium, high, critical
status No One of open, mitigated, transferred, acknowledged (default open)

Returns the threats grouped by source (current full state of the component):

{
  "built_in": [
    {
      "id": "{{threat_id}}",
      "title": "Spoofing Identity",
      "description": "...",
      "priority": "high",
      "status": "open"
    }
  ],
  "custom_codex": [],
  "custom": [
    {
      "id": "{{threat_id}}",
      "title": "Custom inline threat",
      "description": "Free-form threat",
      "priority": "medium",
      "status": "open",
      "created_by": "{{user_id}}"
    }
  ]
}

Bulk Add Threats

To bulk add threats to multiple components use this code:

axios.post("/threats/bulk-add", {
  operations: [
    {
      component_id: "{{component_id_1}}",
      built_in: [{ id: "{{built_in_threat_id_1}}" }],
      custom: [{ title: "Bulk inline threat", description: "...", priority: "low" }]
    },
    {
      component_id: "{{component_id_2}}",
      built_in: [{ id: "{{built_in_threat_id_2}}" }]
    }
  ]
});

This endpoint adds threats to one or multiple components in a single request. Returns an array of grouped responses — one entry per operation, in the same order.

HTTP Request

POST https://api.devici.com/api/v1/threats/bulk-add

Request Body

Field Required Description
operations Yes Array of add-threat operations. Each follows the same schema as POST /threats/add-to-component. Min 1, max 20 operations.

Returns an array of grouped responses — one entry per operation, in the same order:

[
  {
    "built_in": [
      { "id": "{{threat_id}}", "title": "Spoofing Identity", "description": "...", "priority": "high", "status": "open" }
    ],
    "custom_codex": [],
    "custom": [
      { "id": "{{threat_id}}", "title": "Bulk inline threat", "description": "...", "priority": "low", "status": "open", "created_by": "{{user_id}}" }
    ]
  },
  {
    "built_in": [
      { "id": "{{threat_id}}", "title": "Tampering", "description": "...", "priority": "high", "status": "open" }
    ],
    "custom_codex": [],
    "custom": []
  }
]

Bulk Remove Threats

To bulk remove threats use this code:

axios.post("/threats/bulk-remove", {
  ids: [
    "{{threat_id_1}}",
    "{{threat_id_2}}"
  ]
});

Soft-deletes the listed threats. Cross-tenant IDs are rejected.

HTTP Request

POST https://api.devici.com/api/v1/threats/bulk-remove

Request Body

Field Required Description
ids Yes Array of threat UUIDs to remove. Min 1, max 100 IDs.

Responds with 201 Created and an empty body on success. Returns 403 Forbidden if any ID belongs to another tenant; nothing is removed in that case. Returns 400 Bad Request if any ID is unknown.

Get All Threats

To get all threats use this code:

axios.get("/threats");

This endpoint retrieves all threats for the customer.

HTTP Request

GET https://api.devici.com/api/v1/threats

Query Parameters

Parameter Default Description
limit 20 Count of items per request
page 0 Page number (0-based)
sort created_at Order by
order ASC ASC or DESC

The above command returns JSON structured like this:

{
  "items": [
    {
      "id": "{{threat_id}}",
      "created_at": "2024-05-22T16:25:46.212Z",
      "updated_at": "2024-05-22T16:25:46.212Z",
      "ref_id": "0dda2bb4-c754-471b-93a1-fe74067e1ff0",
      "title": "Information Disclosure",
      "description": "Information disclosure is the unintentional exposure or release of confidential or sensitive data to unauthorized individuals or entities.",
      "source": null,
      "priority": "medium",
      "status": "open",
      "is_custom": false,
      "component": {
        "id": "{{component_id}}"
      }
    }
  ],
  "count": 1
}

Get a Specific Threat

To get a specific threat use this code:

axios.get("/threats/:id");

HTTP Request

GET https://api.devici.com/api/v1/threats/:id

Returns:

{
  "id": "{{threat_id}}",
  "created_at": "2024-05-22T16:25:46.212Z",
  "updated_at": "2024-05-22T16:25:46.212Z",
  "ref_id": null,
  "title": "Custom inline threat",
  "description": "Free-form threat",
  "source": null,
  "priority": "medium",
  "status": "open",
  "is_custom": true,
  "component": {
    "id": "{{component_id}}"
  }
}

ref_id, source, is_custom indicate the origin: built-in / custom-codex threats have ref_id set to the source UUID and is_custom: false; inline custom threats have ref_id: null and is_custom: true.

Get Threats by Component

To get threats for a specific component (grouped by source) use this code:

axios.get("/threats/component/{{component_id}}");

HTTP Request

GET https://api.devici.com/api/v1/threats/component/:componentId

Returns:

{
  "built_in": [
    { "id": "{{threat_id}}", "title": "Spoofing Identity", "description": "...", "priority": "high", "status": "open" }
  ],
  "custom_codex": [],
  "custom": [
    { "id": "{{threat_id}}", "title": "Custom inline threat", "description": "...", "priority": "medium", "status": "open", "created_by": "{{user_id}}" }
  ]
}

Get Threats for a Specific Component (flat list)

To get all threats for a specific component as a flat list use this code:

axios.get("/threats/for-component/:componentId");

Returns a flat list (not grouped by source). Prefer /threats/component/:componentId (above) when you want the grouped shape.

HTTP Request

GET https://api.devici.com/api/v1/threats/for-component/:componentId

Returns:

[
  {
    "id": "{{threat_id}}",
    "title": "Spoofing Identity",
    "description": "...",
    "priority": "high",
    "status": "open",
    "is_custom": false,
    "ref_id": "{{built_in_threat_id}}"
  }
]

Get Threats by Canvas

To get threats for all components in a canvas use this code:

// Nested by component (default)
axios.get("/threats/canvas/{{canvas_id}}");

// Flat — all components merged, deduplicated by title per source
axios.get("/threats/canvas/{{canvas_id}}?flat=true");

By default returns a list nested by component. Use ?flat=true to receive a single grouped response with threats deduplicated by title.

HTTP Request

GET https://api.devici.com/api/v1/threats/canvas/:representationId

Query Parameters

Parameter Default Description
flat false When true, returns a flat grouped response instead of nesting by component

Default response (nested by component):

[
  {
    "component_id": "{{component_id}}",
    "component_title": "Process",
    "threats": {
      "built_in": [
        { "id": "{{threat_id}}", "title": "Spoofing Identity", "description": "...", "priority": "high", "status": "open" }
      ],
      "custom_codex": [],
      "custom": []
    }
  }
]

Get Threats by Threat Model

To get threats for all components in a threat model use this code:

axios.get("/threats/threat-model/{{threat_model_id}}");
axios.get("/threats/threat-model/{{threat_model_id}}?flat=true");

Same shape as /threats/canvas/:id, scoped to all canvases in the threat model.

HTTP Request

GET https://api.devici.com/api/v1/threats/threat-model/:threatModelId

Query Parameters

Parameter Default Description
flat false When true, returns a flat grouped response instead of nesting by component

Default response (nested by component, one entry per component across all canvases):

[
  {
    "component_id": "{{component_id}}",
    "component_title": "Process",
    "threats": {
      "built_in": [
        { "id": "{{threat_id}}", "title": "Spoofing Identity", "description": "...", "priority": "high", "status": "open" }
      ],
      "custom_codex": [],
      "custom": []
    }
  }
]

Flat response (?flat=true):

{
  "built_in": [
    { "id": "{{threat_id}}", "title": "Spoofing Identity", "description": "...", "priority": "high", "status": "open" }
  ],
  "custom_codex": [],
  "custom": []
}

Create a Custom Threat

To create a single custom threat on a component use this code:

axios.post("/threats", {
  componentId: "{{component_id}}",
  title: "New Threat",
  priority: "low",
  description: "description"
});

Equivalent to sending a single custom item to POST /threats/add-to-component — useful when you only need to create one inline custom threat at a time and don't need the grouped response.

HTTP Request

POST https://api.devici.com/api/v1/threats

Request Body

Field Required Description
componentId Yes UUID of the target component
title Yes Threat title
description Yes Threat description
priority Yes One of low, medium, high, critical
status No One of open, mitigated, transferred, acknowledged (default open)

Returns:

{
  "threatId": "{{threat_id}}",
  "componentId": "{{component_id}}"
}

Update a Specific Threat

To update a specific threat use this code:

axios.patch("/threats/:id", {
  title: "New Title",
  description: "New description",
  priority: "low",
  status: "open"
});

HTTP Request

PATCH https://api.devici.com/api/v1/threats/:id

Request Body

Field Required Description
title No New title
description No New description
priority No One of low, medium, high, critical
status No One of open, mitigated, transferred, acknowledged

Responds with 200 OK and an empty body on success.

Delete a Specific Threat

To delete a specific threat use this code:

axios.delete("/threats/:id");

HTTP Request

DELETE https://api.devici.com/api/v1/threats/:id

Responds with 200 OK and an empty body on success. Soft-deletes the threat — any cascading mitigation links are removed too.

Mitigations

Manage mitigations on threats. Mitigations can come from three distinct sources, mirroring how the diagram editor lets you drop a Devici-codex mitigation, an organisation-codex mitigation, or write a custom one.

Mitigation Rate Limits & Constraints

Limit Value
Max mitigations per source per request 20
Max operations per bulk-add request 20
Max IDs per bulk-remove request 100

Add Mitigation(s) to Threat

To add mitigations to a threat use this code:

axios.post("/mitigations/add-to-threat", {
  threat_id: "{{threat_id}}",
  built_in: [
    { id: "{{built_in_mitigation_id}}" }
  ],
  custom_codex: [
    { id: "{{codex_mitigation_id}}" }
  ],
  custom: [
    {
      title: "Custom inline mitigation",
      definition: "Free-form mitigation",
      consideration: "Optional consideration",
      example: "Optional example"
    }
  ]
});

This endpoint attaches one or more mitigations to a threat from any combination of sources. At least one of built_in, custom_codex, or custom must be provided and non-empty.

HTTP Request

POST https://api.devici.com/api/v1/mitigations/add-to-threat

Request Body

Field Required Description
threat_id Yes UUID of the target threat
built_in No Built-in library mitigations. Each item requires id. Max 20 items.
custom_codex No Custom codex mitigations. Each item requires id. Max 20 items.
custom No Inline custom mitigations. Each item requires title and definition. consideration, explanation, example, question are optional. Max 20 items.

Custom Source Item Fields

Field Required Description
title Yes Mitigation title
definition Yes What the mitigation does
consideration No Implementation consideration
explanation No Why the mitigation works
example No Concrete example
question No Question the mitigation answers

Returns mitigations grouped by source for the threat:

{
  "built_in": [
    {
      "id": "{{mitigation_id}}",
      "title": "Strong Authentication",
      "definition": "Requires verified identity before granting access."
    }
  ],
  "custom_codex": [],
  "custom": [
    {
      "id": "{{mitigation_id}}",
      "title": "Custom inline mitigation",
      "definition": "Free-form mitigation",
      "consideration": "Optional consideration",
      "example": "Optional example",
      "created_by": "{{user_id}}"
    }
  ]
}

Bulk Add Mitigations

To bulk add mitigations to multiple threats use this code:

axios.post("/mitigations/bulk-add", {
  operations: [
    {
      threat_id: "{{threat_id_1}}",
      built_in: [{ id: "{{built_in_mitigation_id_1}}" }],
      custom: [{ title: "Bulk mitigation A", definition: "..." }]
    },
    {
      threat_id: "{{threat_id_2}}",
      custom_codex: [{ id: "{{codex_mitigation_id_1}}" }]
    }
  ]
});

Returns an array of grouped responses — one entry per operation, in the same order.

HTTP Request

POST https://api.devici.com/api/v1/mitigations/bulk-add

Request Body

Field Required Description
operations Yes Array of add-mitigation operations. Each follows the same schema as POST /mitigations/add-to-threat. Min 1, max 20 operations.

Returns an array of grouped responses — one entry per operation, in the same order:

[
  {
    "built_in": [
      { "id": "{{mitigation_id}}", "title": "Strong Authentication", "definition": "..." }
    ],
    "custom_codex": [],
    "custom": [
      { "id": "{{mitigation_id}}", "title": "Bulk mitigation A", "definition": "...", "created_by": "{{user_id}}" }
    ]
  },
  {
    "built_in": [],
    "custom_codex": [
      { "id": "{{mitigation_id}}", "title": "Codex mitigation", "definition": "..." }
    ],
    "custom": []
  }
]

Bulk Remove Mitigations

To bulk remove mitigations use this code:

axios.post("/mitigations/bulk-remove", {
  ids: [
    "{{mitigation_id_1}}",
    "{{mitigation_id_2}}"
  ]
});

HTTP Request

POST https://api.devici.com/api/v1/mitigations/bulk-remove

Request Body

Field Required Description
ids Yes Array of mitigation UUIDs to remove. Min 1, max 100 IDs.

Responds with 201 Created and an empty body on success. Returns 403 Forbidden if any ID belongs to another tenant; nothing is removed in that case. Returns 400 Bad Request if any ID is unknown.

Get All Mitigations

To get all mitigations use this code:

axios.get("/mitigations");

HTTP Request

GET https://api.devici.com/api/v1/mitigations

Query Parameters

Parameter Default Description
limit 20 Count of items per request
page 0 Page number (0-based)
sort created_at Order by
order ASC ASC or DESC

Get a Specific Mitigation

To get a specific mitigation use this code:

axios.get("/mitigations/:id");

HTTP Request

GET https://api.devici.com/api/v1/mitigations/:id

Returns:

{
  "id": "{{mitigation_id}}",
  "title": "Strong Authentication",
  "definition": "Requires verified identity before granting access.",
  "consideration": "...",
  "explanation": "...",
  "example": "...",
  "question": "...",
  "status": null,
  "is_custom": false,
  "threat": {
    "id": "{{threat_id}}"
  }
}

is_custom: true indicates an inline custom mitigation. Built-in / custom-codex mitigations carry is_custom: false.

Get Mitigations by Threat

To get mitigations grouped by source for a threat use this code:

axios.get("/mitigations/threat/{{threat_id}}");

HTTP Request

GET https://api.devici.com/api/v1/mitigations/threat/:threatId

Returns:

{
  "built_in": [
    { "id": "{{mitigation_id}}", "title": "Strong Authentication", "definition": "..." }
  ],
  "custom_codex": [],
  "custom": []
}

Get Mitigations for a Specific Threat (flat list)

To get all mitigations on a threat as a flat list use this code:

axios.get("/mitigations/for-threat/:threatId");

Returns a flat list (not grouped by source). Prefer /mitigations/threat/:threatId (above) when you want the grouped shape.

HTTP Request

GET https://api.devici.com/api/v1/mitigations/for-threat/:threatId

Returns:

[
  {
    "id": "{{mitigation_id}}",
    "title": "Strong Authentication",
    "definition": "Requires verified identity before granting access.",
    "consideration": "...",
    "explanation": "...",
    "example": "...",
    "question": "...",
    "status": null,
    "is_custom": false,
    "threat": { "id": "{{threat_id}}" }
  }
]

Get Mitigations by Component

To get mitigations across all threats on a component use this code:

axios.get("/mitigations/component/{{component_id}}");

Returns a list nested by threat — each entry includes the threat id, title, and grouped mitigations.

HTTP Request

GET https://api.devici.com/api/v1/mitigations/component/:componentId

Returns:

[
  {
    "threat_id": "{{threat_id}}",
    "threat_title": "Spoofing Identity",
    "mitigations": {
      "built_in": [
        { "id": "{{mitigation_id}}", "title": "Strong Authentication", "definition": "..." }
      ],
      "custom_codex": [],
      "custom": []
    }
  }
]

Get Mitigations by Canvas

To get mitigations for all threats in a canvas use this code:

// Nested by threat (default)
axios.get("/mitigations/canvas/{{canvas_id}}");

// Flat — all threats merged, deduplicated by title per source
axios.get("/mitigations/canvas/{{canvas_id}}?flat=true");

HTTP Request

GET https://api.devici.com/api/v1/mitigations/canvas/:representationId

Query Parameters

Parameter Default Description
flat false When true, returns a single grouped response instead of nesting by threat

Default response (nested by threat):

[
  {
    "threat_id": "{{threat_id}}",
    "threat_title": "Spoofing Identity",
    "mitigations": {
      "built_in": [
        { "id": "{{mitigation_id}}", "title": "Strong Authentication", "definition": "..." }
      ],
      "custom_codex": [],
      "custom": []
    }
  }
]

Flat response (?flat=true):

{
  "built_in": [
    { "id": "{{mitigation_id}}", "title": "Strong Authentication", "definition": "..." }
  ],
  "custom_codex": [],
  "custom": []
}

Get Mitigations by Threat Model

To get mitigations for every threat in a threat model use this code:

axios.get("/mitigations/threat-model/{{threat_model_id}}");
axios.get("/mitigations/threat-model/{{threat_model_id}}?flat=true");

Same shape as /mitigations/canvas/:id, scoped to all canvases in the threat model.

HTTP Request

GET https://api.devici.com/api/v1/mitigations/threat-model/:threatModelId

Query Parameters

Parameter Default Description
flat false When true, returns a flat grouped response instead of nesting by threat

Default response (nested by threat, one entry per threat across all canvases in the model):

[
  {
    "threat_id": "{{threat_id}}",
    "threat_title": "Spoofing Identity",
    "mitigations": {
      "built_in": [
        { "id": "{{mitigation_id}}", "title": "Strong Authentication", "definition": "..." }
      ],
      "custom_codex": [],
      "custom": []
    }
  }
]

Flat response (?flat=true):

{
  "built_in": [
    { "id": "{{mitigation_id}}", "title": "Strong Authentication", "definition": "..." }
  ],
  "custom_codex": [],
  "custom": []
}

Create a Custom Mitigation

To create a single custom mitigation on a threat use this code:

axios.post("/mitigations", {
  threatId: "{{threat_id}}",
  title: "New Mitigation",
  definition: "How it mitigates the threat"
});

Equivalent to sending a single custom item to POST /mitigations/add-to-threat — useful when you only need to create one inline custom mitigation at a time and don't need the grouped response.

HTTP Request

POST https://api.devici.com/api/v1/mitigations

Request Body

Field Required Description
threatId Yes UUID of the parent threat
title Yes Mitigation title
definition Yes What the mitigation does
consideration No Implementation consideration
explanation No Why the mitigation works
example No Concrete example
question No Question the mitigation answers

Returns:

{
  "mitigationId": "{{mitigation_id}}",
  "threatId": "{{threat_id}}"
}

Update a Specific Mitigation

To update a specific mitigation use this code:

axios.patch("/mitigations/:id", {
  title: "New Title",
  definition: "New definition"
});

HTTP Request

PATCH https://api.devici.com/api/v1/mitigations/:id

Request Body

Field Required Description
title No New title
definition No New definition
consideration No New consideration
explanation No New explanation
example No New example
status No New status

Responds with 200 OK and an empty body on success.

Delete a Specific Mitigation

To delete a specific mitigation use this code:

axios.delete("/mitigations/:id");

HTTP Request

DELETE https://api.devici.com/api/v1/mitigations/:id

Responds with 200 OK and an empty body on success. Soft-deletes the mitigation.

Comments

Get All Comments

To get all Comments use this code:

axios.get("/comments");

The above command returns JSON structured like this:

{
  "items": [
    {
      "id": "{{comment_id}}",
      "text": "This is first comment",
      "created_at": "2024-05-17T16:54:05.143Z",
      "updated_at": "2024-05-17T16:54:05.143Z",
      "is_edited": false,
      "threat": {
        "id": "{{threat_id}}"
      },
      "user": {
        "id": "{{owner_id}}",
        "avatar_uploaded_at": "2024-05-17T16:54:05.143Z"
      }
    },
    {
      "id": "{{comment_id}}",
      "text": "This is second comment",
      "created_at": "2024-05-17T16:54:05.143Z",
      "updated_at": "2024-05-17T16:54:05.143Z",
      "is_edited": false,
      "threat": {
        "id": "{{threat_id}}"
      },
      "user": {
        "id": "{{owner_id}}",
        "avatar_uploaded_at": "2024-05-17T16:54:05.143Z"
      }
    }
  ],
  "count": 2
}

This endpoint retrieves all comments.

HTTP Request

GET https://api.devici.com/api/v1/comments

Query Parameters

Parameter Default Description
limit 20 Count of items per request
page 1 Page
sort created_at Order by created at
order ASC Sort by ASC

Get a Specific Comment

To get specific comment use this code:

axios.get("/comments/:id");

The above command returns JSON structured like this:

{
  "id": "{{comment_id}}",
  "text": "This is second comment",
  "created_at": "2024-05-17T16:54:05.143Z",
  "updated_at": "2024-05-17T16:54:05.143Z",
  "is_edited": false,
  "threat": {
    "id": "{{threat_id}}"
  },
  "user": {
    "id": "{{owner_id}}",
    "avatar_uploaded_at": "2024-05-17T16:54:05.143Z"
  }
}

This endpoint retrieves a specific comment.

HTTP Request

GET https://api.devici.com/api/v1/comments/:id

Get All Comments for specific Threat

To get all Comments for specific Threat use this code:

axios.get("/comments/for-threat/:threatId");

The above command returns JSON structured like this:

[
  {
    "id": "{{comment_id}}",
    "text": "This is first comment",
    "created_at": "2024-05-17T16:54:05.143Z",
    "updated_at": "2024-05-17T16:54:05.143Z",
    "is_edited": false,
    "user": {
      "id": "{{owner_id}}",
      "avatar_uploaded_at": "2024-05-17T16:54:05.143Z"
    }
  },
  {
    "id": "{{comment_id}}",
    "text": "This is second comment",
    "created_at": "2024-05-17T16:54:05.143Z",
    "updated_at": "2024-05-17T16:54:05.143Z",
    "is_edited": false,
    "user": {
      "id": "{{owner_id}}",
      "avatar_uploaded_at": "2024-05-17T16:54:05.143Z"
    }
  }
]

This endpoint retrieves all comments for specific threat.

HTTP Request

GET https://api.devici.com/api/v1/comments/for-threat/:threatId

Create Comment

To create comment use this code:

axios.post("/comments", {
  threatId: "{{threat_id}}",
  text: "Comment text",
});

This endpoint create a specific comment.

HTTP Request

POST https://api.devici.com/api/v1/comments

Create Many Comments

To create many comments use this code:

axios.post("/comments/many", [
  {
    threatId: "{{threat_id}}",
    userId: "{{user_id}}",
    text: "Comment text"
  },
  {
    threatId: "{{threat_id}}",
    userId: "{{user_id}}",
    text: "Comment text"
  },
  {
    threatId: "{{threat_id}}",
    userId: "{{user_id}}",
    text: "Comment text"
  }
]);

This endpoint create a many comments.

HTTP Request

POST https://api.devici.com/api/v1/comments/many

Update a Specific Comment

To update specific comment use this code:

axios.patch("/comments/:id", {
  text: "Updated text",
});

This endpoint update a specific comment.

HTTP Request

PATCH https://api.devici.com/api/v1/comments/:id

Delete a Specific Comment

To delete specific comment use this code:

axios.delete("/comments/:id");

This endpoint deletes a specific comment.

HTTP Request

DELETE https://api.devici.com/api/v1/comments/:id

Codex Attributes

Manage the attributes that belong to your organisation's custom Codex. Attributes can optionally reference causing/neutralising threats, tags, aliases, and external resource links.

Field Constraints

Field Constraint
title 1–256 characters
description 1–1000 characters
aliases Up to 10 entries, each 1–256 characters
resources Up to 5 entries; per entry: title 1–256, url 1–500
causedThreatsIds / neutralizedThreatsIds Arrays of UUIDs (built-in threat IDs)
tagsIds Array of tag UUIDs belonging to your organisation

Get All Attributes

To get all attributes, use this code:

axios.get("/codex/attributes?page=0&limit=20");

HTTP Request

GET https://api.devici.com/api/v1/codex/attributes

Query Parameters

Parameter Required Default Description
page yes Page number (0-based)
limit yes Items per page (max 100)
sort no created_at Sort field (e.g. title, created_at, updated_at)
order no ASC Sort order: ASC or DESC
text no Free-text search across title, description, tag titles, and alias titles
tagIds no Filter by tag UUIDs (repeatable: tagIds=uuid1&tagIds=uuid2)
createdByIds no Filter by creator user UUIDs (repeatable)

The above command returns JSON structured like this:

{
    "items": [
        {
            "id": "{{attribute_id}}",
            "title": "Attribute 1",
            "description": "Description 1",
            "aliases": ["Alias 1", "Alias 2", "Alias 3"],
            "resources": [
                {
                    "url": "https://example.com",
                    "title": "Reference"
                }
            ],
            "tags": [
                {
                    "id": "{{tag_id}}",
                    "title": "pii",
                    "color": "#FF0000"
                }
            ],
            "last_modified_by": {
                "id": "{{user_id}}",
                "first_name": "Jane",
                "last_name": "Doe",
                "email": "jane@example.com"
            },
            "created_at": "2024-08-08T08:54:45.294Z",
            "updated_at": "2024-08-08T08:54:45.294Z"
        }
    ],
    "count": 1
}

Search Attributes

To search attributes, use this code:

axios.get("/codex/attributes/search?text={{some text}}");

HTTP Request

GET https://api.devici.com/api/v1/codex/attributes/search

Query Parameters

Parameter Required Description
text yes Search query, 1–20 characters. Matches attribute title (case-insensitive).

The above command returns JSON structured like this:

[
    {
        "id": "{{attribute_id}}",
        "title": "Search Result Attribute",
        "description": "Description for Search Result",
        "aliases": ["Search Alias 1"],
        "created_at": "2024-08-08T13:06:42.770Z"
    }
]

Get a Specific Attribute

To get a specific attribute, use this code:

axios.get("/codex/attributes/:id");

HTTP Request

GET https://api.devici.com/api/v1/codex/attributes/:id

The above command returns JSON structured like this:

{
    "id": "{{attribute_id}}",
    "title": "Specific Attribute",
    "description": "Description for Specific Attribute",
    "resources": [
        {
            "url": "https://example.com",
            "title": "Reference"
        }
    ],
    "aliases": ["Specific Alias 1", "Specific Alias 2"],
    "causedThreatsIds": ["{{threat_id}}"],
    "neutralizedThreatsIds": [],
    "tags": [
        {
            "id": "{{tag_id}}",
            "title": "pii",
            "color": "#FF0000"
        }
    ],
    "created_by": {
        "id": "{{user_id}}",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com"
    },
    "last_modified_by": {
        "id": "{{user_id}}",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com"
    },
    "created_at": "2024-07-18T14:27:11.414Z",
    "updated_at": "2024-07-18T14:27:11.414Z"
}

causedThreatsIds / neutralizedThreatsIds are the same UUIDs you send on write — the response uses matching field names so the shape can be round-tripped back into PUT /codex/attributes/:id without remapping.

Create a New Attribute

To create a new attribute, use this code:

axios.post("/codex/attributes", {
    title: "New Attribute",
    description: "Description for Attribute",
    aliases: ["Alias 1", "Alias 2"],
    resources: [
        {
            url: "https://example.com",
            title: "Reference"
        }
    ],
    causedThreatsIds: ["{{threat_id}}"],
    neutralizedThreatsIds: [],
    tagsIds: ["{{tag_id}}"]
});

HTTP Request

POST https://api.devici.com/api/v1/codex/attributes

Request Body

Field Required Description
title yes Attribute title, 1–256 chars. Must be unique within the codex.
description no 1–1000 chars
aliases no Up to 10 alias strings, each 1–256 chars
resources no Up to 5 resource objects (url, title)
causedThreatsIds no UUIDs of built-in threats this attribute causes
neutralizedThreatsIds no UUIDs of built-in threats this attribute neutralises
tagsIds no UUIDs of tags belonging to your organisation

The above command returns JSON structured like this:

{
    "id": "{{attribute_id}}",
    "title": "New Attribute",
    "description": "Description for Attribute",
    "resources": null,
    "aliases": ["New Attribute", "Alias 1", "Alias 2"],
    "causedThreatsIds": ["{{threat_id}}"],
    "neutralizedThreatsIds": [],
    "tags": [
        {
            "id": "{{tag_id}}",
            "title": "pii"
        }
    ],
    "created_by": {
        "id": "{{user_id}}",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com"
    },
    "last_modified_by": {
        "id": "{{user_id}}",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com"
    },
    "created_at": "2024-08-08T14:42:32.853Z",
    "updated_at": "2024-08-08T14:42:32.853Z"
}

The attribute's own title is automatically added to its alias set.

Create Multiple Attributes

To create multiple attributes, use this code:

axios.post("/codex/attributes/many", {
    attributes: [
        {
            title: "New Attribute 1",
            description: "Description for Attribute 1",
            aliases: ["Alias 1", "Alias 2"],
            causedThreatsIds: ["{{threat_id}}"]
        },
        {
            title: "New Attribute 2",
            description: "Description for Attribute 2",
            aliases: ["Alias 3"]
        }
    ]
});

HTTP Request

POST https://api.devici.com/api/v1/codex/attributes/many

Request Body

Field Required Description
attributes yes Array of attribute objects. Max 20 per request. Each object follows the same schema as POST /codex/attributes. All titles within the array must be unique.

The above command returns JSON structured like this:

[
    {
        "id": "{{attribute_id}}",
        "title": "New Attribute 1",
        "description": "Description for Attribute 1",
        "resources": null,
        "aliases": ["New Attribute 1", "Alias 1", "Alias 2"],
        "causedThreatsIds": ["{{threat_id}}"],
        "neutralizedThreatsIds": [],
        "tags": [],
        "created_at": "2024-08-08T13:06:42.770Z",
        "updated_at": "2024-08-08T13:06:42.770Z"
    },
    {
        "id": "{{attribute_id}}",
        "title": "New Attribute 2",
        "description": "Description for Attribute 2",
        "resources": null,
        "aliases": ["New Attribute 2", "Alias 3"],
        "causedThreatsIds": [],
        "neutralizedThreatsIds": [],
        "tags": [],
        "created_at": "2024-08-08T13:06:42.770Z",
        "updated_at": "2024-08-08T13:06:42.770Z"
    }
]

Update a Specific Attribute

To update a specific attribute, use this code:

axios.put("/codex/attributes/:id", {
    title: "Updated Attribute",
    description: "Updated Description",
    aliases: ["Updated Alias 1"],
    resources: [
        {
            url: "https://example.com",
            title: "Updated Reference"
        }
    ],
    causedThreatsIds: ["{{threat_id}}"],
    neutralizedThreatsIds: [],
    tagsIds: ["{{tag_id}}"]
});

HTTP Request

PUT https://api.devici.com/api/v1/codex/attributes/:id

Request Body

Field Required Description
title yes 1–256 chars
aliases yes Full replacement. Send the complete list of aliases you want the attribute to have. The attribute's title is always added automatically.
description no 1–1000 chars
resources no Full replacement. Up to 5 entries.
causedThreatsIds no Full replacement of caused-threats mapping.
neutralizedThreatsIds no Full replacement of neutralised-threats mapping.
tagsIds no Full replacement of tags.

The above command returns the full attribute — same shape as GET /codex/attributes/:id:

{
    "id": "{{attribute_id}}",
    "title": "Updated Attribute",
    "description": "Updated Description",
    "resources": [
        {
            "url": "https://example.com",
            "title": "Updated Reference"
        }
    ],
    "aliases": ["Updated Attribute", "Updated Alias 1"],
    "causedThreatsIds": ["{{threat_id}}"],
    "neutralizedThreatsIds": [],
    "tags": [
        {
            "id": "{{tag_id}}",
            "title": "pii"
        }
    ],
    "created_by": {
        "id": "{{user_id}}",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com"
    },
    "last_modified_by": {
        "id": "{{user_id}}",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com"
    },
    "created_at": "2024-07-18T14:27:11.414Z",
    "updated_at": "2024-07-18T15:12:08.041Z"
}

Delete a Specific Attribute

To delete a specific attribute, use this code:

axios.delete("/codex/attributes/:id");

HTTP Request

DELETE https://api.devici.com/api/v1/codex/attributes/:id

Delete Multiple Attributes

To delete multiple attributes, use this code:

axios.delete("/codex/attributes/many", {
    data: {
        ids: ["{{attribute_id}}"]
    }
});

HTTP Request

DELETE https://api.devici.com/api/v1/codex/attributes/many

Request Body

Field Required Description
ids yes Array of attribute UUIDs to delete

Codex Mitigations

Manage mitigations that belong to your organisation's custom Codex. Mitigations describe how to address a threat and can be attached to threats via the threat attach-mitigations / detach-mitigations endpoints.

Field Constraints

Field Constraint
title 1–256 characters, unique within the codex
definition 1–1000 characters, required
consideration 1–1000 characters, optional
explanation 1–1000 characters, optional
example 1–1000 characters, optional
question 1–256 characters, optional
resources Up to 5 entries; per entry: title 1–256, url 1–500
tagsIds UUIDs of tags belonging to your organisation

Get All Codex Mitigations

To get all mitigations, use this code:

axios.get("/codex/mitigations?page=0&limit=20");

HTTP Request

GET https://api.devici.com/api/v1/codex/mitigations

Query Parameters

Parameter Required Default Description
page yes Page number (0-based)
limit yes Items per page (max 100)
sort no created_at Sort field
order no ASC ASC or DESC
text no Free-text search across title, definition, and tag titles
tagIds no Filter by tag UUIDs (repeatable)
createdByIds no Filter by creator UUIDs (repeatable)

The above command returns JSON structured like this:

{
    "items": [
        {
            "id": "{{mitigation_id}}",
            "title": "Mitigation",
            "definition": "Description Mitigation",
            "tags": [],
            "last_modified_by": {
                "id": "{{user_id}}",
                "first_name": "Jane",
                "last_name": "Doe",
                "email": "jane@example.com"
            },
            "created_at": "2024-08-08T08:59:18.952Z",
            "updated_at": "2024-08-08T08:59:18.952Z"
        }
    ],
    "count": 1
}

Search Mitigations

To search mitigations, use this code:

axios.get("/codex/mitigations/search?text={{some text}}");

HTTP Request

GET https://api.devici.com/api/v1/codex/mitigations/search

Query Parameters

Parameter Required Description
text yes Search query, 1–20 characters. Matches mitigation title.

The above command returns JSON structured like this:

[
    {
        "id": "{{mitigation_id}}",
        "title": "Mitigation3",
        "definition": "Description Mitigation3",
        "created_at": "2024-08-08T08:59:18.952Z"
    }
]

Get a Specific Codex Mitigation

To get a specific mitigation, use this code:

axios.get("/codex/mitigations/:id");

HTTP Request

GET https://api.devici.com/api/v1/codex/mitigations/:id

The above command returns JSON structured like this:

{
    "id": "{{mitigation_id}}",
    "title": "Mitigation",
    "definition": "Description Mitigation",
    "consideration": "Consideration",
    "explanation": "Explanation",
    "example": "Example",
    "question": "Question",
    "resources": [
        {
            "url": "https://example.com",
            "title": "Reference"
        }
    ],
    "tags": [],
    "created_by": {
        "id": "{{user_id}}",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com"
    },
    "last_modified_by": {
        "id": "{{user_id}}",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com"
    },
    "created_at": "2024-08-08T08:59:18.952Z",
    "updated_at": "2024-08-08T08:59:18.952Z"
}

Create a New Mitigation

To create a new mitigation, use this code:

axios.post("/codex/mitigations", {
    title: "New Mitigation",
    definition: "Description for Mitigation",
    example: "Example for Mitigation",
    question: "Question for Mitigation",
    explanation: "Explanation for Mitigation",
    consideration: "Consideration for Mitigation",
    resources: [
        {
            url: "https://example.com",
            title: "Reference"
        }
    ],
    tagsIds: ["{{tag_id}}"]
});

HTTP Request

POST https://api.devici.com/api/v1/codex/mitigations

Request Body

Field Required Description
title yes 1–256 chars, unique within the codex
definition yes 1–1000 chars
consideration no 1–1000 chars
explanation no 1–1000 chars
example no 1–1000 chars
question no 1–256 chars
resources no Up to 5 resource objects (url, title)
tagsIds no UUIDs of tags

The above command returns JSON structured like this:

{
    "id": "{{mitigation_id}}",
    "title": "New Mitigation",
    "definition": "Description for Mitigation",
    "consideration": "Consideration for Mitigation",
    "explanation": "Explanation for Mitigation",
    "example": "Example for Mitigation",
    "question": "Question for Mitigation",
    "resources": [
        {
            "url": "https://example.com",
            "title": "Reference"
        }
    ],
    "tags": [
        {
            "id": "{{tag_id}}",
            "title": "pii",
            "color": "#FF0000"
        }
    ],
    "created_by": {
        "id": "{{user_id}}",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com"
    },
    "last_modified_by": {
        "id": "{{user_id}}",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com"
    },
    "created_at": "2024-08-08T08:59:18.952Z",
    "updated_at": "2024-08-08T08:59:18.952Z"
}

Create Multiple Mitigations

To create multiple mitigations, use this code:

axios.post("/codex/mitigations/many", {
    mitigations: [
        {
            title: "Mitigation1",
            definition: "Description Mitigation1",
            example: "Example1",
            question: "Question1",
            explanation: "Explanation1",
            consideration: "Consideration1"
        },
        {
            title: "Mitigation2",
            definition: "Description Mitigation2"
        }
    ]
});

HTTP Request

POST https://api.devici.com/api/v1/codex/mitigations/many

Request Body

Field Required Description
mitigations yes Array of mitigation objects. Max 20 per request. Each object follows the same schema as POST /codex/mitigations. All titles within the array must be unique.

The above command returns JSON structured like this:

[
    {
        "id": "{{mitigation_id}}",
        "title": "Mitigation1",
        "definition": "Description Mitigation1",
        "consideration": "Consideration1",
        "explanation": "Explanation1",
        "example": "Example1",
        "question": "Question1",
        "resources": null,
        "tags": [],
        "created_at": "2024-08-08T13:51:08.098Z",
        "updated_at": "2024-08-08T13:51:08.098Z"
    },
    {
        "id": "{{mitigation_id}}",
        "title": "Mitigation2",
        "definition": "Description Mitigation2",
        "consideration": null,
        "explanation": null,
        "example": null,
        "question": null,
        "resources": null,
        "tags": [],
        "created_at": "2024-08-08T13:51:08.098Z",
        "updated_at": "2024-08-08T13:51:08.098Z"
    }
]

Update a Specific Codex Mitigation

To update a specific codex mitigation, use this code:

axios.put("/codex/mitigations/:id", {
    title: "Mitigation",
    definition: "Description Mitigation",
    consideration: "Consideration",
    explanation: "Explanation",
    example: "Example",
    question: "Question",
    resources: [
        {
            url: "https://example.com",
            title: "Reference"
        }
    ],
    tagsIds: ["{{tag_id}}"]
});

HTTP Request

PUT https://api.devici.com/api/v1/codex/mitigations/:id

Request Body

Field Required Description
title yes 1–256 chars
definition yes 1–1000 chars
consideration no 1–1000 chars
explanation no 1–1000 chars
example no 1–1000 chars
question no 1–256 chars
resources no Full replacement. Up to 5 entries.
tagsIds no Full replacement of tags

The above command returns JSON structured like this:

{
    "id": "{{mitigation_id}}",
    "title": "Mitigation",
    "definition": "Description Mitigation",
    "consideration": "Consideration",
    "explanation": "Explanation",
    "example": "Example",
    "question": "Question",
    "resources": [
        {
            "url": "https://example.com",
            "title": "Reference"
        }
    ],
    "tags": [],
    "created_by": {
        "id": "{{user_id}}",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com"
    },
    "last_modified_by": {
        "id": "{{user_id}}",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com"
    },
    "created_at": "2024-08-08T08:59:18.952Z",
    "updated_at": "2024-08-08T09:12:44.201Z"
}

Delete a Specific Codex Mitigation

To delete a specific codex mitigation, use this code:

axios.delete("/codex/mitigations/:id");

HTTP Request

DELETE https://api.devici.com/api/v1/codex/mitigations/:id

Delete Multiple Mitigations

To delete multiple mitigations, use this code:

axios.delete("/codex/mitigations/many", {
    data: {
        ids: ["{{mitigation_id}}"]
    }
});

HTTP Request

DELETE https://api.devici.com/api/v1/codex/mitigations/many

Request Body

Field Required Description
ids yes Array of mitigation UUIDs to delete

Codex Threats

Manage threats that belong to your organisation's custom Codex. Threats can reference codex attributes (as causing/neutralising) and codex mitigations. Those relationships can be set either on the create/update call or via the dedicated attach/detach endpoints.

Field Constraints

Field Constraint
title 1–256 characters, unique within the codex
description 1–1200 characters
priority One of critical, high, medium, low
resources Up to 5 entries; per entry: title 1–256, url 1–500
causedByIds / neutralizedByIds UUIDs of codex attributes (max 50 each). Must not overlap.
mitigationsIds UUIDs of codex mitigations (max 50)
tagsIds UUIDs of tags belonging to your organisation

Get All Codex Threats

To get all codex threats, use this code:

axios.get("/codex/threats?page=0&limit=20");

HTTP Request

GET https://api.devici.com/api/v1/codex/threats

Query Parameters

Parameter Required Default Description
page yes Page number (0-based)
limit yes Items per page (max 100)
sort no created_at Sort field
order no ASC ASC or DESC
text no Free-text search across title, description, and tag titles (1–20 chars)
priority no Filter by priority (repeatable: priority=high&priority=critical)
tagIds no Filter by tag UUIDs (repeatable)
createdByIds no Filter by creator UUIDs (repeatable)

The above command returns JSON structured like this:

{
    "items": [
        {
            "id": "{{threat_id}}",
            "title": "Threats1",
            "description": "Description Threats1",
            "priority": "low",
            "tags": [],
            "last_modified_by": {
                "id": "{{user_id}}",
                "first_name": "Jane",
                "last_name": "Doe",
                "email": "jane@example.com"
            },
            "created_at": "2024-08-08T14:19:42.080Z",
            "updated_at": "2024-08-08T14:19:42.080Z"
        }
    ],
    "count": 1
}

Search Threats

To search threats, use this code:

axios.get("/codex/threats/search?text={{some text}}");

HTTP Request

GET https://api.devici.com/api/v1/codex/threats/search

Query Parameters

Parameter Required Description
text yes Search query, 1–20 characters. Matches threat title.

The above command returns JSON structured like this:

[
    {
        "id": "{{threat_id}}",
        "title": "Threats1",
        "description": "Description Threats1",
        "priority": "low"
    }
]

Get a Specific Codex Threat

To get a specific codex threat, use this code:

axios.get("/codex/threats/:id");

HTTP Request

GET https://api.devici.com/api/v1/codex/threats/:id

The above command returns JSON structured like this:

{
    "id": "{{threat_id}}",
    "title": "Threats",
    "description": "Description Threats",
    "priority": "low",
    "resources": [
        {
            "url": "https://example.com",
            "title": "Reference"
        }
    ],
    "caused_by": [
        {
            "id": "{{attribute_id}}",
            "title": "Attribute"
        }
    ],
    "neutralized_by": [],
    "mitigations": [
        {
            "id": "{{mitigation_id}}",
            "title": "Mitigation"
        }
    ],
    "causedByIds": ["{{attribute_id}}"],
    "neutralizedByIds": [],
    "mitigationsIds": ["{{mitigation_id}}"],
    "tags": [],
    "created_by": {
        "id": "{{user_id}}",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com"
    },
    "last_modified_by": {
        "id": "{{user_id}}",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com"
    },
    "created_at": "2024-08-08T14:19:42.080Z",
    "updated_at": "2024-08-08T14:19:42.080Z"
}

Create a New Threat

To create a new threat, use this code:

axios.post("/codex/threats", {
    title: "New Threat",
    description: "Description for Threat",
    priority: "low",
    resources: [
        {
            url: "https://example.com",
            title: "Reference"
        }
    ],
    causedByIds: ["{{attribute_id}}"],
    neutralizedByIds: [],
    mitigationsIds: ["{{mitigation_id}}"],
    tagsIds: ["{{tag_id}}"]
});

HTTP Request

POST https://api.devici.com/api/v1/codex/threats

Request Body

Field Required Description
title yes 1–256 chars, unique within the codex
description yes 1–1200 chars
priority yes critical, high, medium, or low
resources no Up to 5 resource objects (url, title)
causedByIds no UUIDs of codex attributes that cause this threat (max 50). Must not overlap with neutralizedByIds.
neutralizedByIds no UUIDs of codex attributes that neutralise this threat (max 50)
mitigationsIds no UUIDs of codex mitigations (max 50)
tagsIds no UUIDs of tags

The above command returns JSON structured like this:

{
    "id": "{{threat_id}}",
    "title": "New Threat",
    "description": "Description for Threat",
    "priority": "low",
    "resources": [
        {
            "url": "https://example.com",
            "title": "Reference"
        }
    ],
    "caused_by": [
        {
            "id": "{{attribute_id}}",
            "title": "Attribute"
        }
    ],
    "neutralized_by": [],
    "mitigations": [
        {
            "id": "{{mitigation_id}}",
            "title": "Mitigation"
        }
    ],
    "causedByIds": ["{{attribute_id}}"],
    "neutralizedByIds": [],
    "mitigationsIds": ["{{mitigation_id}}"],
    "tags": [
        {
            "id": "{{tag_id}}",
            "title": "pii",
            "color": "#FF0000"
        }
    ],
    "created_by": {
        "id": "{{user_id}}",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com"
    },
    "last_modified_by": {
        "id": "{{user_id}}",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com"
    },
    "created_at": "2024-08-08T14:19:42.080Z",
    "updated_at": "2024-08-08T14:19:42.080Z"
}

Create Multiple Threats

To create multiple threats, use this code:

axios.post("/codex/threats/many", {
    threats: [
        {
            title: "Threats1",
            description: "Description Threats1",
            priority: "low",
            causedByIds: ["{{attribute_id}}"],
            mitigationsIds: ["{{mitigation_id}}"],
            tagsIds: ["{{tag_id}}"]
        },
        {
            title: "Threats2",
            description: "Description Threats2",
            priority: "medium"
        }
    ]
});

HTTP Request

POST https://api.devici.com/api/v1/codex/threats/many

Request Body

Field Required Description
threats yes Array of threat objects. Max 20 per request. Each object follows the same schema as POST /codex/threats. All titles within the array must be unique.

The above command returns JSON structured like this:

[
    {
        "id": "{{threat_id}}",
        "title": "Threats1",
        "description": "Description Threats1",
        "priority": "low",
        "resources": null,
        "caused_by": [
            {
                "id": "{{attribute_id}}",
                "title": "Attribute"
            }
        ],
        "neutralized_by": [],
        "mitigations": [
            {
                "id": "{{mitigation_id}}",
                "title": "Mitigation"
            }
        ],
        "causedByIds": ["{{attribute_id}}"],
        "neutralizedByIds": [],
        "mitigationsIds": ["{{mitigation_id}}"],
        "tags": [
            {
                "id": "{{tag_id}}",
                "title": "pii",
                "color": "#FF0000"
            }
        ],
        "created_by": {
            "id": "{{user_id}}",
            "first_name": "Jane",
            "last_name": "Doe",
            "email": "jane@example.com"
        },
        "last_modified_by": {
            "id": "{{user_id}}",
            "first_name": "Jane",
            "last_name": "Doe",
            "email": "jane@example.com"
        },
        "created_at": "2024-08-08T14:19:42.080Z",
        "updated_at": "2024-08-08T14:19:42.080Z"
    },
    {
        "id": "{{threat_id}}",
        "title": "Threats2",
        "description": "Description Threats2",
        "priority": "medium",
        "resources": null,
        "caused_by": [],
        "neutralized_by": [],
        "mitigations": [],
        "causedByIds": [],
        "neutralizedByIds": [],
        "mitigationsIds": [],
        "tags": [],
        "created_by": {
            "id": "{{user_id}}",
            "first_name": "Jane",
            "last_name": "Doe",
            "email": "jane@example.com"
        },
        "last_modified_by": {
            "id": "{{user_id}}",
            "first_name": "Jane",
            "last_name": "Doe",
            "email": "jane@example.com"
        },
        "created_at": "2024-08-08T14:19:42.080Z",
        "updated_at": "2024-08-08T14:19:42.080Z"
    }
]

Update a Specific Codex Threat

To update a specific codex threat, use this code:

axios.put("/codex/threats/:id", {
    title: "Updated Threat",
    description: "Updated Description",
    priority: "medium",
    resources: [
        {
            url: "https://example.com",
            title: "Updated Reference"
        }
    ],
    causedByIds: ["{{attribute_id}}"],
    neutralizedByIds: [],
    mitigationsIds: ["{{mitigation_id}}"],
    tagsIds: []
});

HTTP Request

PUT https://api.devici.com/api/v1/codex/threats/:id

Request Body

Field Required Description
title yes 1–256 chars
description yes 1–1200 chars
priority yes critical, high, medium, or low
resources no Full replacement. Up to 5 entries.
causedByIds no Full replacement of caused-by attribute mapping
neutralizedByIds no Full replacement of neutralised-by attribute mapping
mitigationsIds no Full replacement of mitigations mapping
tagsIds no Full replacement of tags

The above command returns JSON structured like this:

{
    "id": "{{threat_id}}",
    "title": "Updated Threat",
    "description": "Updated Description",
    "priority": "medium",
    "resources": [
        {
            "url": "https://example.com",
            "title": "Updated Reference"
        }
    ],
    "caused_by": [
        {
            "id": "{{attribute_id}}",
            "title": "Attribute"
        }
    ],
    "neutralized_by": [],
    "mitigations": [
        {
            "id": "{{mitigation_id}}",
            "title": "Mitigation"
        }
    ],
    "causedByIds": ["{{attribute_id}}"],
    "neutralizedByIds": [],
    "mitigationsIds": ["{{mitigation_id}}"],
    "tags": [],
    "created_by": {
        "id": "{{user_id}}",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com"
    },
    "last_modified_by": {
        "id": "{{user_id}}",
        "first_name": "Jane",
        "last_name": "Doe",
        "email": "jane@example.com"
    },
    "created_at": "2024-08-08T14:19:42.080Z",
    "updated_at": "2024-08-08T14:25:03.112Z"
}

Attach Attributes to a Threat

Adds attributes to a threat's caused_by or neutralized_by collection. Unlike PUT /:id, this is additive — use it when you want to grow the mapping without replacing it wholesale.

To attach attributes to a threat, use this code:

axios.post("/codex/threats/attach-attributes", {
    threatId: "{{threat_id}}",
    attributesIds: ["{{attribute_id}}"],
    type: "caused_by"
});

HTTP Request

POST https://api.devici.com/api/v1/codex/threats/attach-attributes

Request Body

Field Required Description
threatId yes UUID of the threat
attributesIds yes UUIDs of codex attributes (max 10)
type yes caused_by or neutralized

Returns the full threat (same shape as GET /codex/threats/:id).

Detach Attributes from a Threat

To detach attributes from a threat, use this code:

axios.post("/codex/threats/detach-attributes", {
    threatId: "{{threat_id}}",
    attributesIds: ["{{attribute_id}}"],
    type: "caused_by"
});

HTTP Request

POST https://api.devici.com/api/v1/codex/threats/detach-attributes

Request Body

Same as attach-attributes above. Returns the full threat.

Attach Mitigations to a Threat

To attach mitigations to a threat, use this code:

axios.post("/codex/threats/attach-mitigations", {
    threatId: "{{threat_id}}",
    mitigationsIds: ["{{mitigation_id}}"]
});

HTTP Request

POST https://api.devici.com/api/v1/codex/threats/attach-mitigations

Request Body

Field Required Description
threatId yes UUID of the threat
mitigationsIds yes UUIDs of codex mitigations (max 10)

Returns the full threat.

Detach Mitigations from a Threat

To detach mitigations from a threat, use this code:

axios.post("/codex/threats/detach-mitigations", {
    threatId: "{{threat_id}}",
    mitigationsIds: ["{{mitigation_id}}"]
});

HTTP Request

POST https://api.devici.com/api/v1/codex/threats/detach-mitigations

Request Body

Same as attach-mitigations above. Returns the full threat.

Delete a Specific Codex Threat

To delete a specific codex threat, use this code:

axios.delete("/codex/threats/:id");

HTTP Request

DELETE https://api.devici.com/api/v1/codex/threats/:id

Delete Multiple Threats

To delete multiple threats, use this code:

axios.delete("/codex/threats/many", {
    data: {
        ids: ["{{threat_id}}"]
    }
});

HTTP Request

DELETE https://api.devici.com/api/v1/codex/threats/many

Request Body

Field Required Description
ids yes Array of threat UUIDs to delete

Devici Codex Attributes

The Devici Codex provides read-only access to Devici's built-in security attributes. These are curated attributes maintained by Devici and cannot be modified via the API.

Get All Devici Codex Attributes

To get all Devici Codex attributes, use this code:

axios.get("/codex/built-in/attributes?page=0&limit=20");

HTTP Request

GET https://api.devici.com/api/v1/codex/built-in/attributes

Query Parameters

Parameter Required Default Description
page yes Page number (0-based)
limit yes Items per page (max 100)
sort no title Sort field: title, description, type, created_at, updated_at
order no ASC Sort order: ASC or DESC
text no Search by title or description (min 2 characters)
detailed no false Include caused_threats and neutralized_threats
types no Filter by type: functional, data

The above command returns JSON structured like this:

{
    "items": [
        {
            "id": "9509597d-50d8-462e-864d-9a8825a79175",
            "title": "3DES",
            "description": "Triple DES -- an enhancement of DES...",
            "type": "functional",
            "aliases": ["3DES"],
            "categories": [],
            "created_at": "2023-10-28T16:51:20.523Z",
            "updated_at": "2024-03-06T19:02:47.034Z"
        }
    ],
    "count": 1
}

With detailed=true, each item also includes:

{
    "id": "9509597d-50d8-462e-864d-9a8825a79175",
    "title": "3DES",
    "description": "Triple DES -- an enhancement of DES...",
    "type": "functional",
    "aliases": ["3DES"],
    "categories": [],
    "created_at": "2023-10-28T16:51:20.523Z",
    "updated_at": "2024-03-06T19:02:47.034Z",
    "assignable_to_components": ["process", "external_entity"],
    "caused_threats": [
        {
            "id": "a1b2c3d4-...",
            "title": "Weak Encryption",
            "priority": "high"
        }
    ],
    "neutralized_threats": [
        {
            "id": "e5f6g7h8-...",
            "title": "Brute Force Attack",
            "priority": "medium"
        }
    ]
}

Get a Specific Devici Codex Attribute

To get a specific Devici Codex attribute, use this code:

axios.get("/codex/built-in/attributes/:id");

HTTP Request

GET https://api.devici.com/api/v1/codex/built-in/attributes/:id

The above command returns JSON structured like this (always detailed):

{
    "id": "9509597d-50d8-462e-864d-9a8825a79175",
    "title": "3DES",
    "description": "Triple DES -- an enhancement of DES...",
    "type": "functional",
    "aliases": ["3DES"],
    "categories": [],
    "created_at": "2023-10-28T16:51:20.523Z",
    "updated_at": "2024-03-06T19:02:47.034Z",
    "assignable_to_components": ["process", "external_entity"],
    "caused_threats": [
        {
            "id": "a1b2c3d4-...",
            "title": "Weak Encryption",
            "priority": "high"
        }
    ],
    "neutralized_threats": [
        {
            "id": "e5f6g7h8-...",
            "title": "Brute Force Attack",
            "priority": "medium"
        }
    ]
}

Devici Codex Threats

The Devici Codex provides read-only access to Devici's built-in security threats. These are curated threats maintained by Devici and cannot be modified via the API.

Get All Devici Codex Threats

To get all Devici Codex threats, use this code:

axios.get("/codex/built-in/threats?page=0&limit=20");

HTTP Request

GET https://api.devici.com/api/v1/codex/built-in/threats

Query Parameters

Parameter Required Default Description
page yes Page number (0-based)
limit yes Items per page (max 100)
sort no title Sort field: title, description, priority, created_at, updated_at
order no ASC Sort order: ASC or DESC
text no Search by title or description (min 2 characters)
detailed no false Include source, caused_by, neutralized_by, and mitigations
priority no Filter by priority: low, medium, high, critical (repeatable)
methodologyIds no Filter by methodology UUIDs (repeatable). See /codex/built-in/threats/catalog for the available methodologies.
categoryIds no Filter by category UUIDs (repeatable). When both methodologyIds and categoryIds are provided, categoryIds wins (categories already imply their methodology).

The above command returns JSON structured like this:

{
    "items": [
        {
            "id": "f1a2b3c4-...",
            "title": "SQL Injection",
            "description": "Injection of malicious SQL queries...",
            "priority": "high",
            "resources": [
                {
                    "title": "OWASP SQL Injection",
                    "url": "https://owasp.org/www-community/attacks/SQL_Injection"
                }
            ],
            "created_at": "2024-08-08T14:19:42.080Z",
            "updated_at": "2024-08-08T14:19:42.080Z"
        }
    ],
    "count": 1
}

With detailed=true, each item also includes source, caused_by, neutralized_by, and mitigations:

{
    "id": "f1a2b3c4-...",
    "title": "SQL Injection",
    "description": "Injection of malicious SQL queries...",
    "priority": "high",
    "resources": [
        {
            "title": "OWASP SQL Injection",
            "url": "https://owasp.org/www-community/attacks/SQL_Injection"
        }
    ],
    "source": {
        "methodology": {
            "id": "m1a2b3c4-...",
            "title": "STRIDE"
        },
        "category": {
            "id": "c1a2b3c4-...",
            "title": "Tampering"
        }
    },
    "caused_by": [
        {
            "id": "a1b2c3d4-...",
            "title": "Unsanitized Input",
            "type": "functional"
        }
    ],
    "neutralized_by": [
        {
            "id": "a5b6c7d8-...",
            "title": "Input Validation",
            "type": "functional"
        }
    ],
    "mitigations": [
        {
            "id": "b1c2d3e4-...",
            "title": "Parameterized Queries",
            "definition": "Separates SQL logic from data input"
        }
    ],
    "created_at": "2024-08-08T14:19:42.080Z",
    "updated_at": "2024-08-08T14:19:42.080Z"
}

source may be null when a threat is not associated with any methodology.

Get Threats Catalog

Returns the methodologies and their categories that the built-in threats are organised by. Use the returned UUIDs to filter the threats list via methodologyIds / categoryIds.

To get the threats catalog, use this code:

axios.get("/codex/built-in/threats/catalog");

HTTP Request

GET https://api.devici.com/api/v1/codex/built-in/threats/catalog

Query Parameters

Parameter Required Default Description
page no 0 Page number (0-based)
limit no 20 Items per page (max 100)
all no false When true, returns all methodologies (paging is ignored)

The above command returns JSON structured like this:

{
    "items": [
        {
            "id": "m1a2b3c4-...",
            "title": "STRIDE",
            "description": "Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, Elevation of privilege",
            "categories": [
                {
                    "id": "c1a2b3c4-...",
                    "title": "Tampering",
                    "description": "Modifying data or code without authorisation"
                },
                {
                    "id": "c2b3c4d5-...",
                    "title": "Spoofing",
                    "description": "Impersonating another user or process"
                }
            ]
        }
    ],
    "count": 1
}

Get a Specific Devici Codex Threat

To get a specific Devici Codex threat, use this code:

axios.get("/codex/built-in/threats/:id");

HTTP Request

GET https://api.devici.com/api/v1/codex/built-in/threats/:id

The above command returns JSON structured like this (always detailed):

{
    "id": "f1a2b3c4-...",
    "title": "SQL Injection",
    "description": "Injection of malicious SQL queries...",
    "priority": "high",
    "resources": [
        {
            "title": "OWASP SQL Injection",
            "url": "https://owasp.org/www-community/attacks/SQL_Injection"
        }
    ],
    "source": {
        "methodology": {
            "id": "m1a2b3c4-...",
            "title": "STRIDE"
        },
        "category": {
            "id": "c1a2b3c4-...",
            "title": "Tampering"
        }
    },
    "caused_by": [
        {
            "id": "a1b2c3d4-...",
            "title": "Unsanitized Input",
            "type": "functional"
        }
    ],
    "neutralized_by": [
        {
            "id": "a5b6c7d8-...",
            "title": "Input Validation",
            "type": "functional"
        }
    ],
    "mitigations": [
        {
            "id": "b1c2d3e4-...",
            "title": "Parameterized Queries",
            "definition": "Separates SQL logic from data input"
        }
    ],
    "created_at": "2024-08-08T14:19:42.080Z",
    "updated_at": "2024-08-08T14:19:42.080Z"
}

Devici Codex Mitigations

The Devici Codex provides read-only access to Devici's built-in security mitigations. These are curated mitigations maintained by Devici and cannot be modified via the API.

Get All Devici Codex Mitigations

To get all Devici Codex mitigations, use this code:

axios.get("/codex/built-in/mitigations?page=0&limit=20");

HTTP Request

GET https://api.devici.com/api/v1/codex/built-in/mitigations

Query Parameters

Parameter Required Default Description
page yes Page number (0-based)
limit yes Items per page (max 100)
sort no title Sort field: title, definition, created_at, updated_at
order no ASC Sort order: ASC or DESC
text no Search by title or definition (min 2 characters)
detailed no false Include source, explanation, consideration, example, and question
categoryIds no Filter by category UUIDs (repeatable). See /codex/built-in/mitigations/catalog for the available categories.

The above command returns JSON structured like this:

{
    "items": [
        {
            "id": "b1c2d3e4-...",
            "title": "Parameterized Queries",
            "definition": "Separates SQL logic from data input",
            "resources": [
                {
                    "title": "OWASP Guide",
                    "url": "https://owasp.org/www-community/..."
                }
            ],
            "created_at": "2024-08-08T08:59:18.952Z",
            "updated_at": "2024-08-08T08:59:18.952Z"
        }
    ],
    "count": 1
}

With detailed=true, each item also includes source, explanation, consideration, example, and question:

{
    "id": "b1c2d3e4-...",
    "title": "Parameterized Queries",
    "definition": "Separates SQL logic from data input",
    "resources": [
        {
            "title": "OWASP Guide",
            "url": "https://owasp.org/www-community/..."
        }
    ],
    "source": {
        "category": {
            "id": "c5a6b7c8-...",
            "title": "Input Validation"
        }
    },
    "explanation": "Prevents attackers from injecting malicious SQL by binding parameters.",
    "consideration": "Requires developer adoption. May require refactoring legacy code.",
    "example": "Using prepared statements in Java",
    "question": "Where is user input used in queries?",
    "created_at": "2024-08-08T08:59:18.952Z",
    "updated_at": "2024-08-08T08:59:18.952Z"
}

source may be null when a mitigation is not associated with any category.

Get Mitigations Catalog

Returns the categories that the built-in mitigations are organised by. Use the returned UUIDs to filter the mitigations list via categoryIds.

To get the mitigations catalog, use this code:

axios.get("/codex/built-in/mitigations/catalog");

HTTP Request

GET https://api.devici.com/api/v1/codex/built-in/mitigations/catalog

Query Parameters

Parameter Required Default Description
page no 0 Page number (0-based)
limit no 20 Items per page (max 100)
all no false When true, returns every category (paging is ignored)

The above command returns JSON structured like this:

{
    "items": [
        {
            "id": "c5a6b7c8-...",
            "title": "Input Validation",
            "description": "Validating and sanitising user-supplied data."
        },
        {
            "id": "c6b7c8d9-...",
            "title": "Access Control",
            "description": "Restricting privileges to the minimum required."
        }
    ],
    "count": 2
}

Get a Specific Devici Codex Mitigation

To get a specific Devici Codex mitigation, use this code:

axios.get("/codex/built-in/mitigations/:id");

HTTP Request

GET https://api.devici.com/api/v1/codex/built-in/mitigations/:id

The above command returns JSON structured like this (always detailed):

{
    "id": "b1c2d3e4-...",
    "title": "Parameterized Queries",
    "definition": "Separates SQL logic from data input",
    "source": {
        "category": {
            "id": "c5a6b7c8-...",
            "title": "Input Validation"
        }
    },
    "resources": [
        {
            "title": "OWASP Guide",
            "url": "https://owasp.org/www-community/..."
        }
    ],
    "created_at": "2024-08-08T08:59:18.952Z",
    "updated_at": "2024-08-08T08:59:18.952Z",
    "explanation": "Prevents attackers from injecting malicious SQL by binding parameters.",
    "consideration": "Requires developer adoption. May require refactoring legacy code.",
    "example": "Using prepared statements in Java",
    "question": "Where is user input used in queries?"
}

Audit Logs

Get Audit Logs Actions

To get Audit Logs Actions use this code:

axios.get("/audit-log/types");
[
  "collection-created",
  "collection-deleted",
  "collection-owner-changed",
  "threat-model-created",
  "threat-model-deleted",
  "canvas-created",
  "canvas-deleted",
  "components-deleted",
  "customer-settings-changed",
  "user-deleted",
  "user-role-changed",
  "user-invited",
  "user-toggled-mfa",
  "saml-settings-created",
  "saml-settings-changed",
  "saml-settings-deleted",
  "mfa-enabled",
  "mfa-disabled",
  "session-duration-changed",
  "signed-up",
  "signed-in",
  "signed-out",
  "password-changed",
  "password-forgot",
  "app-integration-created",
  "app-integration-updated",
  "app-integration-deleted",
  "app-integration-test",
  "api-token-created",
  "api-token-updated",
  "api-token-scopes-updated",
  "api-token-ip-whitelist-updated",
  "api-token-transferred",
  "api-token-credentials-regenerated",
  "api-token-disabled",
  "api-token-deleted"
]

This endpoint retrieves all Action for filtering Audit Logs.

HTTP Request

GET https://api.devici.com/api/v1/audit-log/types

Get All Audit Logs

To get all Audit Logs use this code:

axios.get("/audit-log/?limit=1&actions=api-token-regenerated");
{
  "items": [
    {
      "logId": "{{canvas_id}}",
      "action": "API token renenerate",
      "userIp": "123.123.123.123",
      "entityId": "{{entity_id}}}",
      "timestamp": "2024-05-08T16:27:08.765Z",
      "expiresAt": "17457498341",
      "user": {
        "id": "{{user_id}}",
        "email": "johndoe@mail.com",
        "first_name": "John",
        "last_name": "Doe",
        "role": "admin"
      }
    }
  ],
  "nextKey": "{{next_key_id}}"
}

This endpoint retrieves all Audit Logs.

HTTP Request

GET https://api.devici.com/api/v1/audit-log/?limit=1&nextKey={{next_key_id}}&actions=api-token-regenerated

Query Parameters

Parameter Default Description
limit 25 Count of items per request
users - Filter by specific user(s)
actions - Filter by specific action(s)
start 1 month before current date Filter by date (start date), format: yyyy-mm-dd
end Current date Filter by date (end date), format: yyyy-mm-dd
nextKey - Use "nextKey" from previous response to get the next chunk of data

Export on CSV

To export Audit Logs via CSV use this code:

axios.get("/audit-log/csv");
CSV file example:

Action,User,User Ip,Timestamp,Details
API token regenerate,John Doe,123.123.123.123,1/24/2025,-
Signed in,John Doe,123.123.123.123,1/24/2025,-
Threat Model created,John Doe,123.123.123.123,1/22/2025,Title: Draft threat model | Collection: New Collection for test syslog
Signed in,John Doe,123.123.123.123,1/22/2025,-
Collection deleted,John Doe,123.123.123.123,1/21/2025,Title: Edited Collection257384
Threat Model created,John Doe,123.123.123.123,1/20/2025,Title: brave's first threat model | Collection: Default_collection
Signed in,John Doe,123.123.123.1231,1/20/2025,-
Collection deleted,John Doe,123.123.123.123,1/17/2025,Title: Edited Collection244503
...

This endpoint retrieves all Action for filtering Audit Logs.

HTTP Request

GET https://api.devici.com/api/v1/audit-log/csv?actions=api-token-regenerated&start=2025-01-01&end=2025-02-01

Query Parameters

Parameter Default Description
users - Filter by specific user(s)
actions - Filter by specific action(s)
start 1 month before current date Filter by date (start date), format: yyyy-mm-dd
end Current date Filter by date (end date), format: yyyy-mm-dd

Reports

Get Threat Models Reports

To get Threat Models Reports use this code:

axios.get("/reports/threat-models/?limit=1&page=0&start=01-01-2025&end=01-31-2025");
{
  "items": [
    {
      "id": "{{threat_model_id}}",
      "created_at": "2024-10-10T14:58:26.981Z",
      "title": "Title",
      "status": "Threats & Mitigations",
      "priority": "high",
      "owner": {
        "first_name": "Jon",
        "last_name": "Doe"
      },
      "canvasCount": 1,
      "mitigatedThreats": 0,
      "unmitigatedThreats": 4,
      "canvases": [
        {
          "id": "{{canvas_id}}",
          "title": "Canvas 1"
        }
      ],
      "collection": {
        "id": "{{collection_id}}",
        "title": "Collection"
      }
    }
  ],
  "count": 1
}

This endpoint retrieves Threat Models report.

HTTP Request

GET https://api.devici.com/api/v1/reports/threat-models/?limit=1&page=0&start=01-01-2025&end=01-31-2025

Query Parameters

Parameter Default Description
limit 20 Count of items per request
page 1 Page
start - The starting point or timestamp for the query range
end - The endpoint or timestamp for the query range
projectId - Filter by a specific collection
runningId - Filter by a specific running

Get Threat Models Reports via PDF

To get Threat Models Reports via PDF use this code:

axios.get("/reports/threat-models-pdf?start=01-01-2025&end=01-31-2026");
A PDF file will be received.

This endpoint retrieves Threat Models report via PDF file.

HTTP Request

GET https://api.devici.com/api/v1/reports/threat-models-pdf?start=01-01-2025&end=01-31-2026

Query Parameters

Parameter Default Description
start - The starting point or timestamp for the query range
end - The endpoint or timestamp for the query range

Get Threat Models Reports via CSV

To get Threat Models Reports via CSV use this code:

axios.get("/reports/threat-models-csv?start=01-01-2025&end=01-31-2026");
CSV file example:

Title,Collection,Priority,Status,Mitigated Threats,Unmitigated Threats,Responsible,Canvases,Created At
Edited Test Model244,Default_collection,high,Threats & Mitigations,0,4,John Doe,1,10/10/2024
Default_collection Draft threat model,Default_collection,medium,Representation,0,0,John Doe,1,10/14/2024
Draft threat model,Default_collection,medium,Threats & Mitigations,0,0,John Doe,1,10/14/2024
Draft threat model,Default_collection,medium,Threats & Mitigations,0,0,John Doe,1,10/14/2024
Single node,Default_collection,medium,Threats & Mitigations,0,0,John Doe,1,10/14/2024
Draft threat model,Default_collection,medium,Representation,0,0,John Doe,1,10/14/2024
Draft threat model,Default_collection,medium,Representation,0,0,John Doe,1,10/15/2024
Draft threat model,Default_collection,medium,Representation,0,0,John Doe,1,10/15/2024

This endpoint retrieves Threat Models report via CSV file.

HTTP Request

GET https://api.devici.com/api/v1/reports/threat-models-csv?start=01-01-2025&end=01-31-2026

Query Parameters

Parameter Default Description
start - The starting point or timestamp for the query range
end - The endpoint or timestamp for the query range

Dashboard

Get Dashboard Charts Types

To get Dashboard charts types use this code:

axios.get("/dashboard/types");
[
    "total-users",
    "top-threats",
    "top-attributes",
    "top-mitigations",
    "top-risk-threat-models",
    "threat-models-by-project",
    "threats-vs-mitigated-threats",
    "threat-models-by-status-and-priority"
]

This endpoint retrieves Dashboard Charts Types.

HTTP Request

GET https://api.devici.com/api/v1/dashboard/types

Get Dashboard data by specific chart type

To get Dashboard data by specific chart type use this code:

axios.get("/dashboard/?limit=1&page=0&start=01-01-2025&end=01-31-2025&type=top-threats");
[
    {
        "name": "Denial of Service",
        "count": "796"
    },
    {
        "name": "Information Disclosure",
        "count": "794"
    },
    {
        "name": "Tampering",
        "count": "790"
    },
    {
        "name": "Repudiation",
        "count": "523"
    },
    {
        "name": "Spoofing",
        "count": "488"
    }
]

This endpoint retrieves Dashboard data by specific chart type.

HTTP Request

GET https://api.devici.com/api/v1/dashboard/?limit=1&page=0&start=01-01-2025&end=01-31-2025&type=top-threats

Query Parameters

Parameter Default Description
limit 20 Count of items per request
page 1 Page
type - Use one of the types from /dashboard/types
start - The starting point or timestamp for the query range
end - The endpoint or timestamp for the query range
projectId - Filter by a specific collection
runningId - Filter by a specific running

Teams

Get Teams

To get a list of all teams use this code:

axios.get("/teams/?limit=20&page=0");
{
  "items": [
    {
      "id": "{{team_id}}",
      "title": "Alpha",
      "users": ["{{user_id}}"],
      "created_at": "2025-02-10T15:01:41.411Z",
      "collections": ["{{collection_id}}", "{{collection_id}}"]
    }
  ],
  "count": 1
}

Use this endpoint to retrieve a list of all teams.

HTTP Request

GET https://api.devici.com/api/v1/teams/?limit=20&page=0

Query Parameters

Parameter Default Description
limit 20 Count of items per request
page 1 Page

Get a Specific Team

To get specific team by id use this code:

axios.get("/teams/:id");

The above command returns JSON structured like this:

{
  "id": "{{team_id}}",
  "title": "Alpha",
  "users": [
    {
      "id": "{{user_id}}",
      "email": "{{user_email}}",
      "first_name": "First",
      "last_name": "Last",
      "role": "user"
    }
  ],
  "collections": [
    {
      "id": "{{collection_id}}",
      "title": "Collection title",
      "permission": "write"
    }
  ]
}

Use this endpoint to retrieve details of a specific team by its ID.

HTTP Request

GET https://api.devici.com/api/v1/teams/:id

Create Team

To create a new team use this code:

axios.post("/teams", {
  payload: [
    {
      title: "Team 11111",
      usersIds: ["{{user_id}}"],
      collectionsPermissions: [{
        collectionId: "{{collection_id}}",
        permission: "read"
      }]
    },
    {
      title: "Team 22222",
      usersIds: ["{{user_id}}"],
      collectionsPermissions: [{
        collectionId: "{{collection_id}}",
        permission: "write"
      }]
    }
  ]
});

Use this endpoint to create a new team.

permission field must be one of read | write | manage

HTTP Request

POST https://api.devici.com/api/v1/teams

Update Teams

To update multiple teams use this code:

axios.put("/teams", {
  payload: [
    {
      id: "{{team_id}}",
      title: "Team updated title",
      usersIds: ["{{user_id}}"],
      collectionsPermissions: [{
        collectionId: "{{collection_id}}",
        permission: "read"
      }]
    }
  ]
});

Use this endpoint to update multiple teams in one request.

HTTP Request

PUT https://api.devici.com/api/v1/teams

Delete Specific Team

To delete specific team by id use this code:

axios.delete("/teams/:id");

Use this endpoint to delete a specific team by its ID.

HTTP Request

DELETE https://api.devici.com/api/v1/teams/:id

Errors

The Devici API uses the following error codes:

Error Code Meaning
400 Bad Request -- Your request is invalid.
401 Unauthorized -- Your API key is wrong.
403 Forbidden -- The entity requested is hidden for administrators only.
404 Not Found -- The specified entity could not be found.
405 Method Not Allowed -- You tried to access a entity with an invalid method.
406 Not Acceptable -- You requested a format that isn't json.
410 Gone -- The entity requested has been removed from our servers.
418 I'm a teapot.
429 Too Many Requests -- You're requesting too many entities! Slow down!
500 Internal Server Error -- We had a problem with our server. Try again later.
503 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.