ComposerAttachment composer.attachment@1

Generated at from openvibe-contracts v0.419.0 and openvibe-sdk v0.161.0.

Version
1.0.0
Owner
media
Visibility
public
Status
active
Compatibility
backward
Schema
https://openvibe.network/contracts/composer/attachment.v1.json

composer.attachment@1: one file a person attached to a message in the shared composer. Media stores it and answers this shape from POST /api/v1/attachments (multipart field `file`); a client keeps it until the message is sent, then names it in POST /api/v1/attachments/:id/keep. `kind` is sniffed from the bytes, never taken from the browser: image, video, audio, file or code. `thumb` is a small preview for images and video (absent for the rest), `w`/`h` the pixel size when the file is one Media can measure. An attachment nobody keeps expires after 24 hours; `expires_at` says when, and a keep extends it to the message's life.

Fields

FieldTypeRequiredDescriptionConstraints
idstringyesThe attachment id (att_ + ULID): what DELETE /api/v1/attachments/:id and POST /api/v1/attachments/:id/keep name.
  • pattern ^att_[0-9A-HJKMNP-TV-Z]{26}$
kindenumyesDecided by Media from the bytes, not the client's claim: image/video/audio when the signature matches, code for recognised source text, otherwise file. Executables are refused at upload.
  • one of "image", "video", "audio", "file", "code"
namestringyesThe file's original name, sanitised for display; never a path.
  • minLength 1
  • maxLength 255
sizeintegeryesBytes stored.
  • minimum 1
mimestringyesThe content type Media serves the bytes as, from the sniffed kind and format.
urlstringyesAbsolute https URL the bytes are served at. It stays valid while the attachment exists; a kept attachment is the message's to serve.
  • format uri
thumbstring | nullAbsolute URL of a preview image: an image's own small copy or a video's first frame. Null when Media could not make one (or the kind has none).
  • format uri
winteger | nullPixel width of an image, video or video preview; null when unknown.
  • minimum 1
hinteger | nullPixel height of an image, video or video preview; null when unknown.
  • minimum 1
expires_atstringyesWhen an unkept attachment is deleted. The upload answers now + 24 hours; a keep moves it to the kept window.
  • format date-time

Examples

From the contract's own test fixtures: valid ones validate, rejected ones must fail.

Valid: file
{
  "id": "att_01JAB2C3D4E5F6G7H8J9K0MNPS",
  "kind": "file",
  "name": "notes.txt",
  "size": 42,
  "mime": "text/plain",
  "url": "https://openvibe.media/a/01JAB2C3D4E5F6G7H8J9K0MNPS/notes.txt",
  "expires_at": "2026-11-11T12:00:00.000Z"
}
Valid: image
{
  "id": "att_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "kind": "image",
  "name": "screenshot.png",
  "size": 184320,
  "mime": "image/png",
  "url": "https://openvibe.media/a/01JAB2C3D4E5F6G7H8J9K0MNPQ/screenshot.png",
  "thumb": "https://openvibe.media/a/01JAB2C3D4E5F6G7H8J9K0MNPQ/thumb.jpg",
  "w": 1280,
  "h": 720,
  "expires_at": "2026-11-11T12:00:00.000Z"
}
Valid: video
{
  "id": "att_01JAB2C3D4E5F6G7H8J9K0MNPR",
  "kind": "video",
  "name": "clip.mp4",
  "size": 52428800,
  "mime": "video/mp4",
  "url": "https://openvibe.media/a/01JAB2C3D4E5F6G7H8J9K0MNPR/clip.mp4",
  "thumb": "https://openvibe.media/a/01JAB2C3D4E5F6G7H8J9K0MNPR/thumb.jpg",
  "w": 1920,
  "h": 1080,
  "expires_at": "2026-11-11T12:00:00.000Z"
}
Rejected: bad-id
{
  "id": "att_1",
  "kind": "file",
  "name": "a.txt",
  "size": 1,
  "mime": "text/plain",
  "url": "https://openvibe.media/a/x/a.txt",
  "expires_at": "2026-11-11T12:00:00.000Z"
}
Rejected: bad-kind
{
  "id": "att_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "kind": "spreadsheet",
  "name": "book.xlsx",
  "size": 12,
  "mime": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  "url": "https://openvibe.media/a/x/book.xlsx",
  "expires_at": "2026-11-11T12:00:00.000Z"
}
Rejected: no-url
{
  "id": "att_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "kind": "image",
  "name": "screenshot.png",
  "size": 184320,
  "mime": "image/png",
  "expires_at": "2026-11-11T12:00:00.000Z"
}

Validate

const contracts = require('openvibe-contracts');
contracts.validate('composer.attachment@1', value);   // { valid, errors: [{ path, message }] }