---
title: "network.me-consent-apps-result@1 · OpenVibe.Services"
canonical: "https://openvibe.services/docs/contracts/network.me-consent-apps-result"
updated: null
---

# network.me-consent-apps-result@1 · OpenVibe.Services

HTML: [network.me-consent-apps-result@1 · OpenVibe.Services](https://openvibe.services/docs/contracts/network.me-consent-apps-result)

# NetworkMeConsentAppsResult `network.me-consent-apps-result@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/me-consent-apps-result.v1.json`](/docs/contracts/network.me-consent-apps-result.json)

network.me-consent-apps-result@1 (the consent plan's C4, 2026-11-07): "Apps you allowed" on the signed-in person's account page. GET /api/v1/me/consent/apps on OpenVibe.Network. It lists every app the person granted a purpose to on its sign-in screen (consent:<purpose>, network.consent-claim@1), with the purposes granted and those refused in the last 30 days. It also carries the words the app consent screen shows for each purpose. Only the person's own session reads it; an app never sees this list, its own entry included.

## Fields

| Field | Type | Required | Description | Constraints |
| --- | --- | --- | --- | --- |
| `purposes` | array of object | yes | The purposes an app may ask for, with the exact words the app consent screen shows. | - `maxItems 8`<br>- `items: no other fields` |
| `purposes[].id` | enum | yes |  | - `one of "ai.train", "data.public", "face.recognize", "app.data"` |
| `purposes[].title` | string | yes |  | - `minLength 1`<br>- `maxLength 80` |
| `purposes[].allows` | string | yes | What ticking it allows the app, in one plain line. | - `minLength 1`<br>- `maxLength 300` |
| `purposes[].cannot_undo` | string | yes | What turning it off later cannot undo (empty when nothing). | - `maxLength 300` |
| `purposes[].adults_only` | boolean | yes | Ticking it asks the person to confirm they are 18 or older. |  |
| `purposes[].text_version` | string | yes |  | - `pattern ^[0-9]{4}-[0-9]{2}-[0-9]{2}\.[0-9]{1,3}$` |
| `apps` | array of object | yes | One entry per app with a purpose granted or refused, apps with an active grant first, then by name. | - `maxItems 200`<br>- `items: no other fields` |
| `apps[].client` | string | yes | The app's OAuth client id. | - `pattern ^[A-Za-z0-9][A-Za-z0-9_.:-]{0,79}$` |
| `apps[].name` | string | yes | The app's name as its developer (or OpenVibe, for its own sites) registered it. | - `minLength 1`<br>- `maxLength 120` |
| `apps[].third_party` | boolean | yes | True for a developer's app (app\_<ULID>), false for an OpenVibe site. |  |
| `apps[].granted` | array of object | yes | The purposes the app holds now (active network.consent@1 records with this client). | - `maxItems 4`<br>- `items: no other fields` |
| `apps[].granted[].consent_id` | string | yes |  | - `pattern ^cns_[0-9A-HJKMNP-TV-Z]{26}$` |
| `apps[].granted[].purpose` | enum | yes |  | - `one of "ai.train", "data.public", "face.recognize", "app.data"` |
| `apps[].granted[].granted_at` | string | yes |  | - `format date-time` |
| `apps[].granted[].text_version` | string | yes |  | - `pattern ^[0-9]{4}-[0-9]{2}-[0-9]{2}\.[0-9]{1,3}$` |
| `apps[].quiet` | array of object | yes | The purposes the person refused this app in the last 30 days: the app does not ask for them again until quiet\_until. DELETE /api/v1/me/consent/:purpose/:client/refusal ends that early, so the next sign-in asks. | - `maxItems 4`<br>- `items: no other fields` |
| `apps[].quiet[].purpose` | enum | yes |  | - `one of "ai.train", "data.public", "face.recognize", "app.data"` |
| `apps[].quiet[].refused_at` | string | yes |  | - `format date-time` |
| `apps[].quiet[].quiet_until` | string | yes |  | - `format date-time` |

## Examples

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

 Valid: none

~~~~
{
  "purposes": [
    {
      "id": "ai.train",
      "title": "Train AI on your content",
      "allows": "It may use your streams, videos, voice, chat, posts, pictures and code to train or improve its AI.",
      "cannot_undo": "A model it already trained keeps what it learned.",
      "adults_only": true,
      "text_version": "2026-11-07.1"
    },
    {
      "id": "app.data",
      "title": "Use your content",
      "allows": "It may read and use your streams, videos, posts and other content for its own features.",
      "cannot_undo": "A copy it already made stays with the app.",
      "adults_only": false,
      "text_version": "2026-11-07.1"
    }
  ],
  "apps": []
}
~~~~

Valid: two-apps

~~~~
{
  "purposes": [
    {
      "id": "ai.train",
      "title": "Train AI on your content",
      "allows": "It may use your streams, videos, voice, chat, posts, pictures and code to train or improve its AI.",
      "cannot_undo": "A model it already trained keeps what it learned.",
      "adults_only": true,
      "text_version": "2026-11-07.1"
    },
    {
      "id": "app.data",
      "title": "Use your content",
      "allows": "It may read and use your streams, videos, posts and other content for its own features.",
      "cannot_undo": "A copy it already made stays with the app.",
      "adults_only": false,
      "text_version": "2026-11-07.1"
    }
  ],
  "apps": [
    {
      "client": "app_01K6R3A1B2C3D4E5F6G7H8J9KD",
      "name": "Clip Helper",
      "third_party": true,
      "granted": [
        {
          "consent_id": "cns_01K9A3A1B2C3D4E5F6G7H8J9KC",
          "purpose": "ai.train",
          "granted_at": "2026-11-07T05:00:00.000Z",
          "text_version": "2026-11-07.1"
        }
      ],
      "quiet": [
        {
          "purpose": "face.recognize",
          "refused_at": "2026-11-07T05:00:00.000Z",
          "quiet_until": "2026-12-07T05:00:00.000Z"
        }
      ]
    },
    {
      "client": "openvibe-live",
      "name": "OpenVibe.Live",
      "third_party": false,
      "granted": [],
      "quiet": [
        {
          "purpose": "data.public",
          "refused_at": "2026-11-06T05:00:00.000Z",
          "quiet_until": "2026-12-06T05:00:00.000Z"
        }
      ]
    }
  ]
}
~~~~

Rejected: bad-client

~~~~
{
  "purposes": [
    {
      "id": "ai.train",
      "title": "Train AI on your content",
      "allows": "It may use your streams, videos, voice, chat, posts, pictures and code to train or improve its AI.",
      "cannot_undo": "A model it already trained keeps what it learned.",
      "adults_only": true,
      "text_version": "2026-11-07.1"
    },
    {
      "id": "app.data",
      "title": "Use your content",
      "allows": "It may read and use your streams, videos, posts and other content for its own features.",
      "cannot_undo": "A copy it already made stays with the app.",
      "adults_only": false,
      "text_version": "2026-11-07.1"
    }
  ],
  "apps": [
    {
      "client": "not an app id!",
      "name": "Clip Helper",
      "third_party": true,
      "granted": [
        {
          "consent_id": "cns_01K9A3A1B2C3D4E5F6G7H8J9KC",
          "purpose": "ai.train",
          "granted_at": "2026-11-07T05:00:00.000Z",
          "text_version": "2026-11-07.1"
        }
      ],
      "quiet": [
        {
          "purpose": "face.recognize",
          "refused_at": "2026-11-07T05:00:00.000Z",
          "quiet_until": "2026-12-07T05:00:00.000Z"
        }
      ]
    },
    {
      "client": "openvibe-live",
      "name": "OpenVibe.Live",
      "third_party": false,
      "granted": [],
      "quiet": [
        {
          "purpose": "data.public",
          "refused_at": "2026-11-06T05:00:00.000Z",
          "quiet_until": "2026-12-06T05:00:00.000Z"
        }
      ]
    }
  ]
}
~~~~

Rejected: extra-key

~~~~
{
  "purposes": [
    {
      "id": "ai.train",
      "title": "Train AI on your content",
      "allows": "It may use your streams, videos, voice, chat, posts, pictures and code to train or improve its AI.",
      "cannot_undo": "A model it already trained keeps what it learned.",
      "adults_only": true,
      "text_version": "2026-11-07.1"
    },
    {
      "id": "app.data",
      "title": "Use your content",
      "allows": "It may read and use your streams, videos, posts and other content for its own features.",
      "cannot_undo": "A copy it already made stays with the app.",
      "adults_only": false,
      "text_version": "2026-11-07.1"
    }
  ],
  "apps": [
    {
      "client": "app_01K6R3A1B2C3D4E5F6G7H8J9KD",
      "name": "Clip Helper",
      "third_party": true,
      "granted": [
        {
          "consent_id": "cns_01K9A3A1B2C3D4E5F6G7H8J9KC",
          "purpose": "ai.train",
          "granted_at": "2026-11-07T05:00:00.000Z",
          "text_version": "2026-11-07.1"
        }
      ],
      "quiet": [
        {
          "purpose": "face.recognize",
          "refused_at": "2026-11-07T05:00:00.000Z",
          "quiet_until": "2026-12-07T05:00:00.000Z"
        }
      ],
      "refused": [
        "face.recognize"
      ]
    },
    {
      "client": "openvibe-live",
      "name": "OpenVibe.Live",
      "third_party": false,
      "granted": [],
      "quiet": [
        {
          "purpose": "data.public",
          "refused_at": "2026-11-06T05:00:00.000Z",
          "quiet_until": "2026-12-06T05:00:00.000Z"
        }
      ]
    }
  ]
}
~~~~

Rejected: quiet-without-end

~~~~
{
  "purposes": [
    {
      "id": "ai.train",
      "title": "Train AI on your content",
      "allows": "It may use your streams, videos, voice, chat, posts, pictures and code to train or improve its AI.",
      "cannot_undo": "A model it already trained keeps what it learned.",
      "adults_only": true,
      "text_version": "2026-11-07.1"
    },
    {
      "id": "app.data",
      "title": "Use your content",
      "allows": "It may read and use your streams, videos, posts and other content for its own features.",
      "cannot_undo": "A copy it already made stays with the app.",
      "adults_only": false,
      "text_version": "2026-11-07.1"
    }
  ],
  "apps": [
    {
      "client": "app_01K6R3A1B2C3D4E5F6G7H8J9KD",
      "name": "Clip Helper",
      "third_party": true,
      "granted": [
        {
          "consent_id": "cns_01K9A3A1B2C3D4E5F6G7H8J9KC",
          "purpose": "ai.train",
          "granted_at": "2026-11-07T05:00:00.000Z",
          "text_version": "2026-11-07.1"
        }
      ],
      "quiet": [
        {
          "purpose": "face.recognize",
          "refused_at": "2026-11-07T05:00:00.000Z"
        }
      ]
    },
    {
      "client": "openvibe-live",
      "name": "OpenVibe.Live",
      "third_party": false,
      "granted": [],
      "quiet": [
        {
          "purpose": "data.public",
          "refused_at": "2026-11-06T05:00:00.000Z",
          "quiet_until": "2026-12-06T05:00:00.000Z"
        }
      ]
    }
  ]
}
~~~~

Rejected: retired-purpose

~~~~
{
  "purposes": [
    {
      "id": "ai.train",
      "title": "Train AI on your content",
      "allows": "It may use your streams, videos, voice, chat, posts, pictures and code to train or improve its AI.",
      "cannot_undo": "A model it already trained keeps what it learned.",
      "adults_only": true,
      "text_version": "2026-11-07.1"
    },
    {
      "id": "app.data",
      "title": "Use your content",
      "allows": "It may read and use your streams, videos, posts and other content for its own features.",
      "cannot_undo": "A copy it already made stays with the app.",
      "adults_only": false,
      "text_version": "2026-11-07.1"
    }
  ],
  "apps": [
    {
      "client": "app_01K6R3A1B2C3D4E5F6G7H8J9KD",
      "name": "Clip Helper",
      "third_party": true,
      "granted": [
        {
          "consent_id": "cns_01K9A3A1B2C3D4E5F6G7H8J9KC",
          "purpose": "ai.looks",
          "granted_at": "2026-11-07T05:00:00.000Z",
          "text_version": "2026-11-07.1"
        }
      ],
      "quiet": [
        {
          "purpose": "face.recognize",
          "refused_at": "2026-11-07T05:00:00.000Z",
          "quiet_until": "2026-12-07T05:00:00.000Z"
        }
      ]
    },
    {
      "client": "openvibe-live",
      "name": "OpenVibe.Live",
      "third_party": false,
      "granted": [],
      "quiet": [
        {
          "purpose": "data.public",
          "refused_at": "2026-11-06T05:00:00.000Z",
          "quiet_until": "2026-12-06T05:00:00.000Z"
        }
      ]
    }
  ]
}
~~~~

## Validate

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