# Attachment service

The attachment service provides functionality for creating, updating, and archiving attachments uploaded to S3.

OpenAPI file: [`AttachmentService.json`](https://dev.nominal.io/api/_downloads/3233ca5d8e4e0edc428f65cdbd499992/AttachmentService.json)

## Endpoints

### Create

POST `/attachments/v1/attachments`

Create a new attachment. Assumes the file is already uploaded to S3 through the upload service.

Body

`s3Path` string required
:   ​

`title` string required
:   ​

`description` string required
:   ​

`properties` map of `PropertyName` to string
:   ​

`labels` array of string
:   ​

`workspace` string (RID)
:   The workspace in which to create the attachment. If not provided, the attachment will be created in the default workspace for the user’s organization, if the default workspace for the organization is configured.

Response

`rid` string (RID)
:   ​

`title` string
:   ​

`s3Path` string
:   ​

`fileType` string
:   ​

`description` string
:   ​

`createdBy` string (RID)
:   ​

`properties` map of `PropertyName` to string
:   ​

`labels` array of string
:   ​

`createdAt` string (date-time)
:   ​

`isArchived` boolean
:   ​

Request

**curl**

```shell
curl -X POST "https://api.gov.nominal.io/api/attachments/v1/attachments" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "s3Path": "<s3 path>",
  "title": "<title>",
  "description": "<description>"
}'
```

**requests**

```python
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/attachments/v1/attachments",
    headers={"Authorization": "Bearer <api key>"},
    json={"s3Path": "<s3 path>", "title": "<title>", "description": "<description>"},
)
response.raise_for_status()
print(response.json())
```

**httpx**

```python
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/attachments/v1/attachments",
    headers={"Authorization": "Bearer <api key>"},
    json={"s3Path": "<s3 path>", "title": "<title>", "description": "<description>"},
)
response.raise_for_status()
print(response.json())
```

**aiohttp**

```python
import asyncio

import aiohttp

async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/attachments/v1/attachments",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "s3Path": "<s3 path>",
                "title": "<title>",
                "description": "<description>",
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())

asyncio.run(main())
```

Response: `200`

```json
{
  "rid": "<attachment rid>",
  "title": "<title>",
  "s3Path": "<s3 path>",
  "fileType": "<file type>",
  "description": "<description>",
  "createdBy": "<created by>",
  "properties": {
    "<key>": "<property value>"
  },
  "labels": [
    "<label>"
  ],
  "createdAt": "2026-01-01T00:00:00Z",
  "isArchived": true
}
```

### Get

GET `/attachments/v1/attachments/{rid}`

Get an attachment by its RID.

Path parameters

`rid` string (RID) required
:   ​

Response

`rid` string (RID)
:   ​

`title` string
:   ​

`s3Path` string
:   ​

`fileType` string
:   ​

`description` string
:   ​

`createdBy` string (RID)
:   ​

`properties` map of `PropertyName` to string
:   ​

`labels` array of string
:   ​

`createdAt` string (date-time)
:   ​

`isArchived` boolean
:   ​

Request

**curl**

```shell
curl "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>" \
  -H "Authorization: Bearer <api key>"
```

**requests**

```python
import requests

response = requests.get(
    "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
```

**httpx**

```python
import httpx

response = httpx.get(
    "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
```

**aiohttp**

```python
import asyncio

import aiohttp

async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.get(
            "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())

asyncio.run(main())
```

Response: `200`

```json
{
  "rid": "<attachment rid>",
  "title": "<title>",
  "s3Path": "<s3 path>",
  "fileType": "<file type>",
  "description": "<description>",
  "createdBy": "<created by>",
  "properties": {
    "<key>": "<property value>"
  },
  "labels": [
    "<label>"
  ],
  "createdAt": "2026-01-01T00:00:00Z",
  "isArchived": true
}
```

### Update

PUT `/attachments/v1/attachments/{rid}`

Update an attachment. Only the fields that are set in the request will be updated.

Path parameters

`rid` string (RID) required
:   ​

Body

`title` string
:   ​

`description` string
:   ​

`properties` map of `PropertyName` to string
:   ​

`labels` array of string
:   ​

Response

`rid` string (RID)
:   ​

`title` string
:   ​

`s3Path` string
:   ​

`fileType` string
:   ​

`description` string
:   ​

`createdBy` string (RID)
:   ​

`properties` map of `PropertyName` to string
:   ​

`labels` array of string
:   ​

`createdAt` string (date-time)
:   ​

`isArchived` boolean
:   ​

Request

**curl**

```shell
curl -X PUT "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "title": "<title>",
  "description": "<description>",
  "properties": {
    "<key>": "<property value>"
  },
  "labels": [
    "<label>"
  ]
}'
```

**requests**

```python
import requests

response = requests.put(
    "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "title": "<title>",
        "description": "<description>",
        "properties": {"<key>": "<property value>"},
        "labels": ["<label>"],
    },
)
response.raise_for_status()
print(response.json())
```

**httpx**

```python
import httpx

response = httpx.put(
    "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>",
    headers={"Authorization": "Bearer <api key>"},
    json={
        "title": "<title>",
        "description": "<description>",
        "properties": {"<key>": "<property value>"},
        "labels": ["<label>"],
    },
)
response.raise_for_status()
print(response.json())
```

**aiohttp**

```python
import asyncio

import aiohttp

async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.put(
            "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>",
            headers={"Authorization": "Bearer <api key>"},
            json={
                "title": "<title>",
                "description": "<description>",
                "properties": {"<key>": "<property value>"},
                "labels": ["<label>"],
            },
        ) as response:
            response.raise_for_status()
            print(await response.json())

asyncio.run(main())
```

Response: `200`

```json
{
  "rid": "<attachment rid>",
  "title": "<title>",
  "s3Path": "<s3 path>",
  "fileType": "<file type>",
  "description": "<description>",
  "createdBy": "<created by>",
  "properties": {
    "<key>": "<property value>"
  },
  "labels": [
    "<label>"
  ],
  "createdAt": "2026-01-01T00:00:00Z",
  "isArchived": true
}
```

### Get batch

POST `/attachments/v1/attachments/batch`

Get a set of attachments by their RIDs.

Body

`attachmentRids` array of string (RID)
:   ​

Response

`response` array of [`Attachment`](https://dev.nominal.io/api/rest/attachment-service.md#attachment)
:   ​

    Fields of `Attachment`

    `rid` string (RID)
    :   ​

    `title` string
    :   ​

    `s3Path` string
    :   ​

    `fileType` string
    :   ​

    `description` string
    :   ​

    `createdBy` string (RID)
    :   ​

    `properties` map of `PropertyName` to string
    :   ​

    `labels` array of string
    :   ​

    `createdAt` string (date-time)
    :   ​

    `isArchived` boolean
    :   ​

Request

**curl**

```shell
curl -X POST "https://api.gov.nominal.io/api/attachments/v1/attachments/batch" \
  -H "Authorization: Bearer <api key>" \
  -H "Content-Type: application/json" \
  --data '{
  "attachmentRids": [
    "<attachment rid>"
  ]
}'
```

**requests**

```python
import requests

response = requests.post(
    "https://api.gov.nominal.io/api/attachments/v1/attachments/batch",
    headers={"Authorization": "Bearer <api key>"},
    json={"attachmentRids": ["<attachment rid>"]},
)
response.raise_for_status()
print(response.json())
```

**httpx**

```python
import httpx

response = httpx.post(
    "https://api.gov.nominal.io/api/attachments/v1/attachments/batch",
    headers={"Authorization": "Bearer <api key>"},
    json={"attachmentRids": ["<attachment rid>"]},
)
response.raise_for_status()
print(response.json())
```

**aiohttp**

```python
import asyncio

import aiohttp

async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            "https://api.gov.nominal.io/api/attachments/v1/attachments/batch",
            headers={"Authorization": "Bearer <api key>"},
            json={"attachmentRids": ["<attachment rid>"]},
        ) as response:
            response.raise_for_status()
            print(await response.json())

asyncio.run(main())
```

Response: `200`

```json
{
  "response": [
    {
      "rid": "<attachment rid>",
      "title": "<title>",
      "s3Path": "<s3 path>",
      "fileType": "<file type>",
      "description": "<description>",
      "createdBy": "<created by>",
      "properties": {
        "<key>": "<property value>"
      },
      "labels": [
        "<label>"
      ],
      "createdAt": "2026-01-01T00:00:00Z",
      "isArchived": true
    }
  ]
}
```

### Get content

GET `/attachments/v1/attachments/{rid}/content`

Get the binary content of an attachment.

Path parameters

`rid` string (RID) required
:   ​

Response: `application/octet-stream`

The body is the raw bytes.

A successful response.

Request

**curl**

```shell
curl "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>/content" \
  -H "Authorization: Bearer <api key>" \
  --output "<file>"
```

**requests**

```python
from pathlib import Path

import requests

response = requests.get(
    "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>/content",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
Path("<file>").write_bytes(response.content)
```

**httpx**

```python
from pathlib import Path

import httpx

response = httpx.get(
    "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>/content",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
Path("<file>").write_bytes(response.content)
```

**aiohttp**

```python
import asyncio
from pathlib import Path

import aiohttp

async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.get(
            "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>/content",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()
            Path("<file>").write_bytes(await response.read())

asyncio.run(main())
```

Response: `200`

The raw bytes.

### Get uri

GET `/attachments/v1/attachments/{rid}/uri`

Get a pre-signed URI to download an attachment. The link expires in 1 minute.

Path parameters

`rid` string (RID) required
:   ​

Response

`uri` string
:   ​

Request

**curl**

```shell
curl "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>/uri" \
  -H "Authorization: Bearer <api key>"
```

**requests**

```python
import requests

response = requests.get(
    "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>/uri",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
```

**httpx**

```python
import httpx

response = httpx.get(
    "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>/uri",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
print(response.json())
```

**aiohttp**

```python
import asyncio

import aiohttp

async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.get(
            "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>/uri",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()
            print(await response.json())

asyncio.run(main())
```

Response: `200`

```json
{
  "uri": "<uri>"
}
```

### Archive

PUT `/attachments/v1/attachments/{rid}/archive`

Archive an attachment.

Path parameters

`rid` string (RID) required
:   ​

Response

No content (HTTP 204).

Request

**curl**

```shell
curl -X PUT "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>/archive" \
  -H "Authorization: Bearer <api key>"
```

**requests**

```python
import requests

response = requests.put(
    "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>/archive",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
```

**httpx**

```python
import httpx

response = httpx.put(
    "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>/archive",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
```

**aiohttp**

```python
import asyncio

import aiohttp

async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.put(
            "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>/archive",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()

asyncio.run(main())
```

Response: `204`

No content.

### Unarchive

PUT `/attachments/v1/attachments/{rid}/unarchive`

Unarchive an attachment.

Path parameters

`rid` string (RID) required
:   ​

Response

No content (HTTP 204).

Request

**curl**

```shell
curl -X PUT "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>/unarchive" \
  -H "Authorization: Bearer <api key>"
```

**requests**

```python
import requests

response = requests.put(
    "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>/unarchive",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
```

**httpx**

```python
import httpx

response = httpx.put(
    "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>/unarchive",
    headers={"Authorization": "Bearer <api key>"},
)
response.raise_for_status()
```

**aiohttp**

```python
import asyncio

import aiohttp

async def main() -> None:
    async with aiohttp.ClientSession() as session:
        async with session.put(
            "https://api.gov.nominal.io/api/attachments/v1/attachments/<rid>/unarchive",
            headers={"Authorization": "Bearer <api key>"},
        ) as response:
            response.raise_for_status()

asyncio.run(main())
```

Response: `204`

No content.

## Errors

[Errors](https://dev.nominal.io/api/legacy.md#errors) shows how these errors are sent.

Each error’s `errorName` is `Attachment:` followed by its name below.

| Status | Name | Notes |
| --- | --- | --- |
| 400 | `InvalidS3Path` |  |
| 404 | `AttachmentNotFound` |  |
| 404 | `AttachmentsNotFound` |  |
| 404 | `S3FileNotFound` |  |

## Types

### Attachment

`rid` string (RID) required
:   ​

`title` string required
:   ​

`s3Path` string required
:   ​

`fileType` string required
:   ​

`description` string required
:   ​

`createdBy` string (RID) required
:   ​

`properties` map of `PropertyName` to string
:   ​

`labels` array of string
:   ​

`createdAt` string (date-time) required
:   ​

`isArchived` boolean required
:   ​

Page design based on [Scalar](https://scalar.com), MIT License.
