Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions api-reference/authentication.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
title: "Authentication"
description: "Create API keys and authenticate requests to the Hacktron REST API."
---

The Hacktron REST API authenticates every request with an organization‑scoped API key sent in the `X-Api-Key` header.

API keys are:

- **Organization‑scoped** — each key belongs to exactly one organization. You never need to pass an organization ID alongside the key.
- **Scoped** — each key declares one or more scopes (`read`, `write`, `delete`) that gate which endpoints it can call.

## Creating an API key

API keys are created from the Hacktron dashboard. You must have the **Admin** or **Owner** role in the organization you are creating a key for.

1. Sign in to [app.hacktron.ai](https://app.hacktron.ai) and switch to the organization you want the key to belong to.
2. Open **Settings → API keys**.
3. Click **Create API key**.
4. Give the key a descriptive name (for example `ci-pipeline`, `backstage-integration`).
5. Choose the scopes the key needs — pick the minimum set your integration requires. See [Scopes](#scopes).
6. Optionally set an expiration date.
7. Click **Create**.

<Warning>
The full API key is shown **only once**, immediately after creation. Copy it and store it in a secret manager right away. If you lose it, you will need to revoke the key and create a new one.
</Warning>

Each organization can have at most **10 active API keys** at a time. Revoke unused keys before creating new ones if you hit the limit.

### Key format

Hacktron API keys look like this:

```
hacktron_3s9K1sP7m2nXvT8YhLq0ZbW4...
```

- They always start with the `hacktron_` prefix.
- The first 12 characters (for example `hacktron_3s9`) are stored as a non‑secret prefix so you can recognise keys in your logs and in the dashboard. The full key is never stored server‑side — only a SHA‑256 hash.

## Making authenticated requests

Send your API key in the `X-Api-Key` header on every request:

```bash
curl https://api.hacktron.ai/v1/scans \
-H "X-Api-Key: hacktron_3s9K1sP7m2nXvT8YhLq0ZbW4..."
```

You do **not** need to send `X-Organization-Id` or any other header — the organization is resolved from the key.

<Tip>
Never hardcode API keys in source control or client-side code. Load them from environment variables or a secret manager at runtime.
</Tip>

## Scopes

Scopes control what an API key is allowed to do. They are declared when you create the key and cannot be changed afterwards — create a new key if you need different scopes.

| Scope | Grants access to |
| -------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `read` | All `GET` endpoints: list and read scans, findings, and cost estimations. |
| `write` | Mutating endpoints: trigger scans, create cost estimations, update findings, add comments. Implies `read` for the same resources. |
| `delete` | Reserved for future use. |

Each endpoint in this reference states the scope it requires. Calling an endpoint with a key that is missing the required scope returns `403 Forbidden`.

## Revoking a key

You can revoke a key at any time from **Settings → API keys** in the dashboard. Revocation takes effect immediately — the next request with that key will fail with `401 Unauthorized`.

Revoked keys are kept in the dashboard audit trail (with last‑used timestamps) but can never be reactivated.

## Testing your key

To verify a key is working, list scans:

```bash
curl https://api.hacktron.ai/v1/scans?limit=1 \
-H "X-Api-Key: $HACKTRON_API_KEY"
```

A successful response returns HTTP `200` and a JSON body containing `data`, `total`, `page`, and `limit` fields.

<Tip>
Endpoints can also be exercised interactively in the Swagger UI at [https://api.hacktron.ai/docs](https://api.hacktron.ai/docs). The "Authorize" button accepts an `X-Api-Key` value and persists it for subsequent requests.
</Tip>

Common failures:

| Status | Meaning |
| ------ | -------------------------------------------------------------------------------------------- |
| `401` | Missing, malformed, revoked, or expired API key. |
| `403` | Key is valid but is missing the required scope. |
| `429` | You have hit the rate limit for this key. See [Rate limits](/api-reference/rate-limits). |
108 changes: 108 additions & 0 deletions api-reference/cost-estimations/create-cost-estimation.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
title: "Create cost estimation"
api: "POST /cost-estimations"
description: "Estimate the credit cost of scanning one or more repositories before starting a scan."
---

A cost estimation resolves the repositories you plan to scan, detects applications within them, and returns a predicted credit cost. A completed cost estimation is required before calling [`POST /scans`](/api-reference/scans/create-scan).

Cost estimations run asynchronously. The `POST` returns a record in `pending` or `running` state; poll [`GET /cost-estimations/{id}`](/api-reference/cost-estimations/get-cost-estimation) until `status` reaches `completed`, `partial`, or `failed`.

<Info>
**Scope required**: `write`
</Info>

## Request

```bash
curl -X POST https://api.hacktron.ai/v1/cost-estimations \
-H "X-Api-Key: $HACKTRON_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "nightly-estimate",
"repos": [
{
"source": "connected",
"repo_url": "https://github.com/acme/backend",
"branch": "main"
}
]
}'
```

### Body

| Field | Type | Required | Description |
| ------- | -------- | -------- | ------------------------------------------------------------------------------------------------ |
| `name` | string | No | Friendly label for this estimation. Max 255 chars. |
| `repos` | object[] | Yes | 1–20 repositories to estimate. Each entry is one of the repo shapes below, identified by `source`. |

### Repo shapes

Repositories use a discriminated union on the `source` field.

#### `connected` — a repository already synced to Hacktron via GitHub, GitLab, or Bitbucket

| Field | Type | Required | Description |
| ------------------------ | ------ | -------- | ---------------------------------------------------- |
| `source` | `"connected"` | Yes | Discriminator. |
| `repo_url` | string | Yes | Full HTTPS URL of the repository. Max 500 chars. |
| `branch` | string | Yes | Branch to estimate. Max 255 chars. |
| `github_installation_id` | int | No | Specific GitHub App installation ID to use. |

#### `public` — a public git repository Hacktron can clone anonymously

| Field | Type | Required | Description |
| ---------- | ------ | -------- | ----------------------------------------- |
| `source` | `"public"` | Yes | Discriminator. |
| `repo_url` | string | Yes | Full HTTPS URL. Max 500 chars. |
| `branch` | string | Yes | Branch to estimate. Max 255 chars. |

#### `upload` — a previously uploaded archive

| Field | Type | Required | Description |
| ------------ | ------ | -------- | ----------------------------------- |
| `source` | `"upload"` | Yes | Discriminator. |
| `archive_id` | UUID | Yes | ID of a scan archive you uploaded. |

## Response

`201 Created` — the estimation is queued. Poll `GET /cost-estimations/{id}` until `status` reaches a terminal value.

```json
{
"id": "b4f5c6a1-2d3e-4f56-9a8b-0c1d2e3f4a5b",
"organization_id": "f336d0bc-b841-465b-8045-024475c079dd",
"user_id": "e5a6d7c8-9b0a-1c2d-3e4f-5a6b7c8d9e0f",
"name": "nightly-estimate",
"task_id": "cost_est_acme-backend_1712345678",
"status": "pending",
"repos": [
{
"source": "connected",
"repo_url": "https://github.com/acme/backend",
"branch": "main"
}
],
"total_credits": null,
"repo_results": null,
"error": null,
"created_at": "2026-04-13T12:00:00.000Z",
"updated_at": "2026-04-13T12:00:00.000Z"
}
```

### Terminal statuses

| Status | Meaning |
| ----------- | ------------------------------------------------------------------------------- |
| `completed` | All repos were estimated successfully. `total_credits` is populated. |
| `partial` | Some repos completed, others failed. Check `repo_results[].status` for details. |
| `failed` | The whole estimation failed. `error` contains a message. |

Once in a terminal state, an estimation is immutable. Pass its `id` as `cost_estimation_id` to [`POST /scans`](/api-reference/scans/create-scan) to start the scan.

## Errors

- `400` — invalid or missing fields (for example, more than 20 repos, invalid `source`, or missing `repo_url`).
- `401` / `403` — authentication or scope failure.
71 changes: 71 additions & 0 deletions api-reference/cost-estimations/get-cost-estimation.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
title: "Get cost estimation"
api: "GET /cost-estimations/{id}"
description: "Fetch a cost estimation by ID."
---

Returns a single cost estimation. Poll this endpoint on a pending estimation until `status` reaches a terminal value (`completed`, `partial`, or `failed`).

<Info>
**Scope required**: `read`
</Info>

## Request

```bash
curl "https://api.hacktron.ai/v1/cost-estimations/b4f5c6a1-2d3e-4f56-9a8b-0c1d2e3f4a5b" \
-H "X-Api-Key: $HACKTRON_API_KEY"
```

### Path parameters

| Parameter | Type | Description |
| --------- | ---- | --------------------------------- |
| `id` | UUID | The cost estimation UUID. |

## Response

`200 OK` — see [Create cost estimation](/api-reference/cost-estimations/create-cost-estimation) for the response schema.

```json
{
"id": "b4f5c6a1-2d3e-4f56-9a8b-0c1d2e3f4a5b",
"organization_id": "f336d0bc-b841-465b-8045-024475c079dd",
"user_id": "e5a6d7c8-9b0a-1c2d-3e4f-5a6b7c8d9e0f",
"name": "nightly-estimate",
"task_id": "cost_est_acme-backend_1712345678",
"status": "completed",
"repos": [
{
"source": "connected",
"repo_url": "https://github.com/acme/backend",
"branch": "main",
"commit_sha": "abc123def456"
}
],
"total_credits": 4200,
"repo_results": [
{
"repo_url": "https://github.com/acme/backend",
"branch": "main",
"commit_sha": "abc123def456",
"status": "completed",
"from_cache": false,
"credits": 4200,
"applications": [
{
"app_name": "backend-api",
"app_root_path": "apps/api",
"architecture": "NestJS REST API with PostgreSQL"
}
]
}
],
"created_at": "2026-04-13T12:00:00.000Z",
"updated_at": "2026-04-13T12:03:21.000Z"
}
```

## Errors

- `404` — estimation not found or not visible to your organization.
86 changes: 86 additions & 0 deletions api-reference/cost-estimations/list-cost-estimations.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
title: "List cost estimations"
api: "GET /cost-estimations"
description: "List cost estimations for your organization."
---

Returns cost estimations for the organization, most recent first. Use offset-based pagination to page through results.

<Info>
**Scope required**: `read`
</Info>

<Note>
Unlike most list endpoints, cost estimations use **offset‑based pagination** (`limit` + `offset`) instead of `page` + `limit`. See [Pagination, filtering & sorting](/api-reference/pagination-filtering) for the general conventions.
</Note>

## Request

```bash
curl "https://api.hacktron.ai/v1/cost-estimations?limit=20&offset=0" \
-H "X-Api-Key: $HACKTRON_API_KEY"
```

### Query parameters

| Parameter | Type | Default | Max | Description |
| --------- | ------- | ------- | --- | ------------------------------------ |
| `limit` | integer | `50` | `100` | Number of items to return. |
| `offset` | integer | `0` | — | Number of items to skip. |

## Response

`200 OK`

```json
{
"data": [
{
"id": "b4f5c6a1-2d3e-4f56-9a8b-0c1d2e3f4a5b",
"organization_id": "f336d0bc-b841-465b-8045-024475c079dd",
"user_id": "e5a6d7c8-9b0a-1c2d-3e4f-5a6b7c8d9e0f",
"name": "nightly-estimate",
"task_id": "cost_est_acme-backend_1712345678",
"status": "completed",
"repos": [
{
"source": "connected",
"repo_url": "https://github.com/acme/backend",
"branch": "main",
"commit_sha": "abc123def456"
}
],
"total_credits": 4200,
"repo_results": [
{
"repo_url": "https://github.com/acme/backend",
"branch": "main",
"commit_sha": "abc123def456",
"status": "completed",
"from_cache": false,
"credits": 4200,
"applications": [
{
"app_name": "backend-api",
"app_root_path": "apps/api",
"architecture": "NestJS REST API with PostgreSQL"
}
]
}
],
"created_at": "2026-04-13T12:00:00.000Z",
"updated_at": "2026-04-13T12:03:21.000Z"
}
],
"total": 42
}
```

### Fields

| Field | Type | Description |
| ------- | -------- | --------------------------------------------------- |
| `data` | object[] | The estimations on this page. |
| `total` | integer | Total number of estimations in the organization. |

See [Create cost estimation](/api-reference/cost-estimations/create-cost-estimation) for the full estimation object shape.
Loading