---
title: "composer.mention@1 · OpenVibe.Services"
canonical: "https://openvibe.services/docs/contracts/composer.mention"
updated: null
---

# composer.mention@1 · OpenVibe.Services

HTML: [composer.mention@1 · OpenVibe.Services](https://openvibe.services/docs/contracts/composer.mention)

# ComposerMention `composer.mention@1`

Generated at 2026-11-13 06:25:48 UTC from [`openvibe-contracts v0.419.0`](https://github.com/OpenVibers/OpenVibe.Contracts/tree/v0.419.0) and [`openvibe-sdk v0.161.0`](https://github.com/OpenVibers/OpenVibe.SDK/tree/v0.161.0).

- Version: 1.0.0
- Owner: network
- Visibility: first-party
- Status: active
- Compatibility: backward
- Schema: [`https://openvibe.network/contracts/composer/mention.v1.json`](/docs/contracts/composer.mention.json)

composer.mention@1: one thing the composer's @ menu can insert, from GET /api/v1/mentions on OpenVibe.Network. kind person (a person the caller follows first, then a public person), repo (a repository on OpenVibe Git the caller can see), site (a first-party OpenVibe site) or file (a file of the message's own context). \`id\` is the stable id inside its kind, \`label\` what the menu shows, \`handle\` the @name when the kind has one, \`avatar\` the picture, and \`url\` where choosing it links.

## Fields

| Field | Type | Required | Description | Constraints |
| --- | --- | --- | --- | --- |
| `kind` | enum | yes | What is mentioned. The same person is a person; a repository on OpenVibe Git is a repo; a first-party OpenVibe site is a site; a file of the message's context (an attachment or a repository file) is a file. | - `one of "person", "repo", "site", "file"` |
| `id` | string | yes | The stable id inside the kind: a usr\_… subject for a person, owner/name for a repo, a site id for a site, a path or attachment id for a file. | - `minLength 1`<br>- `maxLength 200` |
| `label` | string | yes | What the menu shows (a display name, owner/name, the site's name, a file name). | - `minLength 1`<br>- `maxLength 200` |
| `handle` | string |  | The @name when the kind has one: a person's username, a site's short name. Absent for a repo or a file. | - `pattern ^[A-Za-z0-9_.-]+$`<br>- `maxLength 64` |
| `avatar` | string \| null |  | Absolute URL of the picture to show beside the label. Null when the kind has none (a file, a site without a mark). | - `format uri` |
| `url` | string | yes | Absolute https URL where choosing the mention leads: the person's profile, the repository, the site's home or the file. | - `format uri` |

## Examples

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

 Valid: person

~~~~
{
  "kind": "person",
  "id": "usr_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "label": "Sam Rivera",
  "handle": "sam",
  "avatar": "https://openvibe.network/avatar/sam?s=64",
  "url": "https://openvibe.network/@sam"
}
~~~~

Valid: repo

~~~~
{
  "kind": "repo",
  "id": "openvibers/OpenVibe.Contracts",
  "label": "OpenVibers/OpenVibe.Contracts",
  "url": "https://git.openvibe.codes/OpenVibers/OpenVibe.Contracts"
}
~~~~

Rejected: bad-kind

~~~~
{
  "kind": "channel",
  "id": "openvibe",
  "label": "OpenVibe",
  "url": "https://openvibe.live/openvibe"
}
~~~~

Rejected: no-label

~~~~
{
  "kind": "site",
  "id": "live",
  "url": "https://openvibe.live"
}
~~~~

## Validate

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