QuestAppQuest quest.app-quest@1

Generated at from openvibe-contracts v0.193.1 and openvibe-sdk v0.48.0.

Version
1.0.0
Owner
quest
Visibility
public
Status
active
Compatibility
backward
Schema
https://openvibe.network/contracts/quest/app-quest.v1.json

quest.app-quest@1: one app quest as OpenVibe.Quest keeps it (the answer to PUT and GET /api/v1/app-quests[/:slug]). id is app.<project_key>.<slug>; badge.id is the same id; completions counts the people who finished it.

Fields

FieldTypeRequiredDescriptionConstraints
idstringyes
  • pattern ^app\.p[0-9a-z]{26}\.[a-z0-9][a-z0-9-]{0,47}$
slugstringyes
  • pattern ^[a-z0-9][a-z0-9-]{0,47}$
project_idstringyes
  • pattern ^prj_[0-9A-HJKMNP-TV-Z]{26}$
appstringyesThe app that last defined it.
  • pattern ^app:app_[0-9A-HJKMNP-TV-Z]{26}$
envenumyes
  • one of "sandbox", "production"
titlestringyes
  • minLength 1
  • maxLength 80
whystring | null
  • maxLength 300
stepsarray of objectyes
  • minItems 1
  • maxItems 5
  • items: no other fields
steps[].event_typestringyesOne of the app's own event types (app.<project_key>.<name>), as it publishes them at OpenVibe.Events.
  • pattern ^app\.p[0-9a-z]{26}\.[a-z0-9_]+(\.[a-z0-9_]+){0,3}$
steps[].countintegeryes
  • minimum 1
  • maximum 1000
steps[].labelstringyes
  • minLength 1
  • maxLength 120
badgeobjectyes
  • no other fields
badge.idstringyes
badge.namestringyes
  • minLength 1
  • maxLength 40
urlstring | null
  • maxLength 500
statusenumyes
  • one of "active", "retired"
created_atstringyes
  • format date-time
updated_atstringyes
  • format date-time
completionsintegeryes
  • minimum 0

Examples

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

Valid: one
{
  "id": "app.p01jab2c3d4e5f6g7h8j9k0mnpq.collector",
  "slug": "collector",
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "app": "app:app_01JAB2C3D4E5F6G7H8J9K0MNPR",
  "env": "production",
  "title": "Collector",
  "why": null,
  "steps": [
    {
      "event_type": "app.p01jab2c3d4e5f6g7h8j9k0mnpq.gem.found",
      "count": 5,
      "label": "Find a gem"
    }
  ],
  "badge": {
    "id": "app.p01jab2c3d4e5f6g7h8j9k0mnpq.collector",
    "name": "Gem Collector"
  },
  "url": null,
  "status": "active",
  "created_at": "2026-10-15T22:00:00.000Z",
  "updated_at": "2026-10-15T22:00:00.000Z",
  "completions": 0
}
Rejected: bad-id
{
  "id": "live.collector",
  "slug": "collector",
  "project_id": "prj_01JAB2C3D4E5F6G7H8J9K0MNPQ",
  "app": "app:app_01JAB2C3D4E5F6G7H8J9K0MNPR",
  "env": "production",
  "title": "Collector",
  "why": null,
  "steps": [
    {
      "event_type": "app.p01jab2c3d4e5f6g7h8j9k0mnpq.gem.found",
      "count": 5,
      "label": "Find a gem"
    }
  ],
  "badge": {
    "id": "x",
    "name": "x"
  },
  "url": null,
  "status": "active",
  "created_at": "2026-10-15T22:00:00.000Z",
  "updated_at": "2026-10-15T22:00:00.000Z",
  "completions": 0
}

Validate

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