Skip to main content
POST
/
v1
/
skills
/
upload
Upload a skill
curl --request POST \
  --url https://api.hq.zone/v1/skills/upload \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "body_b64": "<string>",
  "content_type": "<string>",
  "filename": "<string>",
  "caption": "<string>",
  "category": "<string>",
  "channel_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "scope": "<string>",
  "tags": [
    "<string>"
  ]
}
'
{
  "deduplicated": true,
  "document_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "download_url": "<string>",
  "sha256": "<string>",
  "size_bytes": 1,
  "enriched": true
}

Authorizations

Authorization
string
header
required

Personal Access Token. Send as Authorization: Bearer hq_pat_....

Body

application/json
body_b64
string
required

Base64-encoded payload. 16 MiB cap on the JSON body limits raw to ~12 MiB - the multipart streaming path lands in pass 2.

content_type
string
required
filename
string
required
caption
string | null
category
string | null

Free-form user category; the auto-categoriser may overwrite this in a follow-up worker pass once we have Haiku wired.

channel_id
string<uuid> | null

Required iff scope == "channel".

scope
string

private | channel | team. Defaults to private.

tags
string[]

Response

Workspace skill created

deduplicated
boolean
required

True iff this hashed identical to an existing document in this tenant - we still record the new metadata row but the Trove object is shared. The UI surfaces this as a "saved (dedup'd against existing copy)" hint.

document_id
string<uuid>
required
download_url
string
required
sha256
string
required
size_bytes
integer<int64>
required
Required range: x >= 0
enriched
boolean

True iff this was a same-owner/same-scope dedup AND the caller supplied new metadata (tags/caption/category) that we actually merged onto the existing row. Lets the UI say "already in your library - details updated" honestly vs a bare "already there".