Skip to main content

Documentation Index

Fetch the complete documentation index at: https://specterops-bed-7559-api-key-exp.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Enterprise and Community Edition badge BloodHound is an API-first product, which means core product functionality runs on the API layer. All data shown in the user interface, all commands sent to SharpHound Enterprise and AzureHound Enterprise collectors, and all uploaded data pass through the BloodHound APIs. You can use these APIs to integrate BloodHound with other tools and workflows in your environment.

API Explorer

In addition to the REST API reference on this site, BloodHound provides an API Explorer that provides interactive API documentation and testing capabilities. The API Explorer is built using Swagger UI and is accessible from within your tenant after logging in. It allows you to browse available API endpoints, view request and response schemas, and make test API calls directly from the interface.
1

Navigate to API Explorer

  1. Log in to your BloodHound tenant.
  2. In the left menu, click API Explorer.
2

Explore API Endpoints

  1. Browse through the list of available API endpoints categorized by functionality.
  2. Click an endpoint to view details such as required parameters, request body schema, and response schema.
  3. Click Try it out to make test API calls on your tenant.

Authentication

The BloodHound API accepts two forms of authentication:
  • A JSON Web Token (JWT) is generated during login using your email address, password, and 2FA token (or through a SAML- or OIDC-based authentication flow). JWTs remain active for 8 hours and are primarily used for end-user access to the web application.
  • An API token and token ID pair is generated in the Administration interface. API tokens are primarily used for integrations and automation.
There are two methods for creating API tokens in BloodHound, each serving a different purpose:
  • Non-personal API tokens and token IDs for integrations, such as Splunk, ServiceNow, and Cortex XSOAR
  • Personal API tokens and token IDs for individual day-to-day use, such as BloodHound Operator

API key expiration

BloodHound Enterprise supports API key expiration to help you align with internal security and compliance requirements. This setting controls how long API tokens remain valid.
You must manually create replacement tokens and update all dependent integration configurations before they expire. BloodHound does not automatically rotate API keys.

Non-personal API tokens

Administrators can create dedicated, non-personal BloodHound accounts for API integrations. These accounts are not tied to a specific person and are intended for applications and services that need to interact with the BloodHound API. When you create a non-personal API token and token ID for one of these accounts, the roles and permissions assigned to that account determine its API access. To create a non-personal API token and token ID:
1

Create a new user account

  1. Log in as a user with the Administrator role.
  2. In the left menu, click Administration > Manage Users.
  3. Click Create User and enter the required information.
  4. After creating the user, you may optionally log in as that user to enable MFA.
    MFA is not required for API key authentication, but it can provide an additional layer of security for the account.If you choose to enable MFA, securely dispose of the password and MFA configuration after setup, as they are not needed for authenticating with API keys and can be reset by an Administrator if necessary.
2

Generate an API token

  1. Log back in as an Administrator (if not already logged in).
  2. In the left menu, click Administration > Manage Users.
  3. Find the user account you just created, click the hamburger menu, and select Generate / Revoke API Tokens.
    A view of the API token generation interface
  4. Click Create Token, give it a descriptive name, and click Save.
  5. Save the API token and token ID and click Close.
    Both values are required for authentication and will only be shown once. If you lose them, you must generate new credentials. You should also revoke the previous token to prevent unauthorized access.
  6. Configure the dependent integration with the new API token and token ID.

Personal API tokens

You can create personal API tokens and token IDs for your own use, such as for testing API calls. Personal API tokens are tied to your user account and inherit the permissions of that account. To create a personal API token and token ID:
1

Navigate to API Key Management

  1. Log in to your BloodHound tenant.
  2. In the left menu, click My Profile.
  3. Click API Key Management.
2

Generate an API token

  1. Click Create Token.
    A view of the API token creation interface
  2. Give the token a descriptive name and click Save.
  3. Save the API token and token ID and click Close.
    Both values are required for authentication and will only be shown once. If you lose them, you must generate new credentials. You should also revoke the previous token to prevent unauthorized access.
  4. Use the API token and token ID to call the API.

Call the API

After you have an API token and token ID, you can call the BloodHound API.

Use a JWT/bearer token

For quick tests or one-time calls, the JWT used by your browser may be the simplest route. The API accepts calls using the following header structure in the HTTP request:
Authorization: Bearer $JWT_TOKEN
If you open the Network tab in your browser, you’ll see calls against the API made using this structure.

Use an API token

For long-running API integrations, BloodHound’s API uses hash-based message authentication code (HMAC) authentication. The API token is used as the secret key to sign requests, and the token ID is sent as the identifier. Calls against the API must include the following in the signed hash:
  • API token
  • HTTP method and URI
  • Current time
  • Body content (if applicable to the request)
Calls against the API must include the following headers in the HTTP request:
Authorization: bhesignature $TOKEN_ID
RequestDate: $RFC3339_DATETIME
Signature: $BASE64ENCODED_HMAC_SIGNATURE
By validating the hash signature against the request, the API can ensure that calls were made by the original requestor, within a reasonable timeframe, against the proper API endpoint, including the original content body, and that no replay or content modification has occurred. For a complete implementation example, see apiclient.py in the specterops/bloodhound-docs GitHub repository. The following code snippet from the apiclient.py script illustrates the authentication process:
def _request(self, method: str, uri: str, body: Optional[bytes] = None) -> requests.Response:
    # Digester is initialized with HMAC-SHA-256 using the token key as the HMAC digest key.
    digester = hmac.new(self._credentials.token_key.encode(), None, hashlib.sha256)

    # OperationKey is the first HMAC digest link in the signature chain. This prevents replay attacks that seek to
    # modify the request method or URI. It is composed of concatenating the request method and the request URI with
    # no delimiter and computing the HMAC digest using the token key as the digest secret.
    #
    # Example: GET /api/v2/test/resource HTTP/1.1
    # Signature Component: GET/api/v2/test/resource
    digester.update(f'{method}{uri}'.encode())

    # Update the digester for further chaining
    digester = hmac.new(digester.digest(), None, hashlib.sha256)

    # DateKey is the next HMAC digest link in the signature chain. This encodes the RFC3339 formatted datetime
    # value as part of the signature to the hour to prevent replay attacks that are older than max two hours. This
    # value is added to the signature chain by cutting off all values from the RFC3339 formatted datetime from the
    # hours value forward:
    #
    # Example: 2020-12-01T23:59:60Z
    # Signature Component: 2020-12-01T23
    datetime_formatted = datetime.datetime.now().astimezone().isoformat('T')
    digester.update(datetime_formatted[:13].encode())

    # Update the digester for further chaining
    digester = hmac.new(digester.digest(), None, hashlib.sha256)

    # Body signing is the last HMAC digest link in the signature chain. This encodes the request body as part of
    # the signature to prevent replay attacks that seek to modify the payload of a signed request. In the case
    # where there is no body content the HMAC digest is computed anyway, simply with no values written to the
    # digester.
    if body is not None:
        digester.update(body)

    # Perform the request with the signed and expected headers
    return requests.request(
        method=method,
        url=self._format_url(uri),
        headers={
            'User-Agent': 'bhe-python-sdk 0001',
            'Authorization': f'bhesignature {self._credentials.token_id}',
            'RequestDate': datetime_formatted,
            'Signature': base64.b64encode(digester.digest()),
            'Content-Type': 'application/json',
        },
        data=body,
    )
Examples for other languages: