NAV

Introduction

The Cobalt API gives you REST access to Organizations, Assets, Pentests, Findings, and Events.

API Versions

Background

When the Cobalt API was introduced in 2021, it was read-only but plans were already in place to add write support. Initially this was envisioned as being added to v1 of the API.

A close examination of v1 of the API will reveal an odd mix of identifiers - numeric IDs, tokens, and so on. For the sake of simplicity and consistency Cobalt decided to migrate to a common identifier format. Due to the difficulty of maintaining full compatibility across different combinations of identifiers, we decided to introduce v2 of the API exclusively using the new identifier format.

v1 is currently maintained but will not see any new features.

Authentication

To authorize, give this a try:

curl https://api.cobalt.io/orgs \
  -H "Authorization: Bearer YOUR-PERSONAL-API-TOKEN"

Make sure to replace YOUR-PERSONAL-API-TOKEN with your actual API token.

Cobalt uses API tokens to allow access to various endpoints. You can create a new Cobalt API token from within your Cobalt profile.

Cobalt expects the API token to be included in all API requests to the server in a header that looks like the following:

Authorization: Bearer YOUR-PERSONAL-API-TOKEN

Organizations

Get All Organizations

curl -X GET "https://api.cobalt.io/orgs" \
  -H "Accept: application/vnd.cobalt.v1+json" \
  -H "Authorization: Bearer YOUR-PERSONAL-API-TOKEN"

The above command returns JSON structured like this:

{
  "data": [
    {
      "resource": {
        "id": "or_A2bb4FE",
        "name": "Acme Corp.",
        "token": "e9d6da*********0e8ad"
      },
      "links": {
        "ui": {
          "url": "https://api.cobalt.io/links/eyJ0eXBlIjoic29tZXRoaW5nIiwib3JnU2x1ZyI6ImNvYmFsdCIsInBlbnRlc3RUYWciOiJz="
        }
      }
    },
    {
      "resource": {
        "id": "or_UX2Fg3",
        "name": "Lorem Corp.",
        "token": "dfd6da*********0e8ad"
      },
      "links": {
        "ui": {
          "url": "https://api.cobalt.io/links/eyJ0eXBlIjoic29tZXRoaW5nIiwib3JnU2x1ZyI6ImNvYmFsdCIsInBlbnRlc3RUYWciOiJz="
        }
      }
    }
  ],
  "pagination": {
    "next_page": "/orgs?cursor=a1b2c3d4",
    "prev_page": "/orgs?cursor=4d3c2b1a"
  }
}

This endpoint retrieves a list of organizations, i.e. orgs, that you belong to. Save the token field to be used in your X-Org-Token header in subsequent calls in querying for assets, findings, pentests and events that belong to that organization.

HTTP Request

GET https://api.cobalt.io/orgs

URL Parameters

Parameter Default Description
cursor N/A Used for pagination, e.g. https://api.cobalt.io/orgs?cursor=a1b2c3d4
limit 10 If specified, returns only a specified amount of organizations, e.g. https://api.cobalt.io/orgs?limit=5

Response Fields

Field Description
id A unique ID representing the organization. Starts with or_
name The name of the organization
token The organization token you’ll need in subsequent calls
links.ui.url A link to redirect an authorized user to this organization in the Cobalt web application

Assets

Get All Assets

curl -X GET "https://api.cobalt.io/assets" \
  -H "Accept: application/vnd.cobalt.v1+json" \
  -H "Authorization: Bearer YOUR-PERSONAL-API-TOKEN" \
  -H "X-Org-Token: YOUR-V1-ORGANIZATION-TOKEN"

The above command returns JSON structured like this:

{
  "data": [
    {
      "resource": {
        "id": "as_rvZRC5Y",
        "title": "Acme Corp. HR System",
        "description": "HR system of the Acme Corp. holding sensitive employee data",
        "asset_type": "web",
        "logo": "https://s3.amazonaws.com/acmecorp/uploads/attachment/file/12345/cat.jpeg?something=1",
        "attachments": [
          {
            "token": "att_yYXZodA",
            "download_url": "https://s3.amazonaws.com/acmecorp/uploads/attachment/file/12345/rainbow.jpeg?something=1"
          }
        ]
      },
      "links": {
        "ui": {
          "url": "https://api.cobalt.io/links/eyJ0eXBlIjoic29tZXRoaW5nIiwib3JnU2x1ZyI6ImNvYmFsdCIsInBlbnRlc3RUYWciOiJz="
        }
      }
    }
  ],
  "pagination": {
    "next_page": "/assets?cursor=a1b2c3d4",
    "prev_page": "/assets?cursor=4d3c2b1a"
  }
}

