---
title: "network.user-card@1 · OpenVibe.Services"
canonical: "https://openvibe.services/docs/contracts/network.user-card"
updated: null
---

# network.user-card@1 · OpenVibe.Services

HTML: [network.user-card@1 · OpenVibe.Services](https://openvibe.services/docs/contracts/network.user-card)

# NetworkUserCard `network.user-card@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: public
- Status: active
- Compatibility: backward
- Schema: [`https://openvibe.network/contracts/network/user-card.v1.json`](/docs/contracts/network.user-card.json)

network.user-card@1 (ask 287): the one public user card read, GET /api/v1/people/:username/card on OpenVibe.Network. It is public and credential-free; a signed-in viewer may send their Network token (Authorization: Bearer …) and then also receives \`actions\` computed for that viewer, never cached. Without a viewer, or on the viewer's own card, \`actions\` carries Profile and Channel only. A missing, expired or revoked token reads as anonymous, never a 401. Hidden fields are absent, never zero, offline or a placeholder; no presence, page titles or visited URLs leave the read.

## Fields

| Field | Type | Required | Description | Constraints |
| --- | --- | --- | --- | --- |
| `username` | string | yes |  | - `pattern ^[A-Za-z0-9_]{3,24}$` |
| `display_name` | string |  |  | - `minLength 1`<br>- `maxLength 200` |
| `avatar_url` | string |  |  | - `pattern ^https://`<br>- `format uri` |
| `profile_url` | string | yes |  | - `pattern ^https://`<br>- `format uri` |
| `level` | integer |  |  | - `minimum 0` |
| `streak` | integer |  |  | - `minimum 0` |
| `badges_count` | integer |  |  | - `minimum 0` |
| `followers` | integer |  |  | - `minimum 0` |
| `live` | object |  |  | - `no other fields` |
| `live.now` | boolean | yes |  |  |
| `live.site` | const |  |  | - `= "live"` |
| `live.url` | string |  |  | - `pattern ^https://`<br>- `format uri` |
| `channel_url` | string |  |  | - `pattern ^https://`<br>- `format uri` |
| `active_sites` | array of object |  |  | - `items: no other fields` |
| `active_sites[].id` | string | yes |  | - `pattern ^[a-z][a-z0-9-]{1,39}$` |
| `active_sites[].name` | string | yes |  | - `minLength 1`<br>- `maxLength 80` |
| `active_sites[].url` | string | yes |  | - `pattern ^https://`<br>- `format uri` |
| `actions` | `https://openvibe.network/contracts/network/user-card.v1.json#/$defs/action` | yes | What the viewer can do, by what is possible for the pair. Order is the card's order. Each action either opens somewhere (\`href\`) or calls a Network route with the viewer's token (\`method\` + \`path\`, and \`body\` where the route needs one). |  |

## Examples

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

 Valid: anonymous

~~~~
{
  "username": "Example",
  "display_name": "Example",
  "avatar_url": "https://openvibe.network/avatar/Example?s=160",
  "profile_url": "https://openvibe.network/@Example",
  "level": 4,
  "streak": 3,
  "badges_count": 2,
  "followers": 10,
  "live": {
    "now": true,
    "site": "live",
    "url": "https://openvibe.live/@Example"
  },
  "channel_url": "https://openvibe.live/@Example",
  "active_sites": [
    {
      "id": "live",
      "name": "Live",
      "url": "https://openvibe.live"
    }
  ],
  "actions": [
    {
      "id": "profile",
      "label": "Profile",
      "href": "https://openvibe.network/@Example"
    },
    {
      "id": "channel",
      "label": "Channel",
      "href": "https://openvibe.live/@Example"
    }
  ]
}
~~~~

Valid: viewer-actions

~~~~
{
  "username": "Example",
  "profile_url": "https://openvibe.network/@Example",
  "actions": [
    {
      "id": "profile",
      "label": "Profile",
      "href": "https://openvibe.network/@Example"
    },
    {
      "id": "message",
      "label": "Message",
      "href": "https://openvibe.chat/messages"
    },
    {
      "id": "follow",
      "label": "Follow",
      "method": "PUT",
      "path": "/api/v1/me/follows/channel/Example",
      "state": {
        "following": false
      }
    },
    {
      "id": "add-friend",
      "label": "Add friend",
      "method": "PUT",
      "path": "/api/v1/me/friends/Example",
      "state": {
        "friendship": "none"
      }
    },
    {
      "id": "tip",
      "label": "Tip",
      "href": "https://openvibe.tips/Example"
    },
    {
      "id": "mute",
      "label": "Mute",
      "method": "PUT",
      "path": "/api/v1/me/mutes/Example",
      "state": {
        "muted": false
      }
    },
    {
      "id": "block",
      "label": "Block",
      "method": "PUT",
      "path": "/api/v1/me/blocks/Example",
      "state": {
        "blocked": false
      }
    },
    {
      "id": "report",
      "label": "Report",
      "method": "POST",
      "path": "/api/v1/me/reports",
      "body": {
        "target": "Example",
        "reason": "other",
        "detail": ""
      },
      "state": {
        "reported": false
      }
    }
  ]
}
~~~~

Rejected: action-without-destination

~~~~
{
  "username": "Example",
  "profile_url": "https://openvibe.network/@Example",
  "actions": [
    {
      "id": "message",
      "label": "Message",
      "state": {}
    }
  ]
}
~~~~

Rejected: bad-friendship

~~~~
{
  "username": "Example",
  "profile_url": "https://openvibe.network/@Example",
  "actions": [
    {
      "id": "add-friend",
      "label": "Add friend",
      "method": "PUT",
      "path": "/api/v1/me/friends/Example",
      "state": {
        "friendship": "maybe"
      }
    }
  ]
}
~~~~

Rejected: http-href

~~~~
{
  "username": "Example",
  "profile_url": "https://openvibe.network/@Example",
  "actions": [
    {
      "id": "profile",
      "label": "Profile",
      "href": "http://openvibe.network/@Example"
    }
  ]
}
~~~~

## Validate

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