# Upload

Upload a single file (multipart/form-data) to Nairi and get back an attachment ID you can reference in a conversation request.





Uploads a single file scoped to your organization. Returns an ID you can pass to `conversations/start` or `conversations/{job_id}/continue` via `attachment_ids`.

```http
POST /api/public/v1/attachments
```

## Request [#request]

`Content-Type: multipart/form-data` with a single `file` form field. Other fields are ignored.

<TypeTable
  type="{
  file: {
    type: &#x22;file (multipart)&#x22;,
    required: true,
    description: &#x22;The file bytes. Max 50 MB. The filename from the multipart header is stored alongside the attachment.&#x22;
  }
}"
/>

## Example [#example]

<Tabs items="[&#x22;bash&#x22;, &#x22;TypeScript&#x22;, &#x22;Ruby&#x22;, &#x22;Python&#x22;, &#x22;Go&#x22;]">
  <Tab value="bash">
    ```bash
    curl -X POST https://api.nairi.ai/api/public/v1/attachments \
      -H "Authorization: Bearer $NAIRI_API_KEY" \
      -F "file=@./screenshot.png"
    ```
  </Tab>

  <Tab value="TypeScript">
    ```ts
    import fs from "node:fs";

    const form = new FormData();
    form.append(
      "file",
      new Blob([fs.readFileSync("screenshot.png")]),
      "screenshot.png",
    );

    const res = await fetch("https://api.nairi.ai/api/public/v1/attachments", {
      method: "POST",
      headers: { Authorization: `Bearer ${process.env.NAIRI_API_KEY}` },
      body: form,
    });
    const { attachment_id } = (await res.json()) as { attachment_id: string };
    ```
  </Tab>

  <Tab value="Ruby">
    ```ruby
    require "net/http"
    require "uri"
    require "json"

    uri = URI("https://api.nairi.ai/api/public/v1/attachments")
    req = Net::HTTP::Post.new(uri)
    req["Authorization"] = "Bearer #{ENV['NAIRI_API_KEY']}"

    form = [["file", File.open("screenshot.png")]]
    req.set_form(form, "multipart/form-data")

    res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }
    attachment_id = JSON.parse(res.body)["attachment_id"]
    ```
  </Tab>

  <Tab value="Python">
    ```python
    import os
    import requests

    with open("screenshot.png", "rb") as f:
        res = requests.post(
            "https://api.nairi.ai/api/public/v1/attachments",
            headers={"Authorization": f"Bearer {os.environ['NAIRI_API_KEY']}"},
            files={"file": ("screenshot.png", f)},
        )
    attachment_id = res.json()["attachment_id"]
    ```
  </Tab>

  <Tab value="Go">
    ```go
    package main

    import (
    	"bytes"
    	"encoding/json"
    	"fmt"
    	"io"
    	"mime/multipart"
    	"net/http"
    	"os"
    )

    func main() {
    	body := &bytes.Buffer{}
    	writer := multipart.NewWriter(body)
    	file, _ := os.Open("screenshot.png")
    	defer file.Close()
    	part, _ := writer.CreateFormFile("file", "screenshot.png")
    	io.Copy(part, file)
    	writer.Close()

    	req, _ := http.NewRequest("POST", "https://api.nairi.ai/api/public/v1/attachments", body)
    	req.Header.Set("Authorization", "Bearer "+os.Getenv("NAIRI_API_KEY"))
    	req.Header.Set("Content-Type", writer.FormDataContentType())

    	res, _ := http.DefaultClient.Do(req)
    	defer res.Body.Close()
    	var out map[string]string
    	json.NewDecoder(res.Body).Decode(&out)
    	fmt.Println(out["attachment_id"])
    }
    ```
  </Tab>
</Tabs>

## Response [#response]

```json
{
  "attachment_id": "att_01KRK1V46BXS73CSNK2VR35NPJ"
}
```

<Callout type="warn">
  The upload endpoint accepts one file per request. To send multiple attachments, upload each one separately and pass the collected IDs in `attachment_ids` when you start or continue the conversation.
</Callout>