This endpoint retrieves a list of assets that belong to the organization specified in the X-Org-Token header.

HTTP Request

GET https://api.cobalt.io/assets

URL Parameters

Parameter Default Description
cursor N/A Used for pagination, e.g. https://api.cobalt.io/assets?cursor=a1b2c3d4
limit 10 If specified, returns only a specified amount of assets, e.g. https://api.cobalt.io/assets?limit=5

Response Fields

Field Description
id A unique ID representing the asset. Starts with as_
title The title of the asset; set by user creating the asset
description A description of the asset; set by user creating the asset
asset_type An asset type, such as; api, cloud_config, external_network, internal_network, mobile, web, web_plus_api, web_plus_mobile
links.ui.url A link to redirect an authorized user to this asset in the Cobalt web application
logo A link pointing the location of the uploaded asset logo
attachments A list of asset attachments

Pentests

Get All Pentests

curl -X GET "https://api.cobalt.io/pentests" \
  -H "Accept: application/vnd.cobalt.v1+json" \
  -H "Authorization: Bearer YOUR-PERSONAL-API-TOKEN" \
  -H "X-Org-Token: YOUR-V1-ORGANIZATION-TOKEN"

The above command returns JSON structured like this:

{
  "data": [
    {
      "resource": {
        "id": "pt_rVShby8",
        "title": "HR System Security Test 2022-Q4",
        "objectives": "Coverage of OWASP top 10, ASVS and application logic.",
        "state": "new",
        "tag": "#PT5940",
        "asset_id": "as_0EY8V1C",
        "platform_tags": [
          "rails",
          "ruby",
          "aws"
        ],
        "methodology": "web",
        "targets": [
          "https://example.com",
          "192.168.1.1"
        ],
        "start_date": "Dec 11 2019",
        "end_date": "Dec 25 2019"
      },
      "links": {
        "ui": {
          "url": "https://api.cobalt.io/links/eyJ0eXBlIjoic29tZXRoaW5nIiwib3JnU2x1ZyI6ImNvYmFsdCIsInBlbnRlc3RUYWciOiJz="
        }
      }
    }
  ],
  "pagination": {
    "next_page": "/pentests?cursor=a1b2c3d4",
    "prev_page": "/pentests?cursor=4d3c2b1a"
  }
}

This endpoint retrieves a list of all pentests that belong to the organization specified in the X-Org-Token header.

HTTP Request

GET https://api.cobalt.io/pentests

URL Parameters

Parameter Default Description
asset N/A If specified, returns pentests scoped to this asset id, e.g. https://api.cobalt.io/pentests?asset=as_rvZRC5Y
cursor N/A Used for pagination, e.g. https://api.cobalt.io/pentests?cursor=a1b2c3d4
limit 1000 If specified, returns only a specified amount of pentests, e.g. https://api.cobalt.io/pentests?limit=5

Response Fields

Field Description
id A unique ID representing the pentest. Starts with pt_
title The title of the returned pentest.
objectives The objectives of the pentest. E.g. “Coverage of OWASP Top 10”
asset_id ID of the asset that the returned pentest belongs to
platform_tags Tech stack of the target. E.g. java, kotlin, ruby, aws, and so on.
methodology Pentest methodology. Web, API, Web+API, Mobile, External Network and so on.
targets Targetted IP addresses, domains, services, and so on.
start_date The starting date of the pentest. Format: Dec 11 2019
end_date The ending date of the pentest. Format: Dec 11 2019
state new, in_review, planned, cancelled, live, remediation, or closed
links.ui.url A link to redirect an authorized user to this pentest in the Cobalt web application

Findings

Get All Findings

curl -X GET "https://api.cobalt.io/findings" \
  -H "Accept: application/vnd.cobalt.v1+json" \
  -H "Authorization: Bearer YOUR-PERSONAL-API-TOKEN" \
  -H "X-Org-Token: YOUR-V1-ORGANIZATION-TOKEN"

The above command returns JSON structured like this:

{
  "data": [
    {
      "resource": {
        "id": "vu_ZzZuekb",
        "tag": "#PT3334_37",
        "title": "XSS vulnerability",
        "description": "Cross-Site Scripting (XSS) attacks are a type of injection, in which malicious scripts...",
        "type_category": "Cross-Site Scripting (XSS)",
        "labels": [
          {
            "name": "Your label"
          }
        ],
        "impact": 5,
        "likelihood": 4,
        "severity": "high",
        "affected_targets": [
          "https://example.com",
          "192.168.1.1"
        ],
        "proof_of_concept": "Here you can see...",
        "suggested_fix": "Ensure this...",
        "pentest_id": "pt_9Ig1234",
        "asset_id": "as_cwrsqsL",
        "log": [
          {
            "action": "created",
            "timestamp": "2021-04-01T15:13:24.322Z"
          },
          {
            "action": "likelihood_changed",
            "value": 4,
            "timestamp": "2021-04-01T15:14:05.856Z"
          },
          {
            "action": "impact_changed",
            "value": 5,
            "timestamp": "2021-04-01T15:14:05.856Z"
          },
          {
            "action": "state_changed",
            "value": "need_fix",
            "timestamp": "2021-04-01T15:14:06.757Z"
          },
          {
            "action": "state_changed",
            "value": "check_fix",
            "timestamp": "2021-04-01T15:14:57.845Z"
          }
        ],
        "state": "check_fix"
      },
      "links": {
        "ui": {
          "url": "https://api.cobalt.io/links/eyJ0eXBlIjoic29tZXRoaW5nIiwib3JnU2x1ZyI6ImNvYmFsdCIsInBlbnRlc3RUYWciOiJz="
        }
      }
    }
  ],
  "pagination": {
    "next_page": "/findings?cursor=a1b2c3d4",
    "prev_page": "/findings?cursor=4d3c2b1a"
  }
}

This endpoint retrieves a list of all pentest findings that belong to the organization specified in the X-Org-Token header, filterable by pentest_id or asset_id. The log array presents a history of each finding and corresponding timestamp.

Calculations

We follow the standard risk model described by OWASP, where:

Risk = Impact * Likelihood

Cobalt Risk Input Fields:

Cobalt Risk Classification (severity, a.k.a. criticality):

Category Score Description
critical 25 Includes vulnerabilities that require immediate attention.
high 16-24 Impacts the security of your application/platform/hardware, including supported systems. Includes high probability vulnerabilities with a high business impact.
medium 5-15 Includes vulnerabilities that are: medium risk, medium impact; low risk, high impact; high risk, low impact.
low 2-4 Specifies common vulnerabilities with minimal impact.
informational 1 Notes vulnerabilities of minimal risk to your business.

HTTP Request

GET https://api.cobalt.io/findings

GET https://api.cobalt.io/findings?pentest=pt_9Ig1234

GET https://api.cobalt.io/findings?asset=as_cwrsqsL

URL Parameters

Parameter Default Description
cursor N/A Used for pagination, e.g. https://api.cobalt.io/findings?cursor=a1b2c3d4
limit 1000 If specified, returns only a specified amount of findings, e.g. https://api.cobalt.io/findings?limit=5
pentest N/A If specified, returns findings scoped to this pentest id, e.g. https://api.cobalt.io/findings?pentest=pt_9Ig1234
asset N/A If specified, returns findings scoped to this asset id, e.g. https://api.cobalt.io/findings?asset=as_cwrsqsL

Response Fields

Field Enum Types
log created, impact_changed, likelihood_changed, state_changed
severity null, low, medium, high (aka criticality. will be null if likelihood/impact have not yet been set by the pentester)
state new, triaging, need_fix, wont_fix, valid_fix, check_fix, invalid, carried_over
type_category XSS, SQLi, … (about 30 more via the Cobalt Taxonomy)
links.ui.url A link to redirect an authorized user to this finding in the Cobalt web application

State

Events

Get All Events

curl -X GET "https://api.cobalt.io/events" \
  -H "Accept: application/vnd.cobalt.v1+json" \
  -H "Authorization: Bearer YOUR-PERSONAL-API-TOKEN"

The above command returns JSON structured like this:

{
  "data": [
    {
      "resource": {
        "id": "277603",
        "action": "comment_created",
        "subject": {
          "id": "277603",
          "type": "comment"
        },
        "timestamp": "2022-05-03T01:34:21.587Z"
      }
    },
    {
      "resource": {
        "id": "277600",
        "action": "pentest_deleted",
        "subject": {
          "id": "277600",
          "type": "program"
        },
        "timestamp": "2022-05-03T01:34:21.587Z"
      }
    },
    {
      "resource": {
        "id": "277567",
        "action": "finding_created",
        "subject": {
          "id": "277567",
          "type": "vulnerability"
        },
        "timestamp": "2022-05-03T01:34:21.587Z"
      }
    }
  ],
  "pagination": {
    "next_page": "/events?cursor=a1b2c3d4",
    "prev_page": "/events?cursor=4d3c2b1a"
  }
}

This endpoint retrieves a list of all events for your account.

HTTP Request

GET https://api.cobalt.io/events

URL Parameters

