# Get an upload URL for a file

`POST /v1/attachments/uploads`

Checks access and limits and returns a signed URL (15 minutes) to PUT the file's bytes to. `upload` is null when the same bytes are already stored. Then record the file with attachment.create. Needs edit access to the document (or membership for workspace files).

Scope: `docs:write`.

## Request

```bash
curl -X POST "https://api.lydie.co/v1/attachments/uploads" \
  -H "Authorization: Bearer $LYDIE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "workspaceId": "01JCQ3TZ0WJ8K4M2X7T9R6N1PA",
    "contentType": "string",
    "size": 0,
    "sha256": "string"
  }'
```

## Body

- `workspaceId` (string, required): (1–64 chars)
- `documentId` (ULID, optional, nullable): Default: `null`.
- `contentType` (string, required): (1–255 chars)
- `size` (integer, required)
- `sha256` (string, required)

## Response

- `upload` (BlobUpload, required, nullable)
  - `method` ("PUT", required)
  - `url` (string, required)
  - `headers` (object, required)
  - `expiresAt` (timestamp, required)
- `maxBytes` (integer, required)

```json
{
  "upload": null,
  "maxBytes": -9007199254740991
}
```

Errors use the envelope described at https://developers.lydie.co/errors.md.
