Calafai Docs

Attachments API Reference

Attachments API Reference

Attachments allow tenants to upload files to engagements. Uploaded files are stored in Supabase Storage and automatically processed to generate a manifest and context index that the engine uses during crew execution.

Base URL: /api/engagements/:id/attachments

Authentication: All endpoints require authentication (cookie session or Bearer API key).


List Attachments

GET /api/engagements/:id/attachments

Returns all attachments for the specified engagement.

Path Parameters

ParameterTypeDescription
idstringEngagement ID

Response

{
  "attachments": [
    {
      "id": "clxyz100att",
      "filename": "brand-guidelines.pdf",
      "mimeType": "application/pdf",
      "sizeBytes": 2451890,
      "category": "brand_assets",
      "summary": "Official brand guidelines including color palette and typography",
      "uploadedBy": "clxyz200usr",
      "createdAt": "2025-06-01T09:15:00.000Z"
    },
    {
      "id": "clxyz101att",
      "filename": "competitor-data.csv",
      "mimeType": "text/csv",
      "sizeBytes": 34521,
      "category": "data",
      "summary": null,
      "uploadedBy": "clxyz200usr",
      "createdAt": "2025-06-01T09:20:00.000Z"
    }
  ]
}

Example

curl -X GET https://app.groundtruth.ai/api/engagements/clxyz500eng/attachments \
  -H "Authorization: Bearer gt_live_abc123..."

Upload Attachment

POST /api/engagements/:id/attachments

Uploads a file to the engagement. Requires write access (member+ role or read_write API key scope).

Path Parameters

ParameterTypeDescription
idstringEngagement ID

Request

Content-Type: multipart/form-data

FieldTypeRequiredDescription
filefileYesThe file to upload
categorystringNoOne of: reference, styleguide, design_inspiration, data, brand_assets
summarystringNoHuman-readable description of the file contents

Allowed File Types

CategoryExtensions
Modern Office.pdf, .docx, .xlsx, .pptx
Legacy Office.doc, .xls, .ppt
Open formats.odt, .ods, .odp, .rtf
Text / data.csv, .txt, .md, .json, .yaml, .yml
Web.html, .htm
Images.png, .jpg, .jpeg, .svg
Archives.zip

MIME types are automatically normalized from file extension. This fixes browsers that misreport Office XML formats (.docx, .xlsx, .pptx) as application/octet-stream or application/zip.

Plan Limits

PlanMax File SizeMax Total Storage
Starter10 MB100 MB
Professional50 MB500 MB
Enterprise100 MB2 GB

Response

Status: 201 Created

{
  "attachment": {
    "id": "clxyz102att",
    "filename": "market-research.pdf",
    "mimeType": "application/pdf",
    "sizeBytes": 1048576,
    "category": "reference",
    "summary": "Q3 2025 market research report",
    "uploadedBy": "clxyz200usr",
    "createdAt": "2025-06-01T10:00:00.000Z"
  }
}

Side Effects

  • Regenerates the attachment manifest for the engagement
  • Regenerates the context index used by the engine during crew execution
  • Dispatches attachment.uploaded webhook event

Example

curl -X POST https://app.groundtruth.ai/api/engagements/clxyz500eng/attachments \
  -H "Authorization: Bearer gt_live_abc123..." \
  -F "file=@/path/to/market-research.pdf" \
  -F "category=reference" \
  -F "summary=Q3 2025 market research report"

Errors

StatusDescription
400No file provided, unsupported file type, or file exceeds size limit
403Write access required
404Engagement not found
413Total storage limit exceeded for current plan

Get Attachment

GET /api/engagements/:id/attachments/:attachmentId

Returns attachment metadata along with a signed download URL.

Path Parameters

ParameterTypeDescription
idstringEngagement ID
attachmentIdstringAttachment ID

Response

{
  "attachment": {
    "id": "clxyz100att",
    "filename": "brand-guidelines.pdf",
    "mimeType": "application/pdf",
    "sizeBytes": 2451890,
    "category": "brand_assets",
    "summary": "Official brand guidelines including color palette and typography",
    "uploadedBy": "clxyz200usr",
    "createdAt": "2025-06-01T09:15:00.000Z"
  },
  "downloadUrl": "https://xyz.supabase.co/storage/v1/object/sign/attachments/..."
}

The downloadUrl is a signed URL valid for 1 hour from the time of the request. After expiry, request a new URL by calling this endpoint again.

Example

curl -X GET https://app.groundtruth.ai/api/engagements/clxyz500eng/attachments/clxyz100att \
  -H "Authorization: Bearer gt_live_abc123..."

Errors

StatusDescription
404Attachment or engagement not found

Delete Attachment

DELETE /api/engagements/:id/attachments/:attachmentId

Deletes an attachment from the engagement. Requires write access. Removes the file from Supabase Storage and regenerates the manifest.

Path Parameters

ParameterTypeDescription
idstringEngagement ID
attachmentIdstringAttachment ID

Response

{
  "success": true
}

Side Effects

  • Removes the file from Supabase Storage
  • Regenerates the attachment manifest for the engagement

Example

curl -X DELETE https://app.groundtruth.ai/api/engagements/clxyz500eng/attachments/clxyz100att \
  -H "Authorization: Bearer gt_live_abc123..."

Errors

StatusDescription
403Write access required
404Attachment or engagement not found

Add URL as Attachment

POST /api/engagements/:id/attachments/from-url

Fetches a URL, extracts its text content, and stores it as a markdown attachment. The engine can then use this content as context during crew execution. Requires write access.

Path Parameters

ParameterTypeDescription
idstringEngagement ID

Request

Content-Type: application/json

FieldTypeRequiredDescription
urlstringYesThe URL to fetch (must be HTTP or HTTPS)
categorystringNoOne of: reference, styleguide, design_inspiration, data, brand_assets

Response

Status: 201 Created

{
  "attachment": {
    "id": "clxyz103att",
    "filename": "example.com_blog_post.md",
    "mimeType": "text/markdown",
    "sizeBytes": 15234,
    "category": "reference",
    "summary": "Fetched from example.com: Blog Post Title",
    "sourceUrl": "https://example.com/blog/post",
    "uploadedBy": "clxyz200usr",
    "createdAt": "2025-06-01T10:30:00.000Z"
  }
}

Behavior

  • Fetches the URL with a 15-second timeout
  • HTML content is converted to plain text (scripts/styles stripped)
  • Content is stored as a .md file with source metadata header
  • Duplicate filenames are auto-suffixed (_1, _2, etc.)
  • Internal/private IPs are blocked (localhost, 10.x, 192.168.x, 172.16-31.x)
  • Maximum fetched content size: 5MB (text truncated to 500KB)
  • Plan-based storage limits apply (same as file uploads)

Side Effects

  • Regenerates the attachment manifest for the engagement
  • Regenerates the context index used by the engine during crew execution
  • Dispatches attachment.uploaded webhook event (includes sourceUrl field)

Example

curl -X POST https://app.groundtruth.ai/api/engagements/clxyz500eng/attachments/from-url \
  -H "Authorization: Bearer gt_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/market-report", "category": "reference"}'

Errors

StatusDescription
400Missing URL, invalid URL format, unsupported scheme, or private IP
403Write access required
404Engagement not found
413Fetched content exceeds plan storage limits
422URL could not be fetched or returned no extractable content

On this page