> ## Documentation Index
> Fetch the complete documentation index at: https://docs.swisstools.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Release Notes API Reference

> Generate AI-powered release notes from GitHub commits, manage draft and published releases, and distribute them via Slack or email.

The Releases API lets you generate, edit, and distribute release notes. You point Swisstools at one or more GitHub repository URLs and a date range, and the AI generates a structured changelog from the commit history. From there you can refine the draft, publish it, export it as Markdown, and send it to a Slack channel or email list.

All release endpoints require session authentication. See [Authentication](/api-reference/authentication) for details.

Release status values: `processing` (AI generation in progress), `draft` (ready for editing), `published` (finalized and visible).

## List Releases

`GET /api/projects/:projectId/releases`

Returns all releases for the specified project, ordered by creation date descending.

**Path Parameters**

<ParamField path="projectId" type="string" required>
  The UUID of the project.
</ParamField>

**Request**

```bash theme={null}
curl https://swisstools.dev/api/projects/018e5a3b-2d4e-8c9f-a0b1-3c4d5e6f7a8b/releases \
  -b cookies.txt
```

**Response**

```json theme={null}
[
  {
    "id": "018eb19c-8d0e-4f5a-b6c7-9d0e1f2a3b4c",
    "projectId": "018e5a3b-2d4e-8c9f-a0b1-3c4d5e6f7a8b",
    "title": "Release v1.2.0",
    "content": "## What's New\n\n- Improved checkout flow\n- Fixed payment retry bug",
    "status": "published",
    "fromDate": "2024-01-01T00:00:00.000Z",
    "toDate": "2024-01-31T00:00:00.000Z",
    "repoUrls": ["https://github.com/acme/payments"],
    "commitCount": 24,
    "errorMessage": null,
    "publishedAt": "2024-02-01T09:00:00.000Z",
    "createdAt": "2024-01-31T20:00:00.000Z",
    "updatedAt": "2024-02-01T09:00:00.000Z"
  }
]
```

## Generate Release

`POST /api/projects/:projectId/releases/generate`

Triggers AI generation of release notes from GitHub commits in the given date range. The release is created immediately with `status: "processing"` and transitions to `status: "draft"` when the AI finishes (or `status: "draft"` with an `errorMessage` if generation fails). Poll the Get Release endpoint to check progress.

**Path Parameters**

<ParamField path="projectId" type="string" required>
  The UUID of the project.
</ParamField>

**Request Body**

<ParamField body="fromDate" type="string" required>
  Start of the commit date range, ISO 8601 format (e.g., `2024-01-01`).
</ParamField>

<ParamField body="toDate" type="string" required>
  End of the commit date range, ISO 8601 format (e.g., `2024-01-31`).
</ParamField>

<ParamField body="repoUrls" type="array" required>
  One or more GitHub repository URLs to pull commits from (e.g., `["https://github.com/org/repo"]`).
</ParamField>

**Request**

```bash theme={null}
curl -X POST https://swisstools.dev/api/projects/018e5a3b-2d4e-8c9f-a0b1-3c4d5e6f7a8b/releases/generate \
  -b cookies.txt \
  -H "Content-Type: application/json" \
  -d '{
    "fromDate": "2024-01-01",
    "toDate": "2024-01-31",
    "repoUrls": ["https://github.com/acme/payments"]
  }'
```

**Response** — `201 Created`

```json theme={null}
{
  "id": "018eb19c-8d0e-4f5a-b6c7-9d0e1f2a3b4c",
  "projectId": "018e5a3b-2d4e-8c9f-a0b1-3c4d5e6f7a8b",
  "title": "Release — Jan 1 to Jan 31",
  "content": "",
  "status": "processing",
  "fromDate": "2024-01-01T00:00:00.000Z",
  "toDate": "2024-01-31T00:00:00.000Z",
  "repoUrls": ["https://github.com/acme/payments"],
  "commitCount": 0,
  "errorMessage": null,
  "publishedAt": null,
  "createdAt": "2024-01-31T20:00:00.000Z",
  "updatedAt": "2024-01-31T20:00:00.000Z"
}
```

## Get Release

`GET /api/projects/:projectId/releases/:releaseId`

Returns a single release by its ID. Use this to poll for status transitions from `processing` to `draft`.

**Path Parameters**

<ParamField path="projectId" type="string" required>
  The UUID of the project.
</ParamField>

<ParamField path="releaseId" type="string" required>
  The UUID of the release.
</ParamField>

**Request**