Parameter Default Description
cursor N/A Used for pagination, e.g. https://api.cobalt.io/events?cursor=a1b2c3d4
limit 10 If specified, returns only a specified amount of events, e.g. https://api.cobalt.io/events?limit=5

Tokens

Get All Tokens

curl -X GET "https://api.cobalt.io/tokens" \
  -H "Accept: application/vnd.cobalt.v1+json" \
  -H "Authorization: Bearer YOUR-PERSONAL-API-TOKEN"

The above command returns JSON structured like this:

{
  "data": [
    {
      "resource": {
        "id": "api_Dge3LsHMjtX8SGEk4a8nux",
        "last_characters": "9qy7",
        "name": "Lorem ipsum",
        "expire_at": null
      }
    }
  ],
  "pagination": {
    "next_page": null,
    "prev_page": null
  }
}

This endpoint retrieves a list of all tokens that belong to you.

HTTP Request

GET https://api.cobalt.io/tokens

URL Parameters

Parameter Default Description
cursor N/A Used for pagination, e.g. https://api.cobalt.io/tokens?cursor=a1b2c3d4
limit 10 If specified, returns only a specified amount of tokens, e.g. https://api.cobalt.io/tokens?limit=5

Response Fields

Field Description
id A unique ID representing the token. Starts with api_
name Name of the API token
last_characters Last four characters of your token, so that you can recognize tokens even if they have the same name
expire_at null (not currently implemented)

Refresh Token

curl -X POST "https://api.cobalt.io/tokens/YOUR-TOKEN-ID/refresh" \
  -H "Accept: application/vnd.cobalt.v1+json" \
  -H "Authorization: Bearer YOUR-PERSONAL-API-TOKEN"

The above command returns JSON structured like this:

{
  "id": "api_Dge3LsHMjtX8SGEk4a8nux",
  "secret": "YOUR-NEW-PERSONAL-API-TOKEN",
  "name": "Lorem ipsum",
  "expire_at": null
}

You can revoke an existing token and issue a new one with the same name by making a POST request to the token refresh endpoint.

Process:

If you’ve forgotten your token, you can always re-authenticate in the Cobalt web app. Go to your profile, revoke the old token you’ve forgotten, and generate a new token.

HTTP Request

POST https://api.cobalt.io/tokens/YOUR-TOKEN-ID/refresh

Response Fields

Field Description
id A unique ID representing the new token. Starts with api_
secret Your new personal API token. Keep it safe and don’t share with anyone
name Name of your API token
expire_at null (not currently implemented)

Pagination

Pagination can be used if the number of resources for a request exceeds the value of the limit query parameter of the request. If the next_page and/or prev_page values in the response are non-null there are additional resources. To paginate append the next_page or prev_page value to the base API URL.

For example, if the next_page value in a response is /resource?cursor=a1b2c3d4 you can send the following request for the next page.

GET https://api.cobalt.io/resource?cursor=a1b2c3d4

Idempotency

The API supports idempotency for safely retrying requests without accidentally performing the same operation twice. This is useful when an API call is disrupted in transit and you do not receive a response. For example, if a request to create an asset does not respond due to a network connection error, you can retry the request with the same idempotency key to guarantee that no more than one asset is created.

To perform an idempotent request, provide an additional Idempotency-Key: <key> header to the request. The header name Mutation-Check is also supported for backwards compatibility with previous versions of the API.

An idempotency key is a unique value generated by the client which the server uses to recognize subsequent retries of the same request. How you create unique keys is up to you, but we suggest using V4 UUIDs, or another random string with enough entropy to avoid collisions.

All POST requests optionally accept idempotency keys. Idempotency keys expire after 5 minutes.

Errors

The Cobalt API uses the following error codes:

Error Code Meaning
400 Bad Request – Your request is not good
401 Unauthorized – Your API token is wrong
403 Forbidden – You don’t have access to this
404 Not Found – The specified request could not be found
405 Method Not Allowed – You tried to access Cobalt data with an invalid method
406 Not Acceptable – You requested a format that isn’t json
409 Conflict – You attempted to create a resource with the same Idempotency-Key header as a recent request.
410 Gone – The requested endpoint has been removed from Cobalt servers
418 I’m a teapot
422 Unprocessable Entity – The content and syntax are correctly formed, but something else is off.
429 Too Many Requests – You’re making requests too often! Slow down!
500 Internal Server Error – We had a problem with our server. Try again later.
503 Service Unavailable – We’re temporarially offline for maintanance. Please try again later.

Subscription

If you want to receive our API updates you can subscribe to our mailing list. We will be sending you a newsletter containing changes and improvements in our API once a month. You can also unsubscribe anytime you want. Your e-mail address won’t be shared with any other organization.