# Export a conversation

> Starts an asynchronous export of one conversation. Poll the export, or listen for the export.ready webhook, to get the download URL.

Source: https://www.bloomtext.com/developers/api/reference/create-chat-export/

`POST /conversations/{conversationId}/exports`

Starts an asynchronous export of one conversation. Poll the export, or listen for the `export.ready` webhook, to get the download URL.

**Scope** `exports:write` · **Idempotent** with `Idempotency-Key`

### Path parameters

- `conversationId` (UUID, required): ID of the conversation.

### Headers

- `Idempotency-Key` (UUID, required): A UUID you generate for each write. Retrying with the same key returns the original result for 24 hours. Reusing a key with a different method, path, or body returns 409.

### Body parameters

Limits an export to a date range and projection.

- `projection` (messages, messages_and_participants, required): What to export: messages only, or messages plus the participant list.

- `from` (timestamp): Earliest message to include. Defaults to the start of the conversation.

- `to` (timestamp): Latest message to include. Defaults to now.

- `include_files` (boolean): Include file metadata in the export.

### Returns

Returns `202 Accepted` with the [Export object](https://www.bloomtext.com/developers/api/reference/export-object/).

### Errors

Failed requests return `application/problem+json` [problem details](https://www.bloomtext.com/developers/api/errors/). The errors specific to this endpoint:

| Status | Code | Meaning |
| --- | --- | --- |
| 400 | `invalid_request` | The request is malformed, such as invalid JSON. |
| 401 | `unauthorized` | The API key is missing, revoked, or invalid. |
| 403 | `insufficient_scope` | The key lacks the required scope. |
| 403 | `conversation_membership_required` | Your app user is not a participant in this conversation. |
| 404 | `not_found` | The resource doesn’t exist or isn’t visible to this key. |
| 409 | `idempotency_key_reused` | The Idempotency-Key was already used with a different request. |
| 422 | `validation_failed` | A field failed validation. See `field_errors`. |
| 429 | `rate_limited` | Too many requests. Retry after `Retry-After` seconds. |

```bash filename="Request"
curl -X POST "https://api.bloomtext.com/v1/conversations/e5c3b7b8-8f08-4d5a-9af1-0d11b0f4b7a0/exports" \
  -H "Authorization: Bearer $BLOOMTEXT_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"projection":"messages","from":"2026-09-01T00:00:00Z","to":"2026-09-30T23:59:59Z"}'
```

```js filename="Request"
const response = await fetch('https://api.bloomtext.com/v1/conversations/e5c3b7b8-8f08-4d5a-9af1-0d11b0f4b7a0/exports', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.BLOOMTEXT_API_KEY}`,
    'Idempotency-Key': crypto.randomUUID(),
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({"projection":"messages","from":"2026-09-01T00:00:00Z","to":"2026-09-30T23:59:59Z"}),
})

if (!response.ok) throw new Error(`BloomText API error: ${response.status}`)
const data = await response.json()
```

```python filename="Request"
import os
import uuid

import requests

response = requests.post(
    "https://api.bloomtext.com/v1/conversations/e5c3b7b8-8f08-4d5a-9af1-0d11b0f4b7a0/exports",
    headers={
        "Authorization": f"Bearer {os.environ['BLOOMTEXT_API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={"projection":"messages","from":"2026-09-01T00:00:00Z","to":"2026-09-30T23:59:59Z"},
)
response.raise_for_status()
data = response.json()
```

```go filename="Request"
package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"os"

	"github.com/google/uuid"
)

func main() {
	body := bytes.NewBufferString(`{"projection":"messages","from":"2026-09-01T00:00:00Z","to":"2026-09-30T23:59:59Z"}`)
	req, err := http.NewRequest("POST", "https://api.bloomtext.com/v1/conversations/e5c3b7b8-8f08-4d5a-9af1-0d11b0f4b7a0/exports", body)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+os.Getenv("BLOOMTEXT_API_KEY"))
	req.Header.Set("Idempotency-Key", uuid.NewString())
	req.Header.Set("Content-Type", "application/json")

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.Status, string(out))
}
```

```ruby filename="Request"
require "net/http"
require "json"
require "securerandom"

uri = URI("https://api.bloomtext.com/v1/conversations/e5c3b7b8-8f08-4d5a-9af1-0d11b0f4b7a0/exports")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch("BLOOMTEXT_API_KEY")}"
request["Idempotency-Key"] = SecureRandom.uuid
request["Content-Type"] = "application/json"
request.body = { projection: "messages", from: "2026-09-01T00:00:00Z", to: "2026-09-30T23:59:59Z" }.to_json

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end
data = JSON.parse(response.body)
```

```json filename="Response · 202 Accepted"
{
  "id": "7a2e4c6b-9d1f-4b3a-8e5c-2f0d1b3a5c7e",
  "status": "ready",
  "created_at": "2026-09-21T15:04:05Z",
  "download_url": "https://files.bloomtext.com/exports/7a2e4c6b.zip?expires=1790003600&signature=…"
}
```