```bash theme={null}
curl https://swisstools.dev/api/projects/018e5a3b-2d4e-8c9f-a0b1-3c4d5e6f7a8b/releases/018eb19c-8d0e-4f5a-b6c7-9d0e1f2a3b4c \
  -b cookies.txt
```

**Response**

```json theme={null}
{
  "id": "018eb19c-8d0e-4f5a-b6c7-9d0e1f2a3b4c",
  "projectId": "018e5a3b-2d4e-8c9f-a0b1-3c4d5e6f7a8b",
  "title": "Release v1.2.0",
  "content": "## What's New\n\n- Improved checkout flow\n- Fixed payment retry bug",
  "status": "draft",
  "fromDate": "2024-01-01T00:00:00.000Z",
  "toDate": "2024-01-31T00:00:00.000Z",
  "repoUrls": ["https://github.com/acme/payments"],
  "commitCount": 24,
  "errorMessage": null,
  "publishedAt": null,
  "createdAt": "2024-01-31T20:00:00.000Z",
  "updatedAt": "2024-01-31T20:05:00.000Z"
}
```

## Update Release

`PUT /api/projects/:projectId/releases/:releaseId`

Updates the title or content of a release. You can edit `draft` releases before publishing.

**Path Parameters**

<ParamField path="projectId" type="string" required>
  The UUID of the project.
</ParamField>

<ParamField path="releaseId" type="string" required>
  The UUID of the release to update.
</ParamField>

**Request Body**

<ParamField body="title" type="string">
  Updated release title.
</ParamField>

<ParamField body="content" type="string">
  Updated Markdown content.
</ParamField>

**Request**

```bash theme={null}
curl -X PUT https://swisstools.dev/api/projects/018e5a3b-2d4e-8c9f-a0b1-3c4d5e6f7a8b/releases/018eb19c-8d0e-4f5a-b6c7-9d0e1f2a3b4c \
  -b cookies.txt \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Release v1.2.0",
    "content": "## What'\''s New\n\n- Improved checkout flow\n- Fixed payment retry bug\n- Added Apple Pay support"
  }'
```

**Response**

```json theme={null}
{
  "id": "018eb19c-8d0e-4f5a-b6c7-9d0e1f2a3b4c",
  "projectId": "018e5a3b-2d4e-8c9f-a0b1-3c4d5e6f7a8b",
  "title": "Release v1.2.0",
  "content": "## What's New\n\n- Improved checkout flow\n- Fixed payment retry bug\n- Added Apple Pay support",
  "status": "draft",
  "fromDate": "2024-01-01T00:00:00.000Z",
  "toDate": "2024-01-31T00:00:00.000Z",
  "repoUrls": ["https://github.com/acme/payments"],
  "commitCount": 24,
  "errorMessage": null,
  "publishedAt": null,
  "createdAt": "2024-01-31T20:00:00.000Z",
  "updatedAt": "2024-02-01T08:30:00.000Z"
}
```

## Delete Release

`DELETE /api/projects/:projectId/releases/:releaseId`

Permanently deletes a release and all its attachments.

**Path Parameters**

<ParamField path="projectId" type="string" required>
  The UUID of the project.
</ParamField>

<ParamField path="releaseId" type="string" required>
  The UUID of the release to delete.
</ParamField>

**Request**

```bash theme={null}
curl -X DELETE https://swisstools.dev/api/projects/018e5a3b-2d4e-8c9f-a0b1-3c4d5e6f7a8b/releases/018eb19c-8d0e-4f5a-b6c7-9d0e1f2a3b4c \
  -b cookies.txt
```

**Response**

```json theme={null}
{"success": true}
```

## Publish Release

`POST /api/projects/:projectId/releases/:releaseId/publish`

Marks a `draft` release as `published` and records the current timestamp in `publishedAt`.

**Path Parameters**

<ParamField path="projectId" type="string" required>
  The UUID of the project.
</ParamField>

<ParamField path="releaseId" type="string" required>
  The UUID of the release to publish.
</ParamField>

**Request**

```bash theme={null}
curl -X POST https://swisstools.dev/api/projects/018e5a3b-2d4e-8c9f-a0b1-3c4d5e6f7a8b/releases/018eb19c-8d0e-4f5a-b6c7-9d0e1f2a3b4c/publish \
  -b cookies.txt
```

**Response**

```json theme={null}
{
  "id": "018eb19c-8d0e-4f5a-b6c7-9d0e1f2a3b4c",
  "projectId": "018e5a3b-2d4e-8c9f-a0b1-3c4d5e6f7a8b",
  "title": "Release v1.2.0",
  "content": "## What's New\n\n- Improved checkout flow\n- Fixed payment retry bug",
  "status": "published",
  "fromDate": "2024-01-01T00:00:00.000Z",
  "toDate": "2024-01-31T00:00:00.000Z",
  "repoUrls": ["https://github.com/acme/payments"],
  "commitCount": 24,
  "errorMessage": null,
  "publishedAt": "2024-02-01T09:00:00.000Z",
  "createdAt": "2024-01-31T20:00:00.000Z",
  "updatedAt": "2024-02-01T09:00:00.000Z"
}
```

## Export Release

`GET /api/projects/:projectId/releases/:releaseId/export`

Returns the release content as a downloadable Markdown file.

**Path Parameters**

<ParamField path="projectId" type="string" required>
  The UUID of the project.
</ParamField>

<ParamField path="releaseId" type="string" required>
  The UUID of the release to export.
</ParamField>

**Request**

```bash theme={null}
curl https://swisstools.dev/api/projects/018e5a3b-2d4e-8c9f-a0b1-3c4d5e6f7a8b/releases/018eb19c-8d0e-4f5a-b6c7-9d0e1f2a3b4c/export \
  -b cookies.txt \
  -o release-v1.2.0.md
```

**Response** — `200 OK` with `Content-Type: text/markdown` and a `Content-Disposition: attachment` header containing the Markdown content.

## Send to Slack

`POST /api/projects/:projectId/releases/:releaseId/send-slack`

Sends the release to the Slack channel configured in the project's release settings. Requires a Slack integration to be set up for the project.

**Path Parameters**

<ParamField path="projectId" type="string" required>
  The UUID of the project.
</ParamField>

<ParamField path="releaseId" type="string" required>
  The UUID of the release to send.
</ParamField>

**Request**

```bash theme={null}
curl -X POST https://swisstools.dev/api/projects/018e5a3b-2d4e-8c9f-a0b1-3c4d5e6f7a8b/releases/018eb19c-8d0e-4f5a-b6c7-9d0e1f2a3b4c/send-slack \
  -b cookies.txt
```

**Response**

```json theme={null}
{"success": true}
```

## Send via Email

`POST /api/projects/:projectId/releases/:releaseId/send-email`

Sends the release to the email recipients configured in the project's release settings.

**Path Parameters**

<ParamField path="projectId" type="string" required>
  The UUID of the project.
</ParamField>

<ParamField path="releaseId" type="string" required>
  The UUID of the release to send.
</ParamField>

**Request**

```bash theme={null}
curl -X POST https://swisstools.dev/api/projects/018e5a3b-2d4e-8c9f-a0b1-3c4d5e6f7a8b/releases/018eb19c-8d0e-4f5a-b6c7-9d0e1f2a3b4c/send-email \
  -b cookies.txt
```

**Response**

```json theme={null}
{"success": true}
```

## Release Object

<ResponseField name="id" type="string">
  UUID that uniquely identifies the release.
</ResponseField>

<ResponseField name="projectId" type="string">
  UUID of the project that owns this release.
</ResponseField>

<ResponseField name="title" type="string">
  The release title, editable after generation.
</ResponseField>

<ResponseField name="content" type="string">
  The release body in Markdown format. Empty string while `status` is `processing`.
</ResponseField>

<ResponseField name="status" type="string">
  Current lifecycle state. One of `processing`, `draft`, or `published`.
</ResponseField>

<ResponseField name="fromDate" type="string">
  ISO 8601 timestamp for the start of the commit range used to generate this release.
</ResponseField>

<ResponseField name="toDate" type="string">
  ISO 8601 timestamp for the end of the commit range.
</ResponseField>

<ResponseField name="repoUrls" type="array">
  Array of GitHub repository URLs that were analyzed.
</ResponseField>

<ResponseField name="commitCount" type="integer">
  Number of commits included in the generated release notes.
</ResponseField>

<ResponseField name="errorMessage" type="string">
  Populated if AI generation failed; `null` otherwise.
</ResponseField>

<ResponseField name="publishedAt" type="string">
  ISO 8601 timestamp of when the release was published, or `null` if still a draft.
</ResponseField>

<ResponseField name="createdAt" type="string">
  ISO 8601 timestamp of creation.
</ResponseField>

<ResponseField name="updatedAt" type="string">
  ISO 8601 timestamp of the last update.
</ResponseField>
