# Settings and features Canonical page: https://docs.ovok.com/settings-and-features Source Markdown: https://docs.ovok.com/llms/settings-and-features.md Understand project features, settings, defaults, and the APIs that control them in Ovok. Ovok gives each project two kinds of controls. **Features** switch platform capabilities on for the whole project. **Settings** configure how a particular user flow behaves. Knowing which one you need helps avoid changing a project-wide capability when you only mean to change one audience's sign-in or registration flow. ## Feature or setting? A **feature** is a capability the platform turns on for your project: automations, scheduled jobs, email sent from automations, live subscriptions, all-or-nothing batch writes, AI, and document-reading operations. When a feature-gated capability is off, it is unavailable to everyone in the project, whatever their role. A **setting** is a rule you choose for how your project behaves for its users: who may sign in, register, or be invited; where links in your emails point; and which access policy a new practitioner receives. If a setting is off, the affected flow refuses one audience while other project operations continue to work. > **Features answer “Can my project do this at all?” Settings answer “How should my project behave?”** ### Which one do I need? Ask these questions: 1. If I turn it off, does an operation stop existing for everyone (a feature), or does one group get refused in one flow (a setting)? 2. Is it a name from a fixed list that is either on or absent (a feature), or a named value with a default (a setting)? 3. Does the platform provision it (a feature), or can my project admins change it as the app evolves (a setting)? | | Feature | Setting | | --- | --- | --- | | Shape | Names from a fixed list; a listed feature is on. | Named values, such as a Boolean or text value; every supported key has a default. | | Read | `GET /v1/projects/me/features` returns `{ features: [...] }`. | `GET /v1/project/settings` returns every key. An unset Boolean reads as `false`; unset text reads as `null`. | | Write | `PATCH /v1/projects/me/features` replaces the **whole list**. | `PUT /v1/project/settings/:key` changes one Boolean; `PUT /v1/project/settings/values/:key` changes one text value. | | Who | Any practitioner can read; a project admin can write. | Any practitioner can read; a project admin can write. | | When off | The feature-gated capability is unavailable to everyone in the project. | The affected flow refuses its audience; other project operations keep working. | | Usually set | When the project is created. | By admins as the app evolves. | | Inheritance | None. | On/off values do not inherit. App URLs can fall back to the parent project. | | Concurrent edit | A write can return `409`; read again, reapply your change, and retry. | A write can return `409`; read again, reapply your change, and retry. | For the authenticated examples below, set `OVOK_TOKEN` to a practitioner access token for the current project. Read requests are available to practitioners; write requests require a project admin. ## Project features The feature API reads and writes the current project's complete feature list. For example, to add `cron`, first read the current list, add `cron`, then send the entire updated list. A `PATCH` is a replacement, not an add operation: omitting a feature turns it off. ```bash curl --get 'https://api.sandbox.ovok.com/v1/projects/me/features' \ --header "Authorization: Bearer ${OVOK_TOKEN}" ``` | Response field | Example | Meaning | | --- | --- | --- | | `features` | `bots`, `cron`, `email`, `transaction-bundles`, `websocket-subscriptions` | Complete list of feature names currently enabled for this project. | ```bash curl --request PATCH \ --url 'https://api.sandbox.ovok.com/v1/projects/me/features' \ --header "Authorization: Bearer ${OVOK_TOKEN}" \ --header 'Content-Type: application/json' \ --data '{"features":["bots","cron","email","transaction-bundles","websocket-subscriptions","ai"]}' ``` The available feature names include: | Feature | Enables | | --- | --- | | [`bots`](/settings-and-features/features/bots) | Automations. | | [`cron`](/settings-and-features/features/cron) | Scheduled jobs. Add `bots` as well to run automations on a schedule. | | [`email`](/settings-and-features/features/email) | Email sent by automations. It does not control the emails Ovok sends itself. | | [`websocket-subscriptions`](/settings-and-features/features/websocket-subscriptions) | Live updates through WebSocket subscriptions. | | [`transaction-bundles`](/settings-and-features/features/transaction-bundles) | All-or-nothing FHIR transaction bundles. Without it, a transaction bundle runs as a batch. | | [`ai`](/settings-and-features/features/ai) | The AI operation, called with your own model key. | | [`aws-comprehend`](/settings-and-features/features/aws-comprehend) | Accepted and stored; no operation depends on it today. Comprehend Medical analysis is an option of `aws-textract`. | | [`aws-textract`](/settings-and-features/features/aws-textract) | Document-reading and text-extraction operations. Needs S3 file storage on the platform. | | [`google-auth-required`](/settings-and-features/features/google-auth-required) | Require Google sign-in where the platform's standard sign-in applies. | | [`graphql-introspection`](/settings-and-features/features/graphql-introspection) | Accepted and stored; GraphQL introspection is currently controlled platform-wide. | | [`validate-terminology`](/settings-and-features/features/validate-terminology) | Rejects coded values that break a required terminology binding when a resource is written. | ### Edit the feature list with care `PATCH` replaces the whole list, and the 409 only protects against a write that overlaps yours inside the same request. If two admins each read the list, change it, and send it back, the second write silently overwrites the first. Read the list immediately before you write it, and send every feature you want to keep. ## Project settings `GET /v1/project/settings` returns the complete `settings` Boolean record and `values` text record for the current project. The path is **singular**: `/project/settings`. To change a Boolean, send `{"enabled": true}` or `{"enabled": false}` to `PUT /v1/project/settings/:key`. To set a text value, send `{"value": "..."}` to `PUT /v1/project/settings/values/:key`. Send `{"value": null}` to remove a stored text value. ```bash curl --get 'https://api.sandbox.ovok.com/v1/project/settings' \ --header "Authorization: Bearer ${OVOK_TOKEN}" ``` ```bash curl --request PUT \ --url 'https://api.sandbox.ovok.com/v1/project/settings/PATIENT_REGISTRATION_ENABLED' \ --header "Authorization: Bearer ${OVOK_TOKEN}" \ --header 'Content-Type: application/json' \ --data '{"enabled":false}' ``` ```bash curl --request PUT \ --url 'https://api.sandbox.ovok.com/v1/project/settings/values/PRACTITIONER_APP_URL' \ --header "Authorization: Bearer ${OVOK_TOKEN}" \ --header 'Content-Type: application/json' \ --data '{"value":"https://app.example.com"}' ``` ### Unset settings: what the API shows and what the flow does An unset Boolean reads as `false` in the settings response. That value does **not** always describe the behavior of the flow: login, invitations, and patient registration default to enabled when unset, while practitioner self-registration defaults to disabled. The response does not tell you whether `false` was stored explicitly or is the read default. **Set each switch to the value you intend instead of relying on an unset key.** | Setting | `GET` when unset | Flow behavior when unset | | --- | --- | --- | | [`PATIENT_LOGIN_ENABLED`](/settings-and-features/settings/patient-login-enabled) | `false` | Patient sign-in is enabled. | | [`PRACTITIONER_LOGIN_ENABLED`](/settings-and-features/settings/practitioner-login-enabled) | `false` | Practitioner sign-in is enabled. | | [`PATIENT_INVITATION_ENABLED`](/settings-and-features/settings/patient-invitation-enabled) | `false` | Patient invitations are enabled, subject to their setup requirements. | | [`PRACTITIONER_INVITATION_ENABLED`](/settings-and-features/settings/practitioner-invitation-enabled) | `false` | Practitioner invitations are enabled, subject to their setup requirements. | | [`PATIENT_REGISTRATION_ENABLED`](/settings-and-features/settings/patient-registration-enabled) | `false` | Patient registration is enabled if the project has a default patient AccessPolicy. | | [`PRACTITIONER_REGISTRATION_ENABLED`](/settings-and-features/settings/practitioner-registration-enabled) | `false` | Practitioner self-registration is disabled. | ### Settings are not permissions An auth setting controls whether a sign-in, registration, or invitation flow can run. It does not define what a signed-in user can read or change; that is the access policy's job. Turning a login switch off stops new sign-ins. Once the login-switch change is deployed, it will also stop token renewals. A token already issued can remain valid until it expires, for up to 60 minutes. Registration and invitation switches also need their corresponding setup: - Patient registration requires the project's default patient AccessPolicy. - Practitioner registration requires [`DEFAULT_PRACTITIONER_ACCESS_POLICY`](/settings-and-features/settings/default-practitioner-access-policy). - Invitations need the matching app URL ([`PATIENT_APP_URL`](/settings-and-features/settings/patient-app-url) or [`PRACTITIONER_APP_URL`](/settings-and-features/settings/practitioner-app-url)) and the applicable default AccessPolicy. App URLs can fall back to the parent project. If no URL resolves, the invite request returns `409 app_url_not_configured`. The settings response reports values stored on the current project. An app URL shown as `null` there may still resolve from a parent project for link generation. ## Quick reference | I want to… | Switch | | --- | --- | | Run automations | Feature `bots`. | | Run automations on a schedule | Features `bots` and `cron`. | | Send email from an automation | Feature `email`. | | Write several records all-or-nothing | Feature `transaction-bundles`. | | Get live updates | Feature `websocket-subscriptions`. | | Require Google sign-in | Feature `google-auth-required`. | | Stop patients registering themselves | Setting `PATIENT_REGISTRATION_ENABLED` = `false`. | | Pause practitioner sign-in | Setting `PRACTITIONER_LOGIN_ENABLED` = `false`. | | Let admins invite colleagues | Setting `PRACTITIONER_INVITATION_ENABLED`, plus `PRACTITIONER_APP_URL` and a default practitioner AccessPolicy. | | Let practitioners register themselves | Setting `PRACTITIONER_REGISTRATION_ENABLED` = `true`, plus `DEFAULT_PRACTITIONER_ACCESS_POLICY`. | | Make emailed links open my app | Set `PATIENT_APP_URL` and/or `PRACTITIONER_APP_URL`. | | Invite clinicians who register with a work email | [`CLINICIAN_INVITE_ON_BUSINESS_EMAIL`](/settings-and-features/settings/clinician-invite-on-business-email), plus a default practitioner AccessPolicy and both app URLs. | | Customise the emails Ovok sends | [Email templates](/email-templates). | | Let patients share data | [`PATIENT_SHARING_ENABLED`](/settings-and-features/settings/patient-sharing-enabled) at `/v1/patient-sharing/settings`. | ## Reserved settings [`MAILING_ENABLED`](/settings-and-features/settings/mailing-enabled) and [`CONTENT_ENABLED`](/settings-and-features/settings/content-enabled) (which the Console sets when you enable the [CMS](/cms)) are accepted settings keys but do not control an active Ovok flow yet. Treat them as reserved; use the `email` feature to allow email sent from automations.