# Delete account
Source: https://docs.oviond.com/account/delete
Permanently delete your Oviond account and all its data.
Deleting your account is **permanent and irreversible**. It removes the entire workspace — every client, project, page, widget, data source, branding asset, and media file — and removes every team member from the account.
This is not a soft-delete and there's no Archive recovery for a deleted account. Deleting also cancels your active subscription. Every team member loses access the moment the account is deleted. Export anything you need to keep before you proceed.
## Before you delete
* **Export critical reports** — save a PDF of every report you want to retain.
* **Note your billing** — deletion cancels your active subscription. If you have billing questions, contact support first.
* **Tell your team** — every user in the account loses access immediately.
## How to delete
Go to **Settings → My account**.
At the bottom of the page, find the **Danger zone** and click **Delete account**.
In the confirmation dialog, type your account email address exactly to enable the button.
Confirm to delete the account. Oviond removes the account and all its data, then signs you out.
Deleting the account requires **Admin access**. The **Delete account** button appears for everyone, but only admins can complete the deletion — other users receive an error if they try.
# My account
Source: https://docs.oviond.com/account/overview
Manage your personal profile, password, usage, and account settings.
Your **My account** settings are personal to your login — every user manages their own, regardless of access level. To open them, go to **Settings → My account**.
## What you can manage
* [Profile](/account/profile) — your name, avatar, email, and interface language.
* [Password](/account/password) — how you sign in.
* [Usage](/account/usage) — your plan status and active-client usage.
* [Delete account](/account/delete) — permanently remove your account.
## Account-wide settings
Some settings apply to your whole workspace rather than your personal login, and require **Admin access**:
* **Company** — company name, contact details, timezone, default currency, and agency logos. See [Company details](/company/overview).
* **Users** — invite and manage team members. See [List users](/users/list).
* **Billing** — your plan, subscription, and invoices. See [Plans](/billing/plans).
# Password
Source: https://docs.oviond.com/account/password
Change or set the password you sign in with.
The **Password** section on **My account** lets you manage how you sign in. Go to **Settings → My account** to find it.
## Change your password
If you already have a password, use **Change password**: enter your **Current password**, then your **New password** and **Confirm new password**.
## Set a password
If you signed up without a password — for example, through a single sign-on provider — use **Set a password** to create one.
# Profile
Source: https://docs.oviond.com/account/profile
Update your own name, avatar, email, and language.
The **Profile** section on **My account** controls how you appear inside Oviond.
Go to **Settings → My account**.
Edit the **Full name** field. Your name appears in the Oviond interface and in activity-log entries.
Choose a photo from your Media Library. If you don't set one, Oviond shows your initials.
Use the **Language** selector to set your preferred interface language. This applies to your login only — it doesn't affect your teammates or how client-facing reports render.
Save to apply your updates.
Your **email address** is shown on this page but is read-only. To change the email you sign in with, contact support.
Your access level and assigned clients are managed by an admin, not from your own profile. See [Update a user](/users/update).
# Usage
Source: https://docs.oviond.com/account/usage
See what you've used against your plan's limits.
Your plan and usage appear on the **Billing** page. Go to **Settings → Billing** to see your current plan, status, and how much of your limits you've used.
## What's shown
| Item | Description |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------- |
| **Account status** | Your subscription status, shown as a badge (for example, active, trialing, or pending cancellation). |
| **Active clients** | The number of clients you've created against your plan's limit, shown as **used / limit**. Plans with no cap show **Unlimited**. |
The **Active clients** card shows an **Upgrade** badge when you're close to your limit. Archived and deleted clients don't count toward the total.
Your plan also defines a limit on the number of users on your account. Manage team members from **Settings → Users**.
To change your plan or limits, upgrade from **Settings → Billing**. See [Plans](/billing/plans) for what each plan includes, or [Subscription](/billing/subscription) to upgrade.
# Activity log
Source: https://docs.oviond.com/activity-log/overview
Audit meaningful actions taken in your account.
The **Activity log** records who did what and when across your account. Open it from **Settings → Activity log** (`/settings/activity-log`). Use it to:
* Trace when a client, project, or report was created, updated, or deleted
* See which team member changed a role or removed a user
* Correlate a change with a recent data source action
## What each entry shows
The table has a row per action with these columns:
| Column | Field | Description |
| ------------ | --------------- | ------------------------------------------------------------------------ |
| **User** | `user_id` | The team member who performed the action, with their name and email. |
| **Action** | `action` | What happened (for example `created`, `updated`, `deleted`, `restored`). |
| **Type** | `resource_type` | The kind of resource affected. |
| **Source** | `source` | Where the action came from — `app`, `api`, `mcp`, or `system`. |
| **Resource** | `resource_name` | The name of the affected item (falls back to `—`). |
| **Date** | `created_at` | When it happened, in your account timezone. |
Each record also stores `resource_id` and an optional `details` object internally.
## Filter and search
* **Search** by resource name or action.
* **Filter by type** — one resource type at a time: `client`, `project`, `media`, `automation`, `user`, `auth`, or `email`.
## Who can see what
Admins see the whole account's activity. Other members see only their own actions.
# Add API key
Source: https://docs.oviond.com/api-keys/add
Create an API key to authenticate REST API calls.
API keys let external scripts and integrations call the Oviond REST API on behalf of your account. You choose a permission level for each key when you create it, so a key can be scoped more tightly than your own account.
API keys authenticate the **REST API only**. The [MCP server](/mcp/overview) uses its own OAuth 2.1 flow with per-client tokens — it does **not** accept these API keys. See [MCP authentication](/mcp/auth).
API and MCP access is included with the agency plan. If your plan doesn't include API access, the create panel prompts you to upgrade in **Settings → Billing**.
## Create a key
Go to **Settings → API keys**.
Click **Create key** to open the create panel.
Enter a descriptive name — for example, `Reporting automation` — so you can identify what depends on it later.
Pick the access level for the key:
| Permission | What the key can do |
| ---------- | ----------------------------------------------------------------------------------------------------------------- |
| **View** | Read-only access. View clients, projects, and data, but can't make changes. |
| **Edit** | Read and write content. Create and edit clients, projects, and data — but not account settings, billing, or team. |
| **Full** | Full account access. Everything your own account can do, including account settings. |
Oviond shows the key **once**. Copy it immediately and store it somewhere safe — the key is hashed after this panel and can't be retrieved again. The panel also offers ready-made snippets for AI connectors that include the key.
## Use your key
Send the key as a Bearer token on every request:
```bash theme={null}
curl https://api.oviond.com/v1/users/me \
-H "Authorization: Bearer YOUR_API_KEY"
```
Every key starts with the `oviond_` prefix. See [Authentication](/authentication) for more on authenticating API requests.
The full key is only visible at creation. If you lose it, [revoke](/api-keys/revoke) the key and create a new one.
# Delete API key
Source: https://docs.oviond.com/api-keys/delete
Permanently remove a revoked API key from your list.
Deleting a key removes it entirely from your **API keys** list. You can only delete a key after it has been [revoked](/api-keys/revoke) — this prevents you from deleting a key that's still authenticating live requests.
Go to **Settings → API keys**.
If the key is still active, click **Revoke** and confirm. The **Delete** action only appears on revoked keys.
On the revoked key's row, click **Delete** and confirm.
Deletion is permanent. Once a key is deleted it's removed from your account and can't be recovered. If you only want to stop a key from working while keeping a record of it, [revoke](/api-keys/revoke) it instead.
# List API keys
Source: https://docs.oviond.com/api-keys/list
View and manage the API keys issued for your account.
API keys authenticate requests to the Oviond API from external tools, scripts, integrations, and AI connectors. Each key belongs to your account and operates at the permission level you chose when you created it.
Managing API keys requires admin or owner permissions.
## View your keys
Go to **Settings → API keys** to see every key on your account. Each row shows:
* **Name** and the key **prefix** (the first characters of the key — the full value is never shown again)
* **Status** — `Active` or `Revoked`
* **Permission** — `View`, `Edit`, or `Full`
* **Created** date
* **Last used** — when the key last authenticated a request, or `Never`
## Manage keys
From the list you can:
* **Create key** — generate a new key. See [Add API key](/api-keys/add).
* **Revoke** an active key — immediately stops it from authenticating requests. See [Revoke API key](/api-keys/revoke).
* **Delete** a revoked key — permanently removes it from your account. See [Delete API key](/api-keys/delete).
The row action changes with the key's status: active keys offer **Revoke**, and revoked keys offer **Delete**. A key must be revoked before it can be deleted.
Revoking is immediate. Update any tools or scripts that use a key before you revoke it to avoid downtime.
## Security best practices
* Give each key a descriptive name so you can identify and revoke individual integrations.
* Use the lowest permission a tool needs — choose **View** or **Edit** instead of **Full** where possible.
* Never commit API keys to version control.
* Use one key per integration so you can revoke a single key without affecting others.
* Rotate keys periodically, or immediately if you suspect a key has been exposed.
# Revoke API key
Source: https://docs.oviond.com/api-keys/revoke
Immediately disable an API key while keeping it in your list.
Revoking a key stops it from authenticating requests — every future call returns `401 Unauthorized`. The key stays in your **API keys** list with a `Revoked` status, so you keep a record of it and can permanently delete it later.
Revoke a key when:
* The key was accidentally shared or committed to a public repository
* A team member leaves and their key should stop working
* An integration is being decommissioned
Go to **Settings → API keys**.
On the key's row, click **Revoke**.
Confirm in the dialog. The key's status changes to `Revoked` immediately.
## Revoked vs deleted
| State | Still in list? | Can authenticate? | Reversible? |
| ----------- | -------------- | ----------------- | --------------------- |
| **Revoked** | Yes | No | No — create a new key |
| **Deleted** | No | No | No |
Revoking is the first step. To remove a revoked key from the list entirely, see [Delete API key](/api-keys/delete) — a key must be revoked before it can be deleted.
# Delete Account
Source: https://docs.oviond.com/api/account/delete-account
https://api.oviond.com/openapi.json delete /v1/account
Irreversible. Cancels the active Stripe subscription, deletes all data across every table for this account, removes all team members from the users table, purges all S3 media files, and deletes all Supabase Auth users. Requires the account owner's email address in the `confirm_email` field as a confirmation gate (case-insensitive match against the authenticated user's email).
# Get Account
Source: https://docs.oviond.com/api/account/get-account
https://api.oviond.com/openapi.json get /v1/account
Get the accounts row for the current account
# Get Account Usage
Source: https://docs.oviond.com/api/account/get-account-usage
https://api.oviond.com/openapi.json get /v1/account/usage
Get account usage statistics vs plan limits
# List Activity
Source: https://docs.oviond.com/api/activity/list-activity
https://api.oviond.com/openapi.json get /v1/activity
List activity logs for the current account
# Delete Permanently
Source: https://docs.oviond.com/api/archive/delete-permanently
https://api.oviond.com/openapi.json delete /v1/archive/permanent
Permanently delete archived items
# Get Archive Counts
Source: https://docs.oviond.com/api/archive/get-archive-counts
https://api.oviond.com/openapi.json get /v1/archive/counts
Archived item counts per type
# List Archive
Source: https://docs.oviond.com/api/archive/list-archive
https://api.oviond.com/openapi.json get /v1/archive
List archived items (paginated)
# Restore Items
Source: https://docs.oviond.com/api/archive/restore-items
https://api.oviond.com/openapi.json put /v1/archive/restore
Restore soft-deleted items
# Add Asset To Page
Source: https://docs.oviond.com/api/assets/add-asset-to-page
https://api.oviond.com/openapi.json post /v1/assets/{id}/add-to-page
Instantiate an asset's widgets onto a project page (connectivity-aware: unconnected sources land as demo).
# Archive Asset
Source: https://docs.oviond.com/api/assets/archive-asset
https://api.oviond.com/openapi.json delete /v1/assets/{id}
Archive an asset. Recoverable from the archive.
# Create Asset
Source: https://docs.oviond.com/api/assets/create-asset
https://api.oviond.com/openapi.json post /v1/assets
Create a new asset
# Delete Asset Tag
Source: https://docs.oviond.com/api/assets/delete-asset-tag
https://api.oviond.com/openapi.json delete /v1/assets/tags/{tag}
Remove a tag from every asset in the current account (does not touch the shared standard library)
# Duplicate Asset
Source: https://docs.oviond.com/api/assets/duplicate-asset
https://api.oviond.com/openapi.json post /v1/assets/{id}/duplicate
Duplicate an asset with a new name
# Get Asset
Source: https://docs.oviond.com/api/assets/get-asset
https://api.oviond.com/openapi.json get /v1/assets/{id}
Get a single asset by ID
# List Asset Tags
Source: https://docs.oviond.com/api/assets/list-asset-tags
https://api.oviond.com/openapi.json get /v1/assets/tags
List all unique tags across assets for the current account
# List Asset Widgets
Source: https://docs.oviond.com/api/assets/list-asset-widgets
https://api.oviond.com/openapi.json get /v1/assets/{id}/widgets
List the widgets that belong to an asset
# List Assets
Source: https://docs.oviond.com/api/assets/list-assets
https://api.oviond.com/openapi.json get /v1/assets
List assets for the current account
# Update Asset
Source: https://docs.oviond.com/api/assets/update-asset
https://api.oviond.com/openapi.json put /v1/assets/{id}
Update an asset
# Archive Automation
Source: https://docs.oviond.com/api/automations/archive-automation
https://api.oviond.com/openapi.json delete /v1/automations/{id}
Archive an automation and remove it from the cron scheduler. Recoverable from the archive.
# Archive Multiple Automations
Source: https://docs.oviond.com/api/automations/archive-multiple-automations
https://api.oviond.com/openapi.json delete /v1/automations/bulk
Archive multiple automations and remove them from the cron scheduler. Recoverable from the archive.
# Create Automation
Source: https://docs.oviond.com/api/automations/create-automation
https://api.oviond.com/openapi.json post /v1/automations
Create a new automation for a project
# Get Automation History
Source: https://docs.oviond.com/api/automations/get-automation-history
https://api.oviond.com/openapi.json get /v1/automations/{project_id}/history
Get execution history across every automation for a project
# List Automations
Source: https://docs.oviond.com/api/automations/list-automations
https://api.oviond.com/openapi.json get /v1/automations
List automations across all projects for the current account
# Pause Automation
Source: https://docs.oviond.com/api/automations/pause-automation
https://api.oviond.com/openapi.json put /v1/automations/{id}/pause
Pause an automation (removes the cron job but retains the config)
# Test Automation
Source: https://docs.oviond.com/api/automations/test-automation
https://api.oviond.com/openapi.json post /v1/automations/{id}/test
Trigger a test execution of an automation
# Unpause Automation
Source: https://docs.oviond.com/api/automations/unpause-automation
https://api.oviond.com/openapi.json put /v1/automations/{id}/unpause
Resume a paused automation (re-registers the cron job)
# Update Automation
Source: https://docs.oviond.com/api/automations/update-automation
https://api.oviond.com/openapi.json put /v1/automations/{id}
Update automation schedule and notification settings
# Get Billing
Source: https://docs.oviond.com/api/billing/get-billing
https://api.oviond.com/openapi.json get /v1/billing
Get the billing row for the current account
# List Invoices
Source: https://docs.oviond.com/api/billing/list-invoices
https://api.oviond.com/openapi.json get /v1/billing/invoices
List Stripe invoices for a customer
# List Plans
Source: https://docs.oviond.com/api/billing/list-plans
https://api.oviond.com/openapi.json get /v1/billing/plans
List available subscription plans from Stripe
# Get Branding
Source: https://docs.oviond.com/api/branding/get-branding
https://api.oviond.com/openapi.json get /v1/branding
Get branding settings
# Refresh Favicon
Source: https://docs.oviond.com/api/branding/refresh-favicon
https://api.oviond.com/openapi.json post /v1/branding/favicon/refresh
Re-derive the account favicon from its stored website, cache-bust it, save it and return the new URL. Requires a website on the account.
# Update Branding
Source: https://docs.oviond.com/api/branding/update-branding
https://api.oviond.com/openapi.json put /v1/branding
Update branding settings
# Archive Calculated Metric
Source: https://docs.oviond.com/api/calculated-metrics/archive-calculated-metric
https://api.oviond.com/openapi.json delete /v1/calculated-metrics/{id}
Archive a calculated metric. Recoverable from the archive.
# Create Calculated Metric
Source: https://docs.oviond.com/api/calculated-metrics/create-calculated-metric
https://api.oviond.com/openapi.json post /v1/calculated-metrics
Create a new calculated metric
# Duplicate Calculated Metric
Source: https://docs.oviond.com/api/calculated-metrics/duplicate-calculated-metric
https://api.oviond.com/openapi.json post /v1/calculated-metrics/{id}/duplicate
Duplicate a calculated metric
# List Calculated Metrics
Source: https://docs.oviond.com/api/calculated-metrics/list-calculated-metrics
https://api.oviond.com/openapi.json get /v1/calculated-metrics
List all calculated metrics for the current account
# Update Calculated Metric
Source: https://docs.oviond.com/api/calculated-metrics/update-calculated-metric
https://api.oviond.com/openapi.json put /v1/calculated-metrics/{id}
Update a calculated metric
# Archive Client
Source: https://docs.oviond.com/api/clients/archive-client
https://api.oviond.com/openapi.json delete /v1/clients/{id}
Archive a client and all its associated projects and widgets. Recoverable from the archive.
# Archive Multiple Clients
Source: https://docs.oviond.com/api/clients/archive-multiple-clients
https://api.oviond.com/openapi.json delete /v1/clients/bulk
Archive multiple clients by ID, each with its projects and their widgets. Recoverable from the archive.
# Bulk Update Clients
Source: https://docs.oviond.com/api/clients/bulk-update-clients
https://api.oviond.com/openapi.json patch /v1/clients/bulk
Apply the same partial patch to many clients in one call.
# Count Clients
Source: https://docs.oviond.com/api/clients/count-clients
https://api.oviond.com/openapi.json get /v1/clients/count
Count total clients for the current account
# Create Client
Source: https://docs.oviond.com/api/clients/create-client
https://api.oviond.com/openapi.json post /v1/clients
Create a new client
# Get Client
Source: https://docs.oviond.com/api/clients/get-client
https://api.oviond.com/openapi.json get /v1/clients/{id}
Get a single client by ID
# List All Clients
Source: https://docs.oviond.com/api/clients/list-all-clients
https://api.oviond.com/openapi.json get /v1/clients/all
List all clients with optional field selection
# List Client Datasources
Source: https://docs.oviond.com/api/clients/list-client-datasources
https://api.oviond.com/openapi.json get /v1/clients/{id}/datasources
List datasources connected to a client
# List Clients
Source: https://docs.oviond.com/api/clients/list-clients
https://api.oviond.com/openapi.json get /v1/clients
List clients for the current account
# Move Client Folder
Source: https://docs.oviond.com/api/clients/move-client-folder
https://api.oviond.com/openapi.json put /v1/clients/{id}/folder
Move a client to one or more folders
# Refresh Favicon
Source: https://docs.oviond.com/api/clients/refresh-favicon
https://api.oviond.com/openapi.json post /v1/clients/{id}/favicon/refresh
Re-derives the square favicon from the client's stored website (Google favicon service), cache-busts it so the browser re-pulls the latest image, saves it, and returns the new URL. Use this for user-triggered refresh on the client branding panel.
# Refresh Screenshot
Source: https://docs.oviond.com/api/clients/refresh-screenshot
https://api.oviond.com/openapi.json post /v1/clients/{id}/screenshot/refresh
Re-fetches the screenshot synchronously using the client's stored website and returns the new URL. Use this for user-triggered refresh on the dashboard card.
# Set Projects Sort
Source: https://docs.oviond.com/api/clients/set-projects-sort
https://api.oviond.com/openapi.json put /v1/clients/{id}/projects-sort
Save the default sort for this client's Projects list.
# Update Client
Source: https://docs.oviond.com/api/clients/update-client
https://api.oviond.com/openapi.json put /v1/clients/{id}
Update a client
# Get Company
Source: https://docs.oviond.com/api/company/get-company
https://api.oviond.com/openapi.json get /v1/company
Get company settings for the current account
# Update Company
Source: https://docs.oviond.com/api/company/update-company
https://api.oviond.com/openapi.json put /v1/company
Update company settings
# Errors & request IDs
Source: https://docs.oviond.com/api/concepts/errors
Every Oviond API response uses one consistent JSON envelope. Learn the error shape, the status codes, and how to use request IDs when contacting support.
Every Oviond API response — success or failure — uses the same JSON envelope, so your client can parse one shape everywhere. All fields are `snake_case`.
## Success envelope
```json theme={null}
{
"success": true,
"data": { "...": "..." },
"meta": { "request_id": "req_a1b2c3" }
}
```
List endpoints add pagination fields to `meta`. See [Pagination, filtering & sorting](/api/concepts/pagination).
## Error envelope
```json theme={null}
{
"success": false,
"error": {
"message": "Client not found",
"status_code": 404
},
"meta": { "request_id": "req_a1b2c3" }
}
```
Every error returns this shape with the matching HTTP status — including `401` and `403`. There are no plain-text error bodies.
### Validation errors
`400` and `422` responses add a `details` object with per-field messages, so you can surface exactly which field failed:
```json theme={null}
{
"success": false,
"error": {
"message": "Validation error",
"status_code": 422,
"details": [
{ "path": ["name"], "message": "Required" }
]
},
"meta": { "request_id": "req_a1b2c3" }
}
```
## Status codes
| Code | Meaning |
| ----- | ------------------------------------------------------------------------------ |
| `200` | Success |
| `201` | Created |
| `204` | No content (successful delete) |
| `400` | Bad request — malformed body or parameters |
| `401` | Unauthorized — missing, malformed, invalid, or revoked credential |
| `403` | Forbidden — valid credential without permission, or your plan lacks API access |
| `404` | Not found — the resource doesn't exist, or isn't in your account |
| `422` | Validation error — see `error.details` |
| `429` | Too many requests — see [Rate limits & retries](/api/concepts/rate-limits) |
| `500` | Server error — safe to retry with backoff |
A `404` is also returned when a resource exists but belongs to a different account — Oviond never reveals whether an ID exists outside your tenant.
## Request IDs
Every response includes an `X-Request-Id` header, and every error repeats it as `meta.request_id`. If you send your own `X-Request-Id`, Oviond preserves it so you can correlate requests across your systems and ours.
```bash theme={null}
curl -i https://api.oviond.com/v1/users/me \
-H "Authorization: Bearer YOUR_API_KEY"
# ...
# X-Request-Id: req_a1b2c3
```
When something looks wrong, capture the `request_id` and include it when you contact support — it lets us find the exact request in our logs.
# Pagination, filtering & sorting
Source: https://docs.oviond.com/api/concepts/pagination
How Oviond list endpoints page, filter, and sort results — page/limit parameters, the meta totals, search, and sort order.
List endpoints (for example `GET /v1/clients`, `GET /v1/projects`) return a page of results plus a `meta` block describing the full set.
## Pagination
Control the page with two query parameters:
| Parameter | Type | Default | Notes |
| --------- | ------- | ------- | --------------------------------------- |
| `page` | integer | `0` | **Zero-based** — the first page is `0`. |
| `limit` | integer | `20` | Items per page, `1`–`100`. |
The response repeats these in `meta` along with the total count:
```bash theme={null}
curl "https://api.oviond.com/v1/clients?page=0&limit=20" \
-H "Authorization: Bearer YOUR_API_KEY"
```
```json theme={null}
{
"success": true,
"data": [ { "id": "...", "name": "Acme" } ],
"meta": { "page": 0, "limit": 20, "total": 137 }
}
```
To walk every page, request `page=0`, `page=1`, … until `page * limit >= total`.
Some endpoints expose an unpaginated `/all` variant (for example `GET /v1/clients/all`) that returns a lightweight `{ id, name }[]` of every record — handy for populating dropdowns without paging.
## Filtering
Most list endpoints accept a free-text `search` parameter plus resource-specific filters. Common examples:
| Parameter | Example endpoint | Purpose |
| ----------- | --------------------------------- | ------------------------------------------- |
| `search` | `GET /v1/clients?search=acme` | Free-text match on name and related fields. |
| `client_id` | `GET /v1/projects?client_id=...` | Scope results to one client. |
| `folder_id` | `GET /v1/clients?folder_id=...` | Scope clients to a folder. |
| `type` | `GET /v1/projects?type=DASHBOARD` | Filter by resource type. |
Filters combine with `AND`. The exact set differs per endpoint — check each endpoint's **Query Parameters** in the [API reference](/api/introduction).
## Sorting
Where sorting is supported, use:
| Parameter | Default | Notes |
| --------- | ------------ | ------------------ |
| `sort_by` | `updated_at` | Column to sort by. |
| `order` | `desc` | `asc` or `desc`. |
```bash theme={null}
curl "https://api.oviond.com/v1/clients?sort_by=name&order=asc" \
-H "Authorization: Bearer YOUR_API_KEY"
```
# Querying data
Source: https://docs.oviond.com/api/concepts/querying-data
Use POST /v1/data/query to pull live metric values from a client's connected data sources — the endpoint behind Oviond's charts and KPIs.
`POST /v1/data/query` returns live metric values from one of a client's **connected** data sources. It's the same call that powers every chart and KPI widget in the app, exposed for your own automations.
This endpoint proxies to Oviond's datasource service. It reads a data source the client has already connected in the app — it does not create or authorize connections. Connect a source in the [project editor](/data-sources/connect) first.
## Request
```bash theme={null}
curl -X POST https://api.oviond.com/v1/data/query \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"datasource_id": "ga4",
"client_id": "cliAbc123",
"date_range": { "current_start": "2026-03-01", "current_end": "2026-03-31" },
"metrics": ["sessions", "conversions"],
"dimensions": ["DATE"],
"data_view": "OVERVIEW"
}'
```
| Field | Required | Description |
| --------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `datasource_id` | ✓ | The datasource alias, e.g. `ga4`, `gadw`, `fb-ads`. **List all with [`GET /v1/datasources`](#finding-valid-identifiers).** |
| `client_id` | ✓ | The client whose connected data source you're querying. List with `GET /v1/clients`. |
| `date_range` | ✓ | `{ current_start, current_end }` as `YYYY-MM-DD`. Add `previous_start` / `previous_end` to get period-over-period comparison values. |
| `metrics` | ✓ | Array of metric `id`s, e.g. `["clicks", "impressions"]`. **Get valid ids from [`GET /v1/datasources/{datasource_id}/describe`](#finding-valid-identifiers).** |
| `dimensions` | ✓ | Array of dimension `id`s, e.g. `["DATE"]` for a time series, or `[]` for a single total. **Get valid ids from [`GET /v1/datasources/{datasource_id}/describe`](#finding-valid-identifiers).** |
| `data_view` | ✓ | The datasource view, e.g. `ACCOUNT`. A metric or dimension is only valid inside its own view — `/describe` groups them by view. |
| `filters` | | Array of `{ field, operator, value }` filter objects. `operator` is one of `equals`, `not_equals`, `contains`, `not_contains`, `starts_with`, `ends_with`, `greater_than`, `less_than`, `greater_than_or_equal`, `less_than_or_equal`. Add `"logicalOperator": "and"` (or `"or"`) to combine multiple filters. |
| `timezone` | | IANA timezone for date bucketing. Defaults to `UTC`. |
## Response
```json theme={null}
{
"success": true,
"data": {
"current": [
{ "DATE": "2026-03-01", "sessions": 1240, "conversions": 18 },
{ "DATE": "2026-03-02", "sessions": 1310, "conversions": 22 }
],
"currentSummary": { "sessions": 39120, "conversions": 604 },
"previous": [],
"previousSummary": {},
"state": "ACTIVE"
},
"meta": { "request_id": "req_a1b2c3" }
}
```
* `data.current` — the rows for the current range (one per `dimensions` bucket, keyed by your metric and dimension identifiers).
* `data.currentSummary` — the totals across the current range.
* `data.previous` / `data.previousSummary` — the same for the comparison period, when you pass `previous_start` / `previous_end` (empty otherwise).
* `data.state` — `ACTIVE` when the connection returned data.
Read fields by the identifiers you requested rather than by position; the exact keys vary by datasource and `data_view`.
## Finding valid identifiers
The valid `datasource_id`, `metrics`, `dimensions`, and `data_view` values are all discoverable — you never have to guess. Walk the **field catalog**:
**1. Find the `datasource_id`** — list every datasource Oviond supports:
```bash theme={null}
curl "https://api.oviond.com/v1/datasources" \
-H "Authorization: Bearer YOUR_API_KEY"
# → [{ "id": "gadw", "name": "Google Ads", "category": "...", "data_views": [...] }, ...]
```
**2. Describe it** — one call returns its data views and every field you can query:
```bash theme={null}
curl "https://api.oviond.com/v1/datasources/gadw/describe" \
-H "Authorization: Bearer YOUR_API_KEY"
```
```json theme={null}
{
"success": true,
"data": {
"datasource_id": "gadw",
"default_data_view": "ACCOUNT",
"data_views": [
{ "value": "ACCOUNT", "label": "Account", "required_advanced": [] },
{ "value": "CAMPAIGNS", "label": "Campaigns", "required_advanced": [] }
],
"metrics": [
{ "id": "impressions", "name": "Impressions", "data_view": "ACCOUNT", "group": "Basic" },
{ "id": "clicks", "name": "Clicks", "data_view": "ACCOUNT", "group": "Basic" }
],
"dimensions": [
{ "id": "DATE", "name": "Date", "data_view": "TIME", "group": "Time" }
]
}
}
```
Use each `id` as an entry in `metrics` / `dimensions`, and its `data_view` as `data_view`. Add `?data_view=ACCOUNT` to scope the response to one view.
Three things in the response decide what you can combine:
* **`data_view`** — a metric or dimension is only valid inside its own view. Mixing views in one query is rejected.
* **`required_advanced`** — advanced settings the view can't run without (a Semrush region, a Mailchimp audience). Each entry names the `advanced` key and the message shown when it's missing.
* **Field flags** — `single` (must be the only dimension), `deprecated` (retired by the vendor; still resolves, may return nothing) and `custom` (a per-account definition, not part of the static catalog).
Other helpful endpoints:
* **`GET /v1/clients/{id}/datasources`** — which sources a specific client has connected.
* **`POST /v1/data/resource`** — selectable sub-resource values (campaigns, ad sets, videos) for filters.
* **`POST /v1/datasources/accounts`** — the accounts, properties or pages a connection can be linked to.
Over MCP the same catalog is two tools — `datasources` → `describe_datasource`, which returns a datasource's data views with their metrics, dimensions and required settings in one call. Agents call them in that order, no guessing. Live values are read by configuring a saved widget (`add_data_widget`) and refreshing it, not by querying ad hoc.
## Common errors
| Status | Cause | What to do |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `422` | Missing/invalid field — no `metrics`, or an unknown `datasource_id`, `metric`, or `dimension` for that datasource. Identifiers are validated against the field catalog before the query runs, so a typo is rejected here rather than failing upstream. | Check the request against the table above and the [field catalog](#finding-valid-identifiers); details are in `error.details`. |
| `404` | `client_id` doesn't exist in your account. | Verify the ID via `GET /v1/clients`. |
| `502` | Upstream datasource error — not connected or an expired OAuth token. | Run [`POST /v1/datasources/test`](/api/introduction) with the connection's `auth_id` (from `GET /v1/datasources/auths`) to check it; if the token expired, reconnect the source in the app. |
A `502` most often means the client's OAuth token for that datasource has expired and needs reconnecting in the app — it's not a bug in your request.
# Rate limits & retries
Source: https://docs.oviond.com/api/concepts/rate-limits
Oviond rate-limits programmatic API and MCP traffic per account. Learn the limits, the X-RateLimit headers, the 429 response, and how to retry safely.
Oviond rate-limits **programmatic** traffic to protect the platform. This applies to:
* **REST API** calls authenticated with an [API key](/authentication), and
* **[MCP](/mcp/overview)** agent calls.
The Oviond web app (which signs in with a session token) is **never** rate-limited — so your own dashboards and the product UI are unaffected.
## The limits
* **Per account, per surface.** Your REST API budget and your MCP budget are counted **separately** — heavy agent traffic can't starve your direct API usage, and vice-versa.
* **Per minute.** Limits are enforced in a fixed 60-second window.
* **Default: 300 requests per minute** per account for each surface. Your account's actual ceiling is always returned in the `X-RateLimit-Limit` header — read it rather than hard-coding a number.
## Rate-limit headers
Every programmatic response carries your current budget:
| Header | Meaning |
| ----------------------- | ------------------------------------------- |
| `X-RateLimit-Limit` | Requests allowed in the window. |
| `X-RateLimit-Remaining` | Requests left in the current window. |
| `X-RateLimit-Reset` | Unix time (seconds) when the window resets. |
## When you're limited
Exceeding the budget returns `429 Too Many Requests` in the standard [error envelope](/api/concepts/errors), with a `Retry-After` header (seconds to wait):
```json theme={null}
{
"success": false,
"error": {
"message": "Rate limit exceeded. Please retry after some time.",
"status_code": 429
},
"meta": { "request_id": "req_a1b2c3" }
}
```
## Retrying safely
* **Honor `Retry-After`.** On a `429`, wait the number of seconds it specifies before retrying.
* **Back off exponentially** on repeated `429` or `5xx` responses (for example 1s, 2s, 4s, with jitter).
* **`GET` requests are always safe to retry** — they don't change state.
* **Writes are not idempotent.** Oviond does not support idempotency keys, so a `POST`/`PUT`/`DELETE` that timed out may or may not have applied. Before blindly retrying a write, re-fetch the resource (or list) to check whether the first attempt succeeded, to avoid creating duplicates.
* **Stay under the limit proactively** by watching `X-RateLimit-Remaining` and pacing bulk jobs, rather than sprinting into a `429`.
# Sandbox
Source: https://docs.oviond.com/api/concepts/sandbox
Try the Oviond API against a shared, read-only demo account — no signup — before wiring in your own key.
The sandbox lets you make real API calls against a demo account with live data connected, so you can see actual responses before building against your own account. It's **read-only**: you can list and query, but not create or change anything.
The key below is a shared **read-only** sandbox key — safe to use publicly. Write calls (`POST`/`PUT`/`DELETE`) return `403`. For write access, use a key from your own account (see [Authentication](/authentication)).
## Set up
```bash theme={null}
export OVIOND_SANDBOX_KEY="oviond_276f473c1ea416ec1d6ab186f628e04748195705c77492d798b7b0c10736610f"
export OVIOND_BASE="https://api.oviond.com"
```
The sandbox account has one demo client with Google Ads, Google Analytics 4, and Facebook Ads connected:
| Value | |
| -------------------------- | ----------------------- |
| `client_id` | `OGlOKfzHdJTpJouhD` |
| Connected `datasource_id`s | `gadw`, `ga4`, `fb-ads` |
## List the demo client
```bash theme={null}
curl "$OVIOND_BASE/v1/clients" \
-H "Authorization: Bearer $OVIOND_SANDBOX_KEY"
```
## Query live data
Pull real Google Ads numbers for the demo client:
```bash theme={null}
curl -X POST "$OVIOND_BASE/v1/data/query" \
-H "Authorization: Bearer $OVIOND_SANDBOX_KEY" \
-H "Content-Type: application/json" \
-d '{
"datasource_id": "gadw",
"client_id": "OGlOKfzHdJTpJouhD",
"date_range": { "current_start": "2026-06-07", "current_end": "2026-07-06" },
"metrics": ["impressions", "clicks", "ctr"],
"dimensions": ["DATE"],
"data_view": "ACCOUNT"
}'
```
You'll get back the [data-query response shape](/api/concepts/querying-data) — `data.current` rows plus `data.currentSummary` totals — with real values.
## What you can't do here
The sandbox key is read-only, so `POST`/`PUT`/`DELETE` calls return `403`. To try the full create → connect → build flow, use your own account and follow the [Quickstart](/api/quickstart).
# OpenAPI, Postman & environment
Source: https://docs.oviond.com/api/concepts/tools
Download the Oviond OpenAPI spec, import it into Postman, Bruno, or Insomnia, and set up your environment variables.
The Oviond API publishes a machine-readable OpenAPI 3.1 spec you can import into any API client or code generator.
## Download the spec
```
https://api.oviond.com/openapi.json
```
It's always current — the spec is generated from the live API on every release, so it never drifts from the running service.
## Import into an API client
Every operation in the spec has a stable `operationId`, so imports produce clean, named requests.
**Import → Link**, paste `https://api.oviond.com/openapi.json`, and Postman generates a collection with a folder per tag. Then create an environment (below) so `{{base_url}}` and `{{api_key}}` resolve.
**Import Collection → OpenAPI V3**, point it at the downloaded `openapi.json`. Bruno creates a `.bru` request per operation.
**Import → From URL**, paste the spec URL. Insomnia builds a request collection you can run immediately.
## Environment variables
Set these once in your client's environment (or your shell) and reuse them everywhere:
| Variable | Value | Notes |
| ---------- | ------------------------ | ---------------------------------------------------------------------------- |
| `base_url` | `https://api.oviond.com` | Always pin the `/v1` version in the path. |
| `api_key` | `oviond_...` | Your [API key](/authentication). Store it as a **secret** — never commit it. |
Then send the key as a Bearer token on every request:
```
Authorization: Bearer {{api_key}}
```
Treat your API key like a password. Use your client's secret/vault storage, and never paste it into a shared collection or version control.
## SDKs
There is no official published SDK yet. Because the spec carries stable `operationId`s and typed schemas, you can generate a client in the meantime with a tool like [openapi-generator](https://openapi-generator.tech/) or [openapi-typescript](https://github.com/openapi-ts/openapi-typescript):
```bash theme={null}
npx openapi-typescript https://api.oviond.com/openapi.json -o oviond.d.ts
```
Generated clients are community-supported until official SDKs ship.
# Versioning & stability
Source: https://docs.oviond.com/api/concepts/versioning
How Oviond versions its REST API, what counts as a breaking change, and how to build integrations that keep working.
The Oviond REST API is versioned in the URL path. Every endpoint today lives under `/v1`:
```
https://api.oviond.com/v1/...
```
## What we may change without a new version
These are **additive** and can ship at any time — build your integration to tolerate them:
* New endpoints.
* New **optional** request fields.
* New fields in a response object.
* New values in an enum where the field is already documented as extensible.
Parse responses **tolerantly** — ignore fields you don't recognize, and don't fail on new properties. A strict client that rejects unknown fields will break on additive changes.
## What counts as a breaking change
Breaking changes ship under a **new version prefix** (for example a future `/v2`), and `/v1` continues to work during any migration window:
* Removing or renaming an endpoint, field, or enum value.
* Making a previously optional request field required.
* Changing a field's type or the shape of the response envelope.
* Changing authentication or default behavior in a way that rejects previously valid requests.
## Staying current
* Follow the [Changelog](/changelog/2026-06) for additive changes and deprecations.
* Field names are always `snake_case`; timestamps are ISO 8601.
* Pin your integration to `/v1` explicitly — never depend on an unversioned base URL.
# Archive Custom Data
Source: https://docs.oviond.com/api/custom-data/archive-custom-data
https://api.oviond.com/openapi.json delete /v1/custom-data/{id}
Archive a custom dataset. Recoverable from the archive.
# Create Custom Data
Source: https://docs.oviond.com/api/custom-data/create-custom-data
https://api.oviond.com/openapi.json post /v1/custom-data
Create a new custom dataset (max 10,000 rows)
# Duplicate Custom Data
Source: https://docs.oviond.com/api/custom-data/duplicate-custom-data
https://api.oviond.com/openapi.json post /v1/custom-data/{id}/duplicate
Duplicate a custom dataset
# Get Custom Data
Source: https://docs.oviond.com/api/custom-data/get-custom-data
https://api.oviond.com/openapi.json get /v1/custom-data/{id}
Get a single custom dataset by ID (includes raw_data)
# List Custom Data
Source: https://docs.oviond.com/api/custom-data/list-custom-data
https://api.oviond.com/openapi.json get /v1/custom-data
List custom datasets for the current account (no raw_data)
# Update Custom Data
Source: https://docs.oviond.com/api/custom-data/update-custom-data
https://api.oviond.com/openapi.json put /v1/custom-data/{id}
Update a custom dataset
# Add Domain
Source: https://docs.oviond.com/api/custom-domains/add-domain
https://api.oviond.com/openapi.json post /v1/custom-domains
Add a custom domain. Detects the DNS provider and registers the domain on Vercel.
# Check Domain Status
Source: https://docs.oviond.com/api/custom-domains/check-domain-status
https://api.oviond.com/openapi.json get /v1/custom-domains/{domain_id}/status
Check domain verification status via Vercel.
# Delete Domain
Source: https://docs.oviond.com/api/custom-domains/delete-domain
https://api.oviond.com/openapi.json delete /v1/custom-domains/{domain_id}
Remove a custom domain.
# List Domains
Source: https://docs.oviond.com/api/custom-domains/list-domains
https://api.oviond.com/openapi.json get /v1/custom-domains
List custom domains for the current account.
# Set Default Domain
Source: https://docs.oviond.com/api/custom-domains/set-default-domain
https://api.oviond.com/openapi.json post /v1/custom-domains/{domain_id}/default
Mark a custom domain as the account default for shared URLs (when a client has no domain override), or clear the default. Only an active domain can be set.
# Query Data
Source: https://docs.oviond.com/api/data/query-data
https://api.oviond.com/openapi.json post /v1/data/query
Proxy a datasource data query to data.oviond.com
# Delete Connection
Source: https://docs.oviond.com/api/datasources/delete-connection
https://api.oviond.com/openapi.json delete /v1/datasources/auths/{id}
Delete a data source auth entry
# Delete Profile
Source: https://docs.oviond.com/api/datasources/delete-profile
https://api.oviond.com/openapi.json delete /v1/datasources/{datasource_id}/profiles/{profile_name}
Delete an auth connection
# Describe Datasource
Source: https://docs.oviond.com/api/datasources/describe-datasource
https://api.oviond.com/openapi.json get /v1/datasources/{datasource_id}/describe
Describe one datasource the way the report builder sees it: its data views (with the `advanced` keys each view requires), its default view and defaults, and its metric and dimension catalogs carrying the flags that decide what can be combined (`single` — must be the only dimension; `requires_metric` — only offered once that metric is picked; `deprecated`; `custom`). A metric or dimension is only valid inside its own `data_view`. Pass `data_view` to scope the response to one view.
# List All Profiles
Source: https://docs.oviond.com/api/datasources/list-all-profiles
https://api.oviond.com/openapi.json get /v1/datasources/profiles
List all auth profiles for every data source
# List Connected Datasources
Source: https://docs.oviond.com/api/datasources/list-connected-datasources
https://api.oviond.com/openapi.json get /v1/datasources/auths
List all OAuth data sources stored for the current account
# List Datasource Accounts
Source: https://docs.oviond.com/api/datasources/list-datasource-accounts
https://api.oviond.com/openapi.json post /v1/datasources/accounts
Proxy a datasource accounts listing to data.oviond.com
# List Datasource Profiles
Source: https://docs.oviond.com/api/datasources/list-datasource-profiles
https://api.oviond.com/openapi.json get /v1/datasources/{datasource_id}/profiles
List auth profiles for a specific data source
# List Supported Datasources
Source: https://docs.oviond.com/api/datasources/list-supported-datasources
https://api.oviond.com/openapi.json get /v1/datasources
List every datasource Oviond supports, each with its `id` (the `datasource_id` you pass to the data endpoints), name, category, and available data views. Start here to find the `datasource_id`, then call `/{datasource_id}/describe` for its fields.
# Rename Connection
Source: https://docs.oviond.com/api/datasources/rename-connection
https://api.oviond.com/openapi.json put /v1/datasources/auths/{id}/name
Rename a data source auth entry
# Rename Profile
Source: https://docs.oviond.com/api/datasources/rename-profile
https://api.oviond.com/openapi.json put /v1/datasources/{datasource_id}/profiles/{profile_name}/rename
Rename an auth connection
# Test Stored Connection
Source: https://docs.oviond.com/api/datasources/test-stored-connection
https://api.oviond.com/openapi.json post /v1/datasources/test
Test whether a stored auth connection is valid
# Unlink Datasource
Source: https://docs.oviond.com/api/datasources/unlink-datasource
https://api.oviond.com/openapi.json post /v1/datasources/{client_id}/unlink
Unlink a datasource from a client
# Add Email Domain
Source: https://docs.oviond.com/api/email/add-email-domain
https://api.oviond.com/openapi.json post /v1/email/domain
Register a sending domain with Resend.
# Create Email Template
Source: https://docs.oviond.com/api/email/create-email-template
https://api.oviond.com/openapi.json post /v1/email/templates
# Create Sender
Source: https://docs.oviond.com/api/email/create-sender
https://api.oviond.com/openapi.json post /v1/email/senders
Add a sender tied to either the verified domain or the SMTP config.
# Delete Email Domain
Source: https://docs.oviond.com/api/email/delete-email-domain
https://api.oviond.com/openapi.json delete /v1/email/domain/{id}
Remove the domain from Resend and the account.
# Delete Email Template
Source: https://docs.oviond.com/api/email/delete-email-template
https://api.oviond.com/openapi.json delete /v1/email/templates/{id}
# Delete Sender
Source: https://docs.oviond.com/api/email/delete-sender
https://api.oviond.com/openapi.json delete /v1/email/senders/{id}
# Delete SMTP Config
Source: https://docs.oviond.com/api/email/delete-smtp-config
https://api.oviond.com/openapi.json delete /v1/email/smtp
Remove the account SMTP server config.
# Get Email Provider
Source: https://docs.oviond.com/api/email/get-email-provider
https://api.oviond.com/openapi.json get /v1/email/provider
Return the active email transport for the account.
# Get Email Template
Source: https://docs.oviond.com/api/email/get-email-template
https://api.oviond.com/openapi.json get /v1/email/templates/{id}
# Get SMTP Config
Source: https://docs.oviond.com/api/email/get-smtp-config
https://api.oviond.com/openapi.json get /v1/email/smtp
Return the account SMTP config (password redacted), or null.
# List Active Senders
Source: https://docs.oviond.com/api/email/list-active-senders
https://api.oviond.com/openapi.json get /v1/email/senders
Senders matching the active provider, with Oviond default first.
# List All Senders
Source: https://docs.oviond.com/api/email/list-all-senders
https://api.oviond.com/openapi.json get /v1/email/senders/all
Every configured sender row regardless of the active provider.
# List Email Domains
Source: https://docs.oviond.com/api/email/list-email-domains
https://api.oviond.com/openapi.json get /v1/email/domain
Return the account's email sending domain (with current verification status), or null.
# List Email Templates
Source: https://docs.oviond.com/api/email/list-email-templates
https://api.oviond.com/openapi.json get /v1/email/templates
# Set Default Email Sender
Source: https://docs.oviond.com/api/email/set-default-email-sender
https://api.oviond.com/openapi.json post /v1/email/senders/{id}/default
# Set Default Email Template
Source: https://docs.oviond.com/api/email/set-default-email-template
https://api.oviond.com/openapi.json post /v1/email/templates/{id}/default
# Set Email Provider
Source: https://docs.oviond.com/api/email/set-email-provider
https://api.oviond.com/openapi.json put /v1/email/provider
Switch the active email transport. Requires the chosen transport to already be configured.
# Test SMTP Connection
Source: https://docs.oviond.com/api/email/test-smtp-connection
https://api.oviond.com/openapi.json post /v1/email/smtp/test
Connect to the SMTP server and verify credentials without sending mail.
# Update Email Template
Source: https://docs.oviond.com/api/email/update-email-template
https://api.oviond.com/openapi.json put /v1/email/templates/{id}
# Update Sender
Source: https://docs.oviond.com/api/email/update-sender
https://api.oviond.com/openapi.json put /v1/email/senders/{id}
# Upsert SMTP Config
Source: https://docs.oviond.com/api/email/upsert-smtp-config
https://api.oviond.com/openapi.json put /v1/email/smtp
Save or update the SMTP server settings for the account.
# Verify Email Domain
Source: https://docs.oviond.com/api/email/verify-email-domain
https://api.oviond.com/openapi.json post /v1/email/domain/{id}/verify
Checks the domain. Fetches the current verification status: if the domain is already verified, the stored record is updated to verified and returned immediately. If not, verification is started and the current (unverified) record is returned — the status then updates on the next check or automatically in the background.
# Archive Export
Source: https://docs.oviond.com/api/exports/archive-export
https://api.oviond.com/openapi.json delete /v1/exports/{id}
Archive a PDF export record. The S3 object is KEPT so a restore still has its PDF — it is purged only when the export is permanently deleted from the archive. Recoverable from the archive.
# List Exports
Source: https://docs.oviond.com/api/exports/list-exports
https://api.oviond.com/openapi.json get /v1/exports
List PDF generation history for a project.
# Create Folder
Source: https://docs.oviond.com/api/folders/create-folder
https://api.oviond.com/openapi.json post /v1/folders/clients
Create a new client folder
# Delete Folder
Source: https://docs.oviond.com/api/folders/delete-folder
https://api.oviond.com/openapi.json delete /v1/folders/clients/{id}
Delete a client folder and unassign all clients from it
# List Folders
Source: https://docs.oviond.com/api/folders/list-folders
https://api.oviond.com/openapi.json get /v1/folders/clients
List all client folders for the current account
# Update Folder
Source: https://docs.oviond.com/api/folders/update-folder
https://api.oviond.com/openapi.json put /v1/folders/clients/{id}
Rename a client folder
# Archive Goal
Source: https://docs.oviond.com/api/goals/archive-goal
https://api.oviond.com/openapi.json delete /v1/goals/{id}
Archive a goal. Recoverable from the archive.
# Create Goal
Source: https://docs.oviond.com/api/goals/create-goal
https://api.oviond.com/openapi.json post /v1/goals
Create a new goal
# Duplicate Goal
Source: https://docs.oviond.com/api/goals/duplicate-goal
https://api.oviond.com/openapi.json post /v1/goals/{id}/duplicate
Duplicate a goal
# List Goals
Source: https://docs.oviond.com/api/goals/list-goals
https://api.oviond.com/openapi.json get /v1/goals
List all goals for the current account, optionally filtered by client_id
# Update Goal
Source: https://docs.oviond.com/api/goals/update-goal
https://api.oviond.com/openapi.json put /v1/goals/{id}
Update a goal
# Health Check
Source: https://docs.oviond.com/api/health/health-check
https://api.oviond.com/openapi.json get /v1/health
# Overview
Source: https://docs.oviond.com/api/introduction
Explore the Oviond REST API. Authenticate with a Bearer token, manage reports, integrations, automations, and access public shared report data.
The Oviond REST API lets you programmatically manage your agency's reports, clients, integrations, and automations. All requests are made over HTTPS to `https://api.oviond.com`.
## Base URL
```
https://api.oviond.com
```
## Authentication
All API requests (except public endpoints) require a Bearer token in the `Authorization` header:
```bash theme={null}
Authorization: Bearer YOUR_API_KEY
```
Generate an API key from **Settings → API Keys** in the Oviond app. See [Authentication](/authentication) for full details.
## Request format
* Send JSON bodies with `Content-Type: application/json`
* All responses are JSON
* Timestamps use ISO 8601 format
## HTTP status codes
| Code | Meaning |
| ----- | --------------------------------------------- |
| `200` | Success |
| `201` | Created |
| `204` | No content (successful delete) |
| `400` | Bad request — check your request body |
| `401` | Unauthorized — missing or invalid API key |
| `403` | Forbidden — insufficient permissions |
| `404` | Not found |
| `422` | Validation error |
| `429` | Too many requests — you've hit the rate limit |
| `500` | Server error |
Every response uses one consistent JSON envelope. See [Errors & request IDs](/api/concepts/errors) for the full shape.
## Rate limiting
Programmatic API and MCP traffic is rate-limited **per account** — the web app is never limited. By default that's 300 requests per minute per surface; a `429 Too Many Requests` response includes a `Retry-After` header. See [Rate limits & retries](/api/concepts/rate-limits) for the headers and safe-retry guidance.
## Concepts
Pull live metric values from connected data sources.
Bearer tokens, API keys, and auth errors.
The response envelope, status codes, and request IDs.
Page through, search, filter, and sort list results.
Limits, headers, and how to retry safely.
What changes are additive vs breaking.
Auth model, tenant isolation, and key handling.
# Archive Media File
Source: https://docs.oviond.com/api/media/archive-media-file
https://api.oviond.com/openapi.json delete /v1/media/{id}
Archive a media item. The underlying file is retained in S3 for potential restore. Recoverable from the archive.
# Archive Multiple Media Files
Source: https://docs.oviond.com/api/media/archive-multiple-media-files
https://api.oviond.com/openapi.json delete /v1/media/bulk
Archive multiple media items. The underlying files are retained in S3 for potential restore. Recoverable from the archive.
# Create Media Folder
Source: https://docs.oviond.com/api/media/create-media-folder
https://api.oviond.com/openapi.json post /v1/media/folders
Create a new media folder.
# Delete Media Folder
Source: https://docs.oviond.com/api/media/delete-media-folder
https://api.oviond.com/openapi.json delete /v1/media/folders/{id}
Delete a media folder. Media items in the folder are not deleted.
# List Media
Source: https://docs.oviond.com/api/media/list-media
https://api.oviond.com/openapi.json get /v1/media
List media assets for the current account (paginated)
# List Media Folders
Source: https://docs.oviond.com/api/media/list-media-folders
https://api.oviond.com/openapi.json get /v1/media/folders
List media folders for the current account.
# Move Media To Folder
Source: https://docs.oviond.com/api/media/move-media-to-folder
https://api.oviond.com/openapi.json put /v1/media/group
Move multiple media items to a folder
# Rename Media File
Source: https://docs.oviond.com/api/media/rename-media-file
https://api.oviond.com/openapi.json put /v1/media/{id}
Update media metadata (e.g. rename).
# Rename Media Folder
Source: https://docs.oviond.com/api/media/rename-media-folder
https://api.oviond.com/openapi.json put /v1/media/folders/{id}
Rename a media folder.
# Archive Multiple Notifications
Source: https://docs.oviond.com/api/notifications/archive-multiple-notifications
https://api.oviond.com/openapi.json delete /v1/notifications/bulk
Archive many notifications in one call (each must belong to the current user). Recoverable from the archive.
# Create Page
Source: https://docs.oviond.com/api/pages/create-page
https://api.oviond.com/openapi.json post /v1/pages
Create a page on a project or template.
# Delete Page
Source: https://docs.oviond.com/api/pages/delete-page
https://api.oviond.com/openapi.json delete /v1/pages/{page_id}
Delete a page.
# List Pages
Source: https://docs.oviond.com/api/pages/list-pages
https://api.oviond.com/openapi.json get /v1/pages
List pages for a project or template.
# Update Page
Source: https://docs.oviond.com/api/pages/update-page
https://api.oviond.com/openapi.json put /v1/pages/{page_id}
Update a page.
# Generate PDF
Source: https://docs.oviond.com/api/pdf/generate-pdf
https://api.oviond.com/openapi.json post /v1/pdf/generate
Enqueue a PDF generation job for a project.
# Get PDF Status
Source: https://docs.oviond.com/api/pdf/get-pdf-status
https://api.oviond.com/openapi.json get /v1/pdf/status/{job_id}
Poll the status of a PDF generation job.
# List Project Changes
Source: https://docs.oviond.com/api/project-changes/list-project-changes
https://api.oviond.com/openapi.json get /v1/projects/{project_id}/changes
Append-only change log for a project, newest-first. The audit trail and the source for preview/scrubber.
# Archive Multiple Projects
Source: https://docs.oviond.com/api/projects/archive-multiple-projects
https://api.oviond.com/openapi.json delete /v1/projects/bulk
Archive multiple projects by ID, each with its widgets. Recoverable from the archive.
# Archive Project
Source: https://docs.oviond.com/api/projects/archive-project
https://api.oviond.com/openapi.json delete /v1/projects/{id}
Archive a project and all its widgets. Recoverable from the archive.
# Create Project
Source: https://docs.oviond.com/api/projects/create-project
https://api.oviond.com/openapi.json post /v1/projects
Create a new project.
# Duplicate Project
Source: https://docs.oviond.com/api/projects/duplicate-project
https://api.oviond.com/openapi.json post /v1/projects/{id}/duplicate
Duplicate a project — deep copy of pages, widgets, and settings.
# Get Project
Source: https://docs.oviond.com/api/projects/get-project
https://api.oviond.com/openapi.json get /v1/projects/{id}
Get a single project by ID.
# List All Projects
Source: https://docs.oviond.com/api/projects/list-all-projects
https://api.oviond.com/openapi.json get /v1/projects/all
List all projects (id + name only) for dropdown selectors.
# List Projects
Source: https://docs.oviond.com/api/projects/list-projects
https://api.oviond.com/openapi.json get /v1/projects
List projects for the current account (optionally filtered by client).
# Refresh Project Widgets
Source: https://docs.oviond.com/api/projects/refresh-project-widgets
https://api.oviond.com/openapi.json post /v1/projects/{id}/refresh
Re-fetch DATA widgets on the project with their current config and the project date range. Optional `datasource_id` body scopes the refresh to widgets fed by that one source (direct + dependent goals / calc-metrics). Fire-and-forget — results broadcast via Realtime.
# Update Project
Source: https://docs.oviond.com/api/projects/update-project
https://api.oviond.com/openapi.json put /v1/projects/{id}
Update a project.
# Quickstart: your first report via the API
Source: https://docs.oviond.com/api/quickstart
Go from an API key to a client report with live data — authenticate, create a client, create a report, and query live metric values.
This quickstart chains the core REST endpoints to take you from zero to a client report with live data. Every field is `snake_case`, and every call uses your [API key](/authentication) as a Bearer token.
One step — connecting a data source — happens once in the Oviond app, because it needs an interactive OAuth consent. Everything else is pure API.
## Before you start
* An Oviond API key (**Settings → API Keys**), on a plan that includes API access.
* Base URL: `https://api.oviond.com`. Set a couple of shell variables to follow along:
```bash theme={null}
export OVIOND_API_KEY="oviond_..."
export OVIOND_BASE="https://api.oviond.com"
```
## 1. Verify your key
```bash theme={null}
curl "$OVIOND_BASE/v1/users/me" -H "Authorization: Bearer $OVIOND_API_KEY"
```
A `200` with your profile confirms the key works. A `401` means the header is missing or the key is invalid; see [Errors](/api/concepts/errors).
## 2. Create a client
Every project belongs to a client.
```bash theme={null}
curl -X POST "$OVIOND_BASE/v1/clients" \
-H "Authorization: Bearer $OVIOND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Demo",
"website": "acme.com",
"timezone": "UTC",
"currency": "USD"
}'
```
The response's `data.id` (for example `cliAbc123`) is your `client_id` for the next steps.
## 3. Connect a data source (in the app)
Data-source connections require interactive OAuth, so connect them once in the app — open a project for the client and use the **Data sources** tab (see [Connecting Data Sources](/data-sources/connect)). Once connected, confirm it over the API:
```bash theme={null}
curl "$OVIOND_BASE/v1/clients/cliAbc123/datasources" \
-H "Authorization: Bearer $OVIOND_API_KEY"
```
Note the `datasource_id` (e.g. `ga4`, `gadw`, `fb-ads`) — you'll need it to query.
## 4. Create a report
```bash theme={null}
curl -X POST "$OVIOND_BASE/v1/projects" \
-H "Authorization: Bearer $OVIOND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Q1 Report",
"type": "REPORT",
"template": "BLANK",
"client_id": "cliAbc123"
}'
```
Use `"type": "DASHBOARD"` for a live dashboard instead of a point-in-time report. The response returns the new project's `id` and `nano_id`. See the [Create Project reference](/api/introduction) for the full set of layout and branding fields.
## 5. Pull live data
Now query real metric values from the connected source:
```bash theme={null}
curl -X POST "$OVIOND_BASE/v1/data/query" \
-H "Authorization: Bearer $OVIOND_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"datasource_id": "ga4",
"client_id": "cliAbc123",
"date_range": { "current_start": "2026-03-01", "current_end": "2026-03-31" },
"metrics": ["sessions", "conversions"],
"dimensions": ["DATE"],
"data_view": "OVERVIEW"
}'
```
See [Querying data](/api/concepts/querying-data) for the full field reference, how to discover valid metrics and dimensions, and error handling.
## 6. Share or schedule
* **Share a link:** open the project in the app and use the **Share** dialog to publish a link (backed by the project's `nano_id`).
* **Schedule delivery:** create an [automation](/automations/scheduled) to email the report on a recurring schedule.
## Next steps
Metrics, dimensions, date ranges, and comparisons.
The response envelope and status codes.
Stay within budget and retry safely.
Every endpoint, request, and response.
# Search
Source: https://docs.oviond.com/api/search/search
https://api.oviond.com/openapi.json get /v1/search
Search clients, projects, users, automations, API keys, email addresses, email templates, email domains and custom domains (powers the command palette).
# Archive Multiple Templates
Source: https://docs.oviond.com/api/templates/archive-multiple-templates
https://api.oviond.com/openapi.json delete /v1/templates/bulk
Archive multiple templates in a single request. Recoverable from the archive.
# Archive Template
Source: https://docs.oviond.com/api/templates/archive-template
https://api.oviond.com/openapi.json delete /v1/templates/{id}
Archive a template. Recoverable from the archive.
# Create Template
Source: https://docs.oviond.com/api/templates/create-template
https://api.oviond.com/openapi.json post /v1/templates
Create a new template, optionally copying pages and widgets from a project.
# Get Template
Source: https://docs.oviond.com/api/templates/get-template
https://api.oviond.com/openapi.json get /v1/templates/{id}
Get a single template by ID.
# List Templates
Source: https://docs.oviond.com/api/templates/list-templates
https://api.oviond.com/openapi.json get /v1/templates
List templates for the current account.
# Update Template
Source: https://docs.oviond.com/api/templates/update-template
https://api.oviond.com/openapi.json put /v1/templates/{id}
Update a template.
# Apply Theme
Source: https://docs.oviond.com/api/themes/apply-theme
https://api.oviond.com/openapi.json post /v1/themes/{id}/apply
Set this theme as the active theme on a scope of projects (current project, all of a client, or every project in the account).
# Archive Theme
Source: https://docs.oviond.com/api/themes/archive-theme
https://api.oviond.com/openapi.json delete /v1/themes/{id}
Archive a theme. Recoverable from the archive.
# Create Theme
Source: https://docs.oviond.com/api/themes/create-theme
https://api.oviond.com/openapi.json post /v1/themes
Create a new theme.
# Get Theme
Source: https://docs.oviond.com/api/themes/get-theme
https://api.oviond.com/openapi.json get /v1/themes/{id}
Get a single theme by ID.
# List Themes
Source: https://docs.oviond.com/api/themes/list-themes
https://api.oviond.com/openapi.json get /v1/themes
List themes for the current account.
# Update Theme
Source: https://docs.oviond.com/api/themes/update-theme
https://api.oviond.com/openapi.json put /v1/themes/{id}
Update a theme.
# Accept Invite
Source: https://docs.oviond.com/api/users/accept-invite
https://api.oviond.com/openapi.json post /v1/users/accept-invite
Called by the frontend after a freshly-invited user completes Supabase Auth callback. Notifies the inviter.
# Change Email
Source: https://docs.oviond.com/api/users/change-email
https://api.oviond.com/openapi.json put /v1/users/me/email
Change the current user email address.
# Delete User
Source: https://docs.oviond.com/api/users/delete-user
https://api.oviond.com/openapi.json delete /v1/users/{id}
Remove a team member from the account.
# Get User
Source: https://docs.oviond.com/api/users/get-user
https://api.oviond.com/openapi.json get /v1/users/me
Get the currently authenticated user profile.
# Invite User
Source: https://docs.oviond.com/api/users/invite-user
https://api.oviond.com/openapi.json post /v1/users/invite
Invite a new user to the account.
# List Users
Source: https://docs.oviond.com/api/users/list-users
https://api.oviond.com/openapi.json get /v1/users
List all team members for the authenticated account.
# Update Avatar
Source: https://docs.oviond.com/api/users/update-avatar
https://api.oviond.com/openapi.json put /v1/users/me/avatar
Update the current user profile picture.
# Update Profile
Source: https://docs.oviond.com/api/users/update-profile
https://api.oviond.com/openapi.json put /v1/users/me/profile
Update the current user profile name, language, and theme.
# Update User
Source: https://docs.oviond.com/api/users/update-user
https://api.oviond.com/openapi.json put /v1/users/{id}
Edit a team member (role, assigned clients, name).
# Bulk Delete Widgets
Source: https://docs.oviond.com/api/widgets/bulk-delete-widgets
https://api.oviond.com/openapi.json delete /v1/widgets/bulk
Delete multiple widgets by ID.
# Bulk Update Widgets
Source: https://docs.oviond.com/api/widgets/bulk-update-widgets
https://api.oviond.com/openapi.json patch /v1/widgets/bulk
Apply per-widget partial updates in a single call.
# Bulk Update Widgets (per-widget patches)
Source: https://docs.oviond.com/api/widgets/bulk-update-widgets-per-widget-patches
https://api.oviond.com/openapi.json patch /v1/widgets/bulk-each
Apply a different patch to each of N widgets in one request.
# Create Widgets
Source: https://docs.oviond.com/api/widgets/create-widgets
https://api.oviond.com/openapi.json post /v1/widgets
Batch create widgets via upsert.
# Delete Widget
Source: https://docs.oviond.com/api/widgets/delete-widget
https://api.oviond.com/openapi.json delete /v1/widgets/{id}
Delete a single widget by ID.
# Duplicate Widgets
Source: https://docs.oviond.com/api/widgets/duplicate-widgets
https://api.oviond.com/openapi.json post /v1/widgets/duplicate
Copy widget rows by id, including persisted series data, into new rows with caller-provided new ids.
# Get Widget
Source: https://docs.oviond.com/api/widgets/get-widget
https://api.oviond.com/openapi.json get /v1/widgets/{id}
Get a single widget by ID.
# List Widgets
Source: https://docs.oviond.com/api/widgets/list-widgets
https://api.oviond.com/openapi.json get /v1/widgets
List widgets for a source.
# Refresh Widgets
Source: https://docs.oviond.com/api/widgets/refresh-widgets
https://api.oviond.com/openapi.json post /v1/widgets/refresh
Authoritative per-widget refresh: connected → real series, not connected → demo, static/non-datasource → skipped.
# Update Widget
Source: https://docs.oviond.com/api/widgets/update-widget
https://api.oviond.com/openapi.json put /v1/widgets/{id}
Update a single widget (partial update).
# Permanently delete
Source: https://docs.oviond.com/archive/delete
Remove archived items from your account forever.
Permanently deleting an archived item is **irreversible** — the row is removed from the database along with all its children (a client's projects and widgets, a project's widgets and pages, a template's pages and widgets, and so on). For media, the underlying file is also removed from storage.
Use it to:
* Free up plan quota immediately
* Remove sensitive data after a client requests erasure
* Clean up test data with certainty
There is no undo. Once an item is permanently deleted, it cannot be recovered — not even by Oviond support.
Go to **Settings → Archive** (`/settings/archive`).
Narrow to the type you want to remove, then check each item. Multi-select works for bulk delete.
A confirmation dialog warns that the items will be permanently deleted. Confirm to proceed, or choose **Keep archived** to cancel.
The Archive is admin-only. Members without the **manage archive** permission can't permanently delete items.
# Restore
Source: https://docs.oviond.com/archive/restore
Bring a soft-deleted item back to your active workspace.
Restoring moves an item out of the Archive and back to its original location. Clients, projects, media, automations, and templates can all be restored — and their dependent children come back intact.
When you restore a **client**, its projects are restored too, along with everything under them (widgets, pages, exports, automations, and run history). When you restore a **project**, its widgets, pages, exports, and automations come back with it. Restored automations are **rescheduled** so they resume on their normal cadence rather than firing a backlog of missed runs.
Go to **Settings → Archive** (`/settings/archive`).
Narrow to **Clients**, **Projects**, **Media**, **Automations**, or **Templates** if you know what you're looking for.
Check the items you want to restore. Multi-select works for bulk restore.
Confirm in the dialog. Items reappear in their original location.
## Plan limits
Restoring a **client** counts against your plan's client limit. If your account is already at the cap, the restore is blocked — upgrade your plan or remove an active client first.
The Archive is admin-only. Members without the **manage archive** permission can't restore items.
# View archive
Source: https://docs.oviond.com/archive/view
Browse every soft-deleted item across your account.
Most things you delete in Oviond are **soft-deleted first** — moved to the Archive rather than removed straight away. Open it from **Settings → Archive** (`/settings/archive`).
The Archive lists archived items across five types:
* **Clients**
* **Projects** (reports and dashboards)
* **Media** (images and files)
* **Automations**
* **Templates**
Each row shows the **Name**, **Type**, and the **Archived** date (`deleted_at`). From here you can **restore** an item back to its original location or **permanently delete** it.
## Find what you're looking for
* **Search** by name.
* **Filter by type** with the type popover — each type shows a live count of how many archived items it holds.
* Sort by name or archived date (newest archived first by default).
The Archive is admin-only. Members without the **manage archive** permission don't see it in the sidebar or have access to the page.
# Authentication
Source: https://docs.oviond.com/authentication
Oviond authenticates API requests with Bearer tokens. Learn how to generate an API key, set the Authorization header, and handle auth errors. All API fields are snake_case.
Oviond's REST API uses Bearer token authentication. Every request must include a token in the `Authorization` header. For programmatic access, generate an API key from your settings. This page explains how to create an API key and pass it correctly in your requests.
The Oviond web app signs in with Supabase Auth and sends a session JWT as its Bearer token. For your own scripts and integrations, use an API key instead, as described below.
## Generate an API key
API keys require the **Manage API keys** permission, so you must be an account owner or admin.
In the Oviond app, go to **Settings → API keys**.
Click **Create**. Give it a descriptive name (for example, "Zapier integration" or "Custom dashboard") so you can identify it later. Choose an access level: **View**, **Edit**, or **Full**. The key inherits your role and client access, capped at the access level you pick.
Your key is shown once and starts with `oviond_`. Copy it and store it securely — you won't be able to see the full key again after you close this dialog.
Treat your API key like a password. Do not commit it to version control or expose it in client-side code.
## Make authenticated requests
Include your API key in the `Authorization` header as a Bearer token on every request:
```bash theme={null}
curl -X GET https://api.oviond.com/v1/users/me \
-H "Authorization: Bearer YOUR_API_KEY"
```
Replace `YOUR_API_KEY` with the key you generated above.
## Example: Fetch your account
```bash theme={null}
curl https://api.oviond.com/v1/users/me \
-H "Authorization: Bearer YOUR_API_KEY"
```
A successful response wraps your user profile in the standard success envelope. All fields are snake\_case:
```json theme={null}
{
"success": true,
"data": {
"id": "...",
"account_id": "ov:26AbCdEfGhIjKlMnOp",
"fullname": "Your Name",
"email": "you@yourcompany.com",
"email_verified": true,
"role": "admin"
}
}
```
## Authentication errors
Errors return the standard error envelope:
```json theme={null}
{
"success": false,
"error": {
"message": "Invalid or revoked API key",
"status_code": 401
},
"meta": {
"request_id": "..."
}
}
```
| Status | Meaning |
| ------------------ | -------------------------------------------------------------------------------------------------- |
| `401 Unauthorized` | The `Authorization` header is missing or malformed, or the key is invalid or revoked. |
| `403 Forbidden` | Your key is valid but doesn't have permission for this resource, or your account lacks API access. |
If you receive a `401`, double-check that you've included the `Authorization: Bearer ` header and that the key hasn't been revoked.
## Manage your API keys
You can list, create, and revoke API keys at any time from **Settings → API keys** in the app, or via the [API Keys API](/api-keys/list).
Each API key is scoped to your account and inherits the role and client access of the person who created it, capped at the key's access level.
# Add an automation
Source: https://docs.oviond.com/automations/add
Schedule a report or dashboard for recurring email delivery.
An **automation** emails a project's report to a list of recipients on a recurring schedule — daily, weekly, or monthly. On each run, Oviond renders the report for the configured date range and emails it from the sender you choose, using the email template you select.
You can create an automation two ways:
* From the top-level **Automations** screen in the sidebar.
* From the **Automations** tab inside the project editor, which pre-selects the current project.
Click **Automations** in the left sidebar, then click **New automation**. Inside the project editor, open the **Automations** tab and click **Add automation** instead.
Enter a **Name**, then set the **Frequency** (**daily**, **weekly**, or **monthly**), the day, and the send time. See [Scheduled delivery](/automations/scheduled).
Pick the **Client** and **Project** to deliver (the project is fixed when you start from the editor tab), then choose a **Date range** such as `Last Month`. The report is rendered fresh for that range on every run.
Add **Recipients**, choose the **From** sender, and pick an **Email template** — or select **Custom message** to compose a new template inline. See [Email delivery](/automations/email).
Click **Create**. The automation is saved and the next run is scheduled automatically.
Always [test](/automations/test) a new automation before relying on it — the test send bypasses the schedule and emails the report immediately so you can verify it looks right.
# Archive an automation
Source: https://docs.oviond.com/automations/delete
Stop and remove a scheduled delivery, with the option to restore it.
Archiving an automation stops it from running and removes it from the active **Automations** list. It's a soft delete — the configuration is retained, so you can restore the automation from the archive later. The underlying **project** is not affected; only the scheduled delivery stops.
From the **Automations** screen, use the row menu or open the details slide-over. You can also archive from the **Automations** tab inside the project editor.
The automation stops running. Confirm when prompted.
Archiving clears the automation's next run so it won't send again. Its email template stays in your templates list and isn't deleted.
If you only need to suspend deliveries temporarily, **Pause** the automation instead of archiving it — paused automations stay in the active list and resume with a single click. See [List automations](/automations/list).
## Bulk archive
To archive several automations at once, select them with the checkboxes and use the bulk **Archive** action. This soft-deletes each selected automation the same way and removes them from the active list.
## API
* `DELETE /v1/automations/:id` — archive a single automation.
* `DELETE /v1/automations/bulk` — archive several at once, with a body of `{ "ids": [...] }`.
# Email delivery
Source: https://docs.oviond.com/automations/email
Configure the recipients, sender, and template of an automation's email.
The **Email** step of an automation controls who receives the report and how the email looks. You set this when you create or edit an automation.
## Recipients
Add one or more recipient email addresses in the **Recipients** field. These are stored as `recipients` and are who the scheduled report is sent to. A [test send](/automations/test) can target a different address without changing this list.
## Sender
Choose who the email comes **From**. The dropdown lists your saved senders by name and address (for example `Reports `), stored as `sender_id`. If no sender resolves, Oviond falls back to its default address, so an automation can still send before you've configured a sender.
An automation with no usable sender shows a **No sender** status on the Automations list and won't deliver until one is set.
## Email template
Pick an **Email template** for the message body and subject, stored as `template_id`:
* **Saved template** — select any template from the list. The default is marked `(default)`.
* **Custom message** — choose **Custom message** to compose a new one. Enter a **Template name**, **Subject**, and **Message**. The custom message is saved as a new, reusable email template in your templates list and the automation references it by id.
The composer preview fills in placeholders — client name, project name, date range, and so on — using the selected project so you can see the real values before sending.
## Date range
The **Date range** you choose (stored as `date_text`) is passed to the report on every run, so the email always reflects the correct reporting period. See [Scheduled delivery](/automations/scheduled).
# Run history
Source: https://docs.oviond.com/automations/history
See every past run of a project's automations and its status.
The **Automation History** page lists every run recorded for a project — across all of its automations, and including both scheduled deliveries and test sends. Open it from an automation's **Executions** action, or from the row menu. The page lives at `/automations/:project_id`.
Each row shows the run's name, **Source** (**Scheduled** or **Test**), the time it sent, its status, the report **Type**, and the **Date range** it covered. Test runs are also tagged with a **Test** badge. You can search by name and filter by report type, and the list is paginated.
## Status values
| Status | Meaning |
| ----------- | ----------------------------------------------------------------------------------------------------- |
| **Success** | The run rendered and sent. |
| **Failed** | The run errored — typically a rendering or delivery problem. The error detail is stored with the run. |
| **Skipped** | The run was skipped (for example, the automation was paused when it was due). |
## When to check history
* **Debugging a missed delivery** — confirm a scheduled run actually fired and whether it succeeded or failed.
* **Verifying a test** — a test send shows up here as a **Test** row right after you trigger it.
* **Auditing** — confirm an end-of-month report went out on time.
## Endpoint
The history is served by `GET /v1/automations/:project_id/history` — note that it's scoped by **project**, not by a single automation id. It aggregates the runs of every automation attached to that project into one timeline and is paginated via `page` and `limit`.
Archiving a run from the history list removes the underlying report snapshot for that run, not the automation itself. The automation keeps running on its schedule.
# List automations
Source: https://docs.oviond.com/automations/list
View, test, pause, or archive every scheduled delivery.
The top-level **Automations** screen lists every automation in your account. Each row shows the automation's name, project, schedule, next send, and a status badge. Use the search box to filter by name, project, recipient, template, or sender, and the filter tiles to narrow the list.
## Filter tiles
| Tile | Shows |
| ------------------- | ----------------------------------------------------------------------------------------------- |
| **Needs attention** | Failed last run, no next send scheduled, paused with nothing upcoming, or no sender configured. |
| **Due next** | Automations scheduled to send within the next 24 hours. |
| **Delivered** | Automations that delivered successfully in the last week. |
| **Paused** | Automations currently paused. |
## Row actions
Click a row to open the details slide-over, or use the row menu:
| Action | Result |
| ------------------ | ------------------------------------------------------------------------------------------------------ |
| **Edit** | Opens the automation for editing (schedule, recipients, template, sender). |
| **Executions** | Opens the run history for the project — see [Run history](/automations/history). |
| **Test** | Sends the automation immediately — see [Test an automation](/automations/test). Disabled while paused. |
| **Pause / Resume** | Stops the automation from running, or resumes it. See below. |
| **Archive** | Soft-deletes the automation — see [Archive an automation](/automations/delete). |
## Pause and resume
Pausing clears the automation's next run so it stops sending, but keeps all of its configuration. Resume it any time to schedule the next run again. Useful when a client is on hold or you're switching templates mid-month.
## Status badges
| Badge | Meaning |
| ------------------------ | ------------------------------------------ |
| **Active** | Scheduled and ready to send. |
| **Delivered** | Last run succeeded. |
| **Queued** / **Running** | A run is in progress. |
| **Failed** | The last run failed. |
| **Paused** | Paused — won't send until resumed. |
| **No next send** | No upcoming run is scheduled. |
| **No sender** | No sender is configured, so it can't send. |
# PDF export
Source: https://docs.oviond.com/automations/pdf
Generate a downloadable PDF of a report on demand.
Oviond renders any report as a PDF on demand. Generation runs asynchronously in the background, so large reports don't block your browser — Oviond queues a job, renders the report headlessly, and stores the finished file for download.
## Generate a PDF
From the project, open **Share** and switch to the **Download** tab.
Oviond queues a generation job. The button shows **Generating** (or a queued count) while it works, and a new entry appears in the **Download History** list in a processing state.
When the job completes, the history row flips to a success state and a **Download** link appears. Use the trash icon to remove an export and its stored file.
The list reflects each generation attempt's state — **processing**, **completed**, or **failed**.
## How it works
Generation is a two-step asynchronous flow:
1. `POST /v1/pdf/generate` validates the request and enqueues the job, returning a `job_id`. The request specifies the `project_id`, `client_id`, a page `format` (**A4** or **Letter**), and `orientation` (**portrait** or **landscape**). The defaults are `A4` and `portrait`.
2. `GET /v1/pdf/status/:job_id` is polled until `status` is `complete` (which returns the file `url`) or `failed`.
Each attempt is recorded in the project's export history, which the **Download History** list reads from.
PDF generation requires Oviond's file storage (S3) to be configured. If it isn't, the generate request is rejected.
## Troubleshooting
**Generation fails or times out** — Very large reports with many widgets can occasionally fail to render. Try again, or split the report across more pages. Failed attempts show a **failed** state in the history list.
**Images or logos missing** — Make sure all image URLs in your report are publicly accessible. Private or expired URLs won't render in the headless browser.
# Scheduled delivery
Source: https://docs.oviond.com/automations/scheduled
Set the frequency, day, and time an automation sends.
Each automation sends its report on a recurring schedule you define. Oviond renders the report for the configured date range and emails it to your recipients — no manual sending required.
## Set the schedule
When you create or edit an automation, the **Schedule** step controls when it sends:
* **Frequency** — **Daily**, **Weekly**, or **Monthly**.
* **Day of week** — shown for **weekly** automations (Monday–Sunday).
* **Day of month** — shown for **monthly** automations (day `1`–`31`).
* **Send at** — the hour, minute (`00` or `30`), and `AM`/`PM`.
The schedule is stored as `frequency`, `day`, `hours`, `minutes`, and `time_format`, and is evaluated against the account's `timezone`. The send time is shown in that timezone in the automation's details.
Oviond checks for due automations every minute, so a run starts shortly after its scheduled time rather than exactly on the second.
## Date range
The **Date range** (for example `Last Month`) is stored as `date_text` and decides which period the report covers. It's resolved fresh on every run, so a monthly automation set to `Last Month` always sends the most recent complete month.
## After it's scheduled
Once saved, the automation runs on its next scheduled time. From the **Automations** screen you can:
* **Edit** the schedule, recipients, template, or sender at any time. Changing the schedule recomputes the next run.
* **Pause / Resume** to suspend sending without losing the configuration.
* **Test** to send immediately — see [Test an automation](/automations/test).
* **Archive** to stop and remove it — see [Archive an automation](/automations/delete).
## View execution history
Open an automation and click **Executions** (or open the project's run history) to see every past run — scheduled and test — with its timestamp and status. See [Run history](/automations/history).
# Test an automation
Source: https://docs.oviond.com/automations/test
Send an automation immediately to verify its content.
A **test send** bypasses the schedule and emails the report right now. Use it after creating or editing an automation — it's the fastest way to catch a broken widget, wrong logo, or mangled subject line before a real delivery.
From the **Automations** list, use the row menu or open the details slide-over. You can also test from the **Automations** tab inside the project editor.
Oviond renders the report with the automation's current settings and sends it exactly as a scheduled run would.
The recipient dialog is pre-filled with the automation's saved recipients. Edit them to send the test to a different address instead.
Verify the subject, sender, message body, and rendered report look correct.
A test runs immediately rather than going through the queue, so you get fast feedback. Oviond also posts a success or failure notification when it finishes.
A test send does **not** advance the automation's schedule — it leaves the last-run and next-run times untouched. It **does** record an entry in [run history](/automations/history), flagged as a **Test** run so you can tell it apart from scheduled deliveries.
You can't test a **paused** automation — the **Test** action is disabled until you resume it.
# Invoices
Source: https://docs.oviond.com/billing/invoices
View and download past invoices for your Oviond subscription.
Oviond issues an invoice each time your plan renews. Past invoices are listed on the billing page, and each links to a Stripe-hosted PDF you can keep for your records.
Viewing invoices requires admin or owner permissions.
## View and download
Go to **Settings → Billing** and scroll to **Invoice history**.
Invoices are listed most-recent first. Each row shows the invoice number, date, description, and status.
Click the invoice number or **View** to open the Stripe-hosted invoice PDF in a new tab, where you can download or print it.
## What's on an invoice
Invoices are generated by Stripe and include:
* Your billing details on file with Stripe
* The Oviond charge and description for the period
* Any taxes collected for your region
* The payment status (for example, `paid`, `open`, or `void`)
To change the billing details or tax ID on future invoices, update them in the Stripe customer portal via **Settings → Billing → Open billing portal** before your next renewal. Past invoices can't be re-issued.
# Plans
Source: https://docs.oviond.com/billing/plans
Understand Oviond's agency plan and how pricing scales with your client count.
Oviond is a single agency plan that scales with the number of clients you report for. Every core feature stays included as you grow — you only change the client count. API and MCP access are included.
Managing billing requires admin or owner permissions.
## How pricing works
Go to **Settings → Billing** to see the plan and pricing. Choose how many clients you report for, and the price updates instantly.
* A **client** is one reporting profile, brand, store, branch, or business you report for.
* Pick **Monthly** or **Annual** billing. Annual billing saves 20% versus paying monthly.
* The per-client price is shown alongside the total so you can see how it scales.
Pricing starts at \$49/month for 5 clients. Exact pricing and client counts come from Stripe and are shown live in the billing page, so treat any figures here as illustrative.
## Plan usage
The billing page shows your current usage at the top:
* **Account status** — your subscription state (for example, `active`, `trialing`, or `past_due`)
* **Active clients** — clients used against the limit included in your plan
When you approach your client limit, Oviond flags it so you can increase your count.
## Change your plan
Go to **Settings → Billing**.
Use the slider or the **+ / −** stepper to choose how many clients you report for, and pick **Monthly** or **Annual**. You can't select fewer clients than you're already using.
* If you're on a trial or have no active subscription, click **Select Plan** to go to Stripe-hosted checkout and enter payment details.
* If you already have an active subscription, click **Update Plan**. Oviond previews the prorated charge or credit, and you confirm the change in-app — no return to checkout.
## Enterprise and volume pricing
If you need volume pricing, custom onboarding, or specific integration or security requirements, use **Get in touch** on the billing page to contact the Oviond team.
## Lifetime deal (LTD) add-ons
If you bought a lifetime deal, the billing page shows **LTD add-ons** instead of the plan selector. From there you can buy additional clients, additional custom domains, API access, and Twitter insights as add-ons to your lifetime plan.
# Subscription
Source: https://docs.oviond.com/billing/subscription
Manage your plan, payment method, and subscription through Stripe.
Oviond uses Stripe for subscription billing. You change your client count and billing cycle directly on the billing page, and manage payment details and cancellation through the Stripe customer portal.
Managing billing requires admin or owner permissions.
## Open the billing portal
Go to **Settings → Billing** and click **Open billing portal**. This opens the Stripe customer portal in a new tab, where you can:
* Update your card or payment method
* View and download past invoices
* Cancel your subscription
## Change your plan
You change your client count and billing cycle on the billing page itself, not in the Stripe portal. Adjust the client count, choose **Monthly** or **Annual**, then click **Update Plan**. Oviond previews the prorated amount or credit, and you confirm the change in-app. See [Plans](/billing/plans) for the full flow.
## Update your payment method
Go to **Settings → Billing** and click **Open billing portal**.
In the Stripe portal, add or update your card details.
Set your preferred card as the default so it's used for future charges.
## Past or missing payments
If a payment fails, the billing page shows a banner. Use **Open billing portal** to update your payment method, or, if your subscription is unpaid, the banner lets you reactivate the subscription and settle outstanding invoices.
## Cancel your subscription
In the Stripe customer portal, cancel your plan. Your subscription stays active until the end of the current billing period — the billing page shows a `pending_cancellation` status until then.
Canceling doesn't delete your data. However, once your subscription ends, access to billed features is limited until you resubscribe.
# Add a calculated metric
Source: https://docs.oviond.com/calculated-metrics/add
Build a custom KPI from a formula and set how it displays.
From the client's **Projects** tab, open the report or dashboard.
In the editor sidebar, open the **Calculated Metrics** tab and click **Add Calculated Metric**.
Add tokens to the formula canvas:
* **Metric** — a query against a connected data source (pick the source, metric, and optional dimension).
* **Operator** — `+`, `-`, `×`, `÷`, and parentheses to control order.
* **Number** — a constant value.
Choose how the result displays: **Numeric**, **Decimal**, **Percentage**, or **Currency**.
Give the metric a clear name and save it. It's now available to widgets in this project.
Each metric token is a normal data-source query, so a single formula can combine metrics from different platforms — for example ad spend from one source divided by conversions from another.
## API
`POST /v1/calculated-metrics` creates a calculated metric.
# Delete a calculated metric
Source: https://docs.oviond.com/calculated-metrics/delete
Remove a calculated metric you no longer need.
Deleting removes the calculated metric from the project.
In the project editor, open the **Calculated Metrics** tab.
Open the metric's menu and choose **Delete**.
Widgets that referenced the deleted metric stop resolving until you point them at another metric.
## API
`DELETE /v1/calculated-metrics/{id}` removes a calculated metric.
# Duplicate a calculated metric
Source: https://docs.oviond.com/calculated-metrics/duplicate
Start a new metric from an existing formula.
Duplicating copies an existing calculated metric's formula and format, so you can create a variant without rebuilding it.
In the project editor, open the **Calculated Metrics** tab.
Open the metric's menu and choose **Duplicate**. A copy is added that you can rename and edit.
Use duplicate to build a family of related KPIs — for example a cost-per-conversion metric per channel — from one formula.
## API
`POST /v1/calculated-metrics/{id}/duplicate` copies a calculated metric.
# Calculated metrics
Source: https://docs.oviond.com/calculated-metrics/overview
Build custom KPIs from formulas that combine metrics across your data sources.
A **calculated metric** is a custom KPI defined by a formula — for example `Revenue / Sessions` or `(Clicks / Impressions) * 100`. You combine metrics from your connected data sources with operators and number constants, then use the result in widgets like any other metric.
Calculated metrics are managed inside the project editor, on the **Calculated Metrics** tab.
## Use a calculated metric
Once saved, a calculated metric appears alongside your data-source metrics in the **Data Query** widget's metric picker. Select it like any other metric to chart it, show it as a KPI, or add it to a table.
## In this section
* [Add a calculated metric](/calculated-metrics/add) — build a formula and set its format.
* [Duplicate a calculated metric](/calculated-metrics/duplicate) — start a variant from an existing metric.
* [Delete a calculated metric](/calculated-metrics/delete) — remove a metric you no longer need.
## API
| Action | Endpoint |
| --------- | -------------------------------------------- |
| List | `GET /v1/calculated-metrics` |
| Create | `POST /v1/calculated-metrics` |
| Update | `PUT /v1/calculated-metrics/{id}` |
| Duplicate | `POST /v1/calculated-metrics/{id}/duplicate` |
| Delete | `DELETE /v1/calculated-metrics/{id}` |
# January 2026
Source: https://docs.oviond.com/changelog/2026-01
Release notes for the Oviond REST API.
### The report canvas
Build reports and dashboards from pages and widgets. Pages organize a report into sections; widgets are the charts, KPIs, text, images, buttons, and embeds on each page. The atomic save persists pages and bulk widget upserts in a single call.
* `POST /v1/pages` and `PUT /v1/pages/{page_id}` — add and update report pages
* `POST /v1/widgets` and `POST /v1/widgets/bulk` — batch upsert and bulk-delete widgets
* `POST /v1/widgets/duplicate` — copy widgets across a page
### Projects
Every report and dashboard is a project that lives inside a client. Create projects from scratch or duplicate an existing one.
* `POST /v1/projects` — create a report or dashboard
* `GET /v1/projects` and `GET /v1/projects/all` — list and dropdown views
* `POST /v1/projects/{id}/duplicate` — clone a project
### Client workspaces
Every project ties to a client. Organize clients into folders and manage them in bulk.
* `POST /v1/clients` — create a client
* `POST /v1/folders/clients` — create a client folder
* `PUT /v1/clients/{id}/folder` — move a client between folders
* `POST /v1/clients/bulk` — bulk operations
### Accounts, users, and onboarding
Sign up, provision an account, and complete the guided onboarding flow. Authenticated requests use a Supabase-issued Bearer JWT.
* `GET /v1/account` and `GET /v1/account/usage` — account and plan snapshot
* `GET /v1/users/me`, `PUT /v1/users/me/profile`, `PUT /v1/users/me/email`, `PUT /v1/users/me/avatar`
* `POST /v1/onboarding` — finalize the onboarding flow
# February 2026
Source: https://docs.oviond.com/changelog/2026-02
Release notes for the Oviond REST API.
### Custom KPIs and reusable queries
Define formulas that combine metrics across data sources, and save query configurations you reuse across reports.
* `POST /v1/calculated-metrics` — define a formula (`POST /v1/calculated-metrics/{id}/duplicate` to clone)
* `POST /v1/saved-metrics` — save a query config (`POST /v1/saved-metrics/{id}/duplicate`)
### Bring your own datasets
Upload CSV or JSON datasets and query them alongside connected data sources.
* `POST /v1/custom-data` — upload and parse a dataset
* `PUT /v1/custom-data/{id}` and `POST /v1/custom-data/{id}/duplicate`
### Pull metrics from any source
A single query API resolves metrics and breakdowns across every connected platform, with a dry-run test path.
* `POST /v1/data/query` — pull metrics
* `POST /v1/data/test` and `GET /v1/data/accounts`, `GET /v1/data/resource`
* `POST /v1/datasources/test` — verify a connection
### Connect marketing platforms via OAuth
OAuth 2.1 connection flow for Google Analytics, Meta Ads, LinkedIn, and the rest of the data-source catalog. Auth profiles link to clients; an account or property is chosen per connection.
* `POST /v1/datasources/auths` — create an auth profile from an OAuth grant
* `POST /v1/datasources/{client_id}/link` and `POST /v1/datasources/{client_id}/unlink`
* `GET /v1/datasources/{datasource_id}/profiles` — manage connection profiles
# March 2026
Source: https://docs.oviond.com/changelog/2026-03
Release notes for the Oviond REST API.
### Sending infrastructure
Send reports from your own addresses over a verified domain or your own SMTP server, with reusable email templates.
* `GET|PUT /v1/email/provider` — select the active transport (Oviond, SMTP, or domain)
* `POST /v1/email/senders` and `POST /v1/email/senders/{id}/default`
* `POST /v1/email/smtp` and `POST /v1/email/smtp/test`
* `POST /v1/email/domain` and `POST /v1/email/domain/{id}/verify`
* `POST /v1/email/templates`
### Scheduled report delivery
Schedule reports to be emailed to clients on a recurring cadence, with pause/resume, run history, and test sends.
* `POST /v1/automations` — create an automation
* `POST /v1/automations/{id}/pause` and `/v1/automations/{id}/unpause`
* `POST /v1/automations/{id}/test` — send a test without advancing the schedule
* `GET /v1/automations/{project_id}/history` — inspect past deliveries
### PDF generation
Render any report to PDF asynchronously — enqueue a job, then poll for status until the download is ready.
* `POST /v1/pdf/generate` — enqueue a job
* `GET /v1/pdf/status/{job_id}` — poll until complete
* `GET /v1/exports` and `GET /v1/exports/{id}` — export history
### Shareable report links
Every project gets a short `nano_id` share URL. Public endpoints return the full rendered payload — widgets, branding, and theme — with no authentication required.
* `GET /v1/public/resolve/{nano_id}` — resolve a short link
* `GET /v1/public/project/{account_id}/{project_id}` — full render payload
* `GET /v1/public/branding/{account_id}` and `GET /v1/public/theme/{theme_id}`
# April 2026
Source: https://docs.oviond.com/changelog/2026-04
Release notes for the Oviond REST API.
### Asset library and saved sections
Upload images, organize them into folders, and save reusable widget sections you can drop into any report.
* `POST /v1/media` and `GET /v1/media/folders` — uploads and folders
* `PUT /v1/media/group` — set folder membership
* `POST /v1/assets` and `POST /v1/assets/{id}/duplicate` — saved widget sections
* `POST /v1/assets/{id}/add-to-page` — drop an asset onto a page
### Reusable scaffolds and styling
Create templates from existing reports and apply themes to control typography, palette, and chart styling across any project.
* `POST /v1/templates` and `POST /v1/templates/bulk`
* `POST /v1/themes` — chart colors auto-derive from `primary_color`
* `POST /v1/themes/{id}/apply` — apply to the current project, the client, or all projects
### Serve reports from your own domain
Add a custom domain, verify it via DNS, and set a default. DNS provider is auto-detected; SSL is handled for you.
* `POST /v1/custom-domains` — add a domain
* `GET /v1/custom-domains/{domain_id}/status` — check DNS verification
* `POST /v1/custom-domains/{domain_id}/default` — set the default domain
### Branded client experiences
Set agency branding — logo, favicon, brand color — and company details that appear on report headers, emails, and shared links.
* `PUT /v1/branding` — update branding settings
* `GET|PUT /v1/company` — company details
# May 2026
Source: https://docs.oviond.com/changelog/2026-05
Release notes for the Oviond REST API.
### Recover anything, find anything
Soft-deleted clients, projects, media, automations, and templates land in the archive, where you can restore or permanently delete them. A unified search spans your workspace.
* `GET /v1/archive` and `GET /v1/archive/counts`
* `PUT /v1/archive/restore` and `DELETE /v1/archive/permanent`
* `GET /v1/search` — search across the workspace
### Targets and a project timeline
Set targets for any metric and track progress in reports. Every project keeps a change history you can inspect and roll back to.
* `POST /v1/goals` — define a target (`POST /v1/goals/{id}/duplicate` to clone)
* `GET /v1/projects/{project_id}/changes` — version history
* `GET /v1/projects/{project_id}/at/{seq}` — load a past version
### Stay informed
In-app notifications for automation failures, data-source disconnects, and team events, plus a full audit log of account activity.
* `GET /v1/notifications` and `DELETE /v1/notifications/bulk`
* `PUT /v1/notifications/preferences` — email, Slack, and Discord delivery
* `GET /v1/activity` — audit log
### Programmatic access
Issue API keys to call the REST API outside the app. Keys carry an access level and can be revoked instantly.
* `POST /v1/api-keys` — create a key (secret shown once)
* `DELETE /v1/api-keys/{id}` — revoke a key
### Multi-user accounts
Invite team members, assign access levels, and restrict users to a subset of clients.
* `POST /v1/users/invite` — invite a team member
* `POST /v1/users/accept-invite` — accept and set a password
* `GET|PUT /v1/users/{id}` — manage a member's access
# June 2026
Source: https://docs.oviond.com/changelog/2026-06
Release notes for the Oviond REST API.
### REST API reference launched
The Oviond REST API reference is now live on Mintlify — the full endpoint catalog across clients, projects, widgets, data sources, automations, and public share links, auto-generated from the backend's OpenAPI spec and kept in sync on every release.
* Interactive **Try it** console against `https://api.oviond.com`
* Bearer-token authentication via API keys from **Settings → API keys**
* Grouped by domain: Account, Clients, Projects, Data sources, Automations, Public, and more
### Model Context Protocol support
Connect AI agents to your Oviond workspace over a streamable HTTP MCP endpoint, secured with OAuth 2.1 (PKCE, dynamic client registration).
* `POST /mcp` — MCP endpoint
* `GET /.well-known/oauth-authorization-server` — discovery
* `POST /oauth/register`, `GET /oauth/authorize`, `POST /oauth/token`, `POST /oauth/revoke`
### Self-serve billing
Manage your plan, payment, and invoices through Stripe. The plan scales by active client count, billed monthly or annually.
* `GET /v1/billing` and `GET /v1/billing/plans`
* `POST /v1/billing/subscribe` and `GET /v1/billing/portal`
* `GET /v1/billing/invoices` — invoice history
# July 2026
Source: https://docs.oviond.com/changelog/2026-07
Release notes for the Oviond REST API.
### Test sends now match what the automation will deliver
The **Send test** button on an automation produced an email whose report link opened the source dashboard on *its* date range, not the automation's. Testing a "Last 12 Months" automation showed "Last 7 Days" — the recipient was reviewing a different report from the one the schedule would send.
A test now builds the same dated copy of the report a scheduled run does, resolved against the automation's own date range. Everything else about a test is unchanged: it still records a single run in the automation's history, never advances the schedule, and can be repeated as often as you like.
### Klaviyo widgets survive rate limits
Klaviyo enforces a strict request rate and returns a `429` with a retry delay when you exceed it — a report with several Klaviyo widgets could trip it and leave widgets in an error state.
Oviond now reads the delay Klaviyo asks for, pauses every Klaviyo request for that period, and retries. Widgets that previously failed on a busy report load complete instead. No reconfiguration needed.
### Choose which SerpWatch keywords a widget reports on
SerpWatch widgets fetched every keyword on a project before filtering, which was slow on large projects and could hit the platform's rate limit.
A widget now reports on up to **50 keywords**, chosen in one of two ways:
* **Pick them explicitly** — the **Keywords** field in advanced settings, which now shows a `n/50` counter and stops accepting selections at the limit.
* **Let Oviond choose** — leave Keywords empty and the top 50 are selected by the new **Sort By** (Current Position, Name, Movement, Status, Best Position) and **Order** settings, narrowed by the new **Device**, **Type** (Owner, Competitor, Paid) and **Search Engine** filters.
Existing SerpWatch widgets keep their configuration and now default to the 50 best-ranking keywords.
### Project ID is now required for Ahrefs Rank Tracker
The Ahrefs **Rank Tracker** dataview needs an Ahrefs project to query keywords against. Without one the widget returned nothing with no explanation.
**Project ID** is now a required field in the widget's advanced settings for that dataview, validated before the query runs. Other Ahrefs dataviews are unaffected.
### `title` on a notification is now `name`
A notification's headline field is renamed from `title` to `name`, so a notification carries the same field as every other record you can list and archive.
This affects the notification endpoints and the corresponding MCP tools. Update any integration that reads `notification.title` to read `notification.name`. Nothing else about the shape changed, and the in-app inbox is unaffected.
### "Delete" now says "Archive" where nothing is destroyed
Sixteen operations were labelled *delete* while the record actually moved to the Archive and could be restored. The names and descriptions now say what happens, and point to the Archive rather than implying the record is gone.
Renamed to `archive_*`: clients, projects, assets, automations, templates, themes, goals, calculated metrics, custom data, exports, media files, and notifications — singular and bulk. The matching REST summaries and descriptions were corrected in the same pass.
Operations that genuinely destroy, with no undo, keep the `delete_*` name: widgets, pages, folders, media folders, datasource connections, notification channels, API keys, email senders and templates, custom domains, and removing a user.
Only the names and descriptions changed. Every endpoint behaves exactly as it did.
### Setting a project date range to a preset now takes effect
Updating a project with a preset alone — `{ "text": "Last 7 Days" }` — stored the preset without any resolved start and end dates. The project looked correct, but its widgets kept rendering their previous dates because the refresh had no window to run against.
The preset is now resolved against the client's timezone before it is stored, merged over the range already on the project so a partial update keeps what it didn't mention (such as the comparison period). Widgets refresh against the resolved range, matching what the date picker in the app has always done.
### Filtering saved sections by data source returns results again
The **Data source** filter in the Assets panel returned nothing. Assets record the data sources they use by display name ("Google Ads"), while the filter sent the alias id (`gadw`), so the two never matched.
The filter now translates the id before matching. Saved sections filter correctly, singly or in combination.
### Google Analytics 4 custom definitions appear in the builder
Custom dimensions and custom metrics defined on a GA4 property are now loaded from that property when you open the report builder, and appear alongside the standard GA4 fields.
They're read live per property, so a definition added in GA4 is available in Oviond without waiting for a release. Existing GA4 widgets are unchanged.
### MCP data widgets are configured the same way the builder configures them
The MCP tools that create and update DATA widgets now run the report builder's own query logic rather than their own copy of it. In practice that means an agent gets the same answers, and the same errors, a person gets in the editor:
* **One discovery call.** `describe_datasource` returns a datasource's data views, the advanced settings each view requires, and its metric and dimension catalogs with the flags that decide what can be combined — a dimension that must be the only one, a dimension only offered once a particular metric is picked, deprecated fields, and per-account custom fields.
* **Selections are validated against the catalog.** A metric or dimension that doesn't belong to the chosen data view is rejected with the valid list, instead of being saved and silently returning nothing.
* **The cascade matches the editor.** Changing the datasource clears the data view, metrics, dimensions, filters and advanced settings, then applies that datasource's defaults; changing the data view clears metrics and dimensions.
* **Widgets are named the same way.** An unnamed widget gets the generated name the builder would give it ("Clicks & Impressions by Date"), and a name you set is never overwritten.
* **Display-only changes don't re-fetch.** Editing a chart type, sort order, row limit or metric label writes through without re-running the query, mirroring the builder's two panels.
Datasource connections can also now be created from a tool for platforms that authenticate with an API key. Platforms that sign in on the vendor's website (Google, Meta, LinkedIn, TikTok) still need a browser and are connected in the app, then linked from a tool.
### ChatGPT Ads
Report on ChatGPT Ads campaign performance. Connect it with an API key from your OpenAI Ads account — the key scopes to the advertiser, so there's no account to pick after connecting.
Three dataviews, each with **Impressions**, **Clicks**, **Spend**, **CTR (%)**, **Avg CPC** and **Avg CPM**:
* **Campaigns** — broken down by campaign name, status, daily budget and lifetime budget. Adds **Conversions**, which the platform reports at campaign level only.
* **Ad Groups** — by ad group name and status.
* **Ads** — by ad name, status, URL and parent ad group.
All three support a date breakdown, and widgets can be narrowed to specific campaigns, ad groups or ads in advanced settings.
### AdRoll gains a Conversion Events dataview
A new **Conversion Events** dataview reports on the audiences and conversion rules configured in AdRoll, broken down by conversion event: **Estimated Audience Size**, **Unique Website Visitors**, **Rule**, **Type** and **Duration**.
The existing **Account** dataview also picks up **CPA**. Existing AdRoll widgets are unaffected.
### Number format per client
Each client can now choose how numbers read in its reports. A **Number format** setting under **Settings → General** sets the thousands and decimal separators — for example `1,234.56` (US) versus `1.234,56` (German) — independently of the client's currency.
The value is a BCP 47 locale, so it works for any region without a fixed list of "US vs Europe" options. New clients default to `en-US`, and every existing client keeps rendering exactly as before until you change it.
Over the API this is the `number_format` field on a client, accepting a locale string such as `en-US` or `de-DE`. Null or absent defaults to `en-US`.
### Insert dynamic variables into text
Textbox widgets can now include variables that resolve to live client and report details when the report is viewed, shared, or exported to PDF. Insert them from the text toolbar; each renders as a chip in the editor and as real text everywhere the report is shown.
Available variables:
* **Client Name**, **Client First Name**, **Client Website**, **Client Manager**
* **Project Type**, **Project Name**, **Date Range**
* **Account Name**, **Report URL**
Write one intro paragraph — *Here's the* `{{Project Name}}` *update for* `{{Client Name}}` *covering* `{{Date Range}}` — and it fills itself in for every client and every period.
### Ahrefs — Organic Traffic and Rank Tracker
Two new Ahrefs dataviews are available in the report builder:
* **Organic Traffic** — organic keywords, traffic, and traffic value over time
* **Rank Tracker** — tracked keyword positions and movement
Existing Ahrefs widgets are unaffected.
### Two new data sources
* **Moz** — domain SEO authority: Domain Authority, Links to Root Domain, Linking Root Domains, Links to Subdomain, Links to Page, and Outbound Links.
* **Vbout** — email marketing: **Email Campaigns** and **Campaigns** dataviews.
Connect either from the **Data Sources** tab in a client's project, the same way as any other platform.
### More reliable PDF exports
PDF generation and report screenshots now run on a dedicated rendering service with its own browser pool and memory watchdog, separated from the API. Large reports render more consistently and are less likely to time out under load. No change to how you generate a PDF — `pdf_generate` and automation attachments work exactly as before.
### Manage a connection in one place
The data-source connection panel gained a profile manager slide-over. From **Settings → Data sources**, opening a connection now shows its status, the clients linked to it, and an inline credentials editor — so you can re-authorize or repoint a connection without leaving the page.
### Your logo is back on emails
The agency (or client) logo again appears in the header of report and authentication emails, following the same branding source as the rest of the workspace. Emails sent without a configured logo fall back cleanly to the workspace name.
### Go High Level expands beyond Opportunities and Contacts
The Go High Level data source gains five new dataviews, so you can report on far more of a sub-account than deals and contacts:
* **Appointments** and **Appointments Performance** — appointment title, status, start/end time, address, contact, and created/updated dates, plus performance counts for **Total Booked**, **Showed**, **No-Show**, and **Cancelled**.
* **Forms Performance** — form **Submissions** over time, broken down by form.
* **Email Campaigns** and **Email Campaigns Performance** — per-campaign **Opens**, **Clicks**, **Delivered**, **Open Rate**, and **Click-Through Rate**, plus workspace-wide totals for the same.
* **Pipeline Summary** — **Contacts** and **Total Value** by pipeline and stage.
* **Social Planner** — scheduled and published posts with **Platform**, **Status**, **Type**, and publish/display dates.
The existing **Contacts** dataview also picks up **Tags** and **Last Updated** as new fields. Existing Go High Level widgets are unaffected.
### New Instagram metrics
The Instagram data source adds several metrics that Meta has surfaced for Reels and cross-posted content:
* **Account performance** — **Reposts**.
* **Media** — **Reels Skip Rate**, **Reposts**, **Crossposted Views**, **Facebook Views**, and **Link Clicks**.
These appear alongside the existing Instagram metrics in the report builder; existing widgets are unchanged.
### Break WhatConverts leads down by source
WhatConverts gains a **Lead Source** dimension, so you can group and chart leads by where they originated — for example splitting a lead-count table or bar chart across Google Ads, organic, direct, and referral traffic. It sits under the **Leads** dimension group and works with any existing WhatConverts lead metric.
### Date selector on mobile
Shared reports now show the date-range selector on mobile as an icon button that expands to the full picker — it was previously hidden below the small-screen breakpoint. The picker popover is capped to the viewport and scrolls, so presets and the calendar stay reachable on a phone.
### Archive placeholder fixes
Fixed placeholder and empty-state glitches in the Archive view so restoring and deleting archived items reads correctly.
### Widget data source types
The `datasource_type` field on a widget accepts:
`DATASOURCE` · `CALCULATION` · `CUSTOM_DATA` · `CUSTOM_IMPORT` · `GOALS`
### Deprecated metrics are flagged, not renamed
When a vendor retires a metric, it is now marked with a `deprecated` flag in the metric catalog rather than having `(Deprecated)` appended to its name. In the report builder these metrics render in red with an explanatory tooltip, and they remain selectable so existing widgets continue to resolve.
The change removes a long-standing annoyance: the old suffix was copied into a widget's saved metric label at the moment it was picked, so every deprecation round left stale labels behind in saved reports. The flag lives only in the catalog, so it can never go out of date.
Applied across Ahrefs, Facebook Pages, Google Analytics 4, Google Ads, Google Business Profile, Google Local Services Ads, Instagram, Instagram Ads, Keywords, Salesforce, Shopify, Twitter Ads, WooCommerce, and YouTube. No metrics were added or removed.
### Facebook post reach returns data again
Post-level reach was still requesting a field Meta has retired, which returned `0` for every post. It now uses Meta's current unique-viewers field. Affected widgets recover on their next refresh — no reconfiguration needed.
### Sorting and search fixed for preview columns
Table columns that render a rich preview — ad creatives, social posts — carry a structured value rather than plain text. Sorting and searching those columns compared the underlying object instead of its text, so every row looked identical: sorting did nothing and search matched everything or nothing.
These columns now sort and search on the text shown in the cell. Period comparison on the same columns matches rows by the entity's identifier, so each row is compared against its own previous-period value instead of all rows collapsing onto the first.
### Choose how comparison data appears
When a comparison period is active, you can now choose what each row or data point shows. A **Comparison Display** setting under **Display** offers:
* **Previous Value** — the raw figure from the previous period (the default)
* **Percentage Change** — the change against the previous period
* **Both** — the previous value and the percentage change side by side
Available on tables, line, area, and bar charts. Pie, funnel, map, and scorecard widgets don't render side-by-side comparisons, so the setting is hidden for them.
Over the API, this is the `comparison_display` field on a widget, accepting `previous`, `change`, or `both`. Widgets without it continue to show the previous value.
### Period comparison matches the correct category
Comparison figures now line up with the category they belong to for dimensions such as channel, country, page, and campaign — including on widgets that are sorted or limited to a set number of rows. Date-based comparisons are unaffected.
### Metric Settings — rename, format, and set comparison direction
A new **Metric Settings** panel under **Display** gives each metric in a widget its own overrides, in a collapsible row per metric:
* **Name** — a custom label that replaces the metric's default name
* **Format** — how the value renders (numeric, decimal, percentage, currency, time)
* **Comparison Indicator** — whether a rise is good or bad for that metric
The comparison indicator matters for cost-style metrics. On **Higher is better** (the default) a rise shows green and a fall red. On **Lower is better** — cost, CPC, bounce rate — the colours swap, so a falling cost reads as a win. Only the colour changes; the arrow and the sign always follow the actual movement.
Applies to scorecards and the KPI figures on chart widgets.
### Dashboard widget limit applies to duplication
Dashboards are capped at 50 widgets. The cap was enforced when saving widgets but not when duplicating them, so a direct API or MCP call could push a dashboard past the limit. Duplicating beyond the cap now returns:
```json theme={null}
{ "success": false, "error": { "message": "Dashboards are limited to 50 widgets.", "status_code": 400 } }
```
Reports paginate across pages and remain exempt. In the editor, a slot counter on the dashboard canvas now shows how much room is left, shifting from neutral to amber as the limit approaches and to red once it is reached.
### Show or hide the table search box
Table widgets accept a new `show_search` boolean on create and update, exposed in the builder under **Display**. It defaults to enabled, so existing widgets are unchanged.
### Headings can be coloured independently
Themes gain an optional `heading_text` token, edited as **Headings** in the theme editor's colour section. It controls the colour of title widgets. When unset, headings continue to follow the general `text` colour, so existing themes render exactly as before.
### New MCP tools
The MCP server now exposes the rest of the workspace to AI agents. New tool groups:
* **Goals** — `goals_list`, `goals_create`, `goals_update`, `goals_delete`, `goals_duplicate`
* **Calculated metrics** — `calculated_metrics_list`, `_create`, `_update`, `_delete`, `_duplicate`
* **Custom data** — `custom_data_list`, `_get`, `_create`, `_update`, `_delete`, `_duplicate`
* **PDF** — `pdf_generate`, `pdf_status`; **Exports** — `exports_list`, `exports_delete`
* **Email** — `email_send`, senders / templates / sending-domains CRUD, and `email_provider_get`/`_set`
* **API keys** — `api_keys_list`, `api_keys_create`, `api_keys_revoke`
* **Notifications** — `notifications_list`, `notifications_unread_count`, `notifications_mark_read`, and more
* **Archive** — `archive_list`, `archive_counts`, `archive_restore`
* **Activity** — `activity_list`
* **Billing** — `billing_get`, `billing_invoices` (read-only; plan changes stay in-app)
### Enumerated fields are now validated
Request fields with a fixed set of options now reject anything outside that set (a clear `400` instead of silently storing a bad value), and every enumerated field shares one definition across the REST API and the MCP tools so they can't drift. Highlights:
* **Sort & filter params** — `sort_by` / `order` on list endpoints, `source` (`all` / `standard` / `mine`) on templates and assets, and the `datasources` filter (each id must be a real data source).
* **Automations** — `frequency`, `time_format`, and the report `date_text` preset.
* **Projects** — `type`, `orientation`, `paper_size`, `branding_source`, and `auto_refresh_interval_hours` (hourly or daily).
* **Goals & calculated metrics** — `operator`, `goal_type`, and the display `format` (Numeric / Decimal / Percentage / Currency).
* **Media** — upload `content_type` is restricted to image types.
* **Onboarding & company** — client-count band and `country` (from the country list).
* **Timezones** — every `timezone` field is validated as a real IANA zone.
No changes are needed for existing integrations that already send valid values.
### Saved Metrics excluded from the public reference
The internal **Saved Metrics** endpoints are no longer published in the OpenAPI spec (`/openapi.json`) or the API reference. The endpoints continue to work for existing callers; they're simply not part of the documented public surface.
# August 2026
Source: https://docs.oviond.com/changelog/2026-08
Release notes for the Oviond REST API.
### Datasource discovery lives under `/v1/datasources`
The endpoints that describe what Oviond can report on have moved from `/v1/data/*` to `/v1/datasources/*`, alongside the connection endpoints they belong with. `POST /v1/data/query` and `POST /v1/data/resource` are unchanged.
| Before | Now |
| ----------------------------------------- | ---------------------------------------------- |
| `GET /v1/data/datasources` | `GET /v1/datasources` |
| `GET /v1/data/{datasource_id}/describe` | `GET /v1/datasources/{datasource_id}/describe` |
| `POST /v1/data/accounts` | `POST /v1/datasources/accounts` |
| `GET /v1/data/{datasource_id}/metrics` | *Removed* — use `/describe` |
| `GET /v1/data/{datasource_id}/dimensions` | *Removed* — use `/describe` |
`GET /{datasource_id}/describe` replaces the separate `/metrics` and `/dimensions` calls: one request returns a datasource's data views, the advanced settings each view requires, its default view, and its metric and dimension catalogs with the flags that decide what can be combined. Pass `?data_view=ACCOUNT` to scope the response to one view.
**Testing a connection has changed shape as well.** `POST /v1/data/test`, which took a `datasource_id` and a `client_id`, is replaced by `POST /v1/datasources/test`, which takes the connection itself:
```json theme={null}
{ "auth_id": "auth_abc123", "datasource_id": "ga4" }
```
Connection ids come from `GET /v1/datasources/auths`. The result is recorded on the connection, so its status in the app reflects the test.
See [Querying data](/api/concepts/querying-data) for the full walkthrough.
### Goal and calculated-metric queries are now validated
A goal's `query` and a calculated metric's `formula` were accepted without inspection, so either could name a datasource, metric or dimension that doesn't exist and nothing would report a problem until the widget rendered empty.
Both are now validated on create and update, against the same catalog the report builder uses. An unknown identifier is rejected with a `400` naming the field and how to find valid values.
This also fixes **creating a calculated metric over the API or MCP**, which could not succeed: a formula is an array of tokens, and the schema in front of it rejected arrays outright. A formula is now described properly — an array of `METRIC`, `NUMBER` and `OPERATOR` tokens, where a `METRIC` token carries the same query a widget does.
Existing goals and calculated metrics are unaffected; the validation runs on write.
### More fields validated against a fixed set
Several fields that accepted any string now accept only their documented values, so a typo returns a clear `400` instead of being stored and quietly resolving to the wrong thing:
* **Date ranges** — `date_range.text` (the preset) and `date_range.compare` (the comparison mode) on projects, widgets, templates and automations. An unrecognised comparison mode previously produced no comparison at all.
* **Metric display** — a metric's `symbol` (number format) and `summary` (how the total aggregates). Both long and short spellings stay valid, so `percent` and `%`, `currency` and `$` all continue to work.
* **Widget type**, and the **notification channel** on channel routes (`slack`, `discord`).
**One breaking change.** A metric or dimension on a widget is now always an object, never a bare id — on `POST /v1/widgets` and on the MCP widget tools alike:
```json theme={null}
"metrics": [{ "value": "clicks" }],
"dimensions": [{ "value": "DATE" }]
```
Only `value` is required; Oviond fills in the rest from the catalog, and `label` renames the field on the widget. Filters are unchanged. Widgets saved from the app were already in this shape, so only integrations that sent `["clicks"]` need updating.
Beyond that, no changes are needed for integrations already sending valid values.
# Create a client
Source: https://docs.oviond.com/clients/add
Add a new client in a few fields.
From the Clients list, click **Add Client** to open the **Add client** panel. **Client Name** and **Client Website** are required; the rest are optional.
The client's name appears on the client card, in the sidebar, and on report headers. You can rename it later without affecting existing reports.
Enter the client's domain (for example, `oviond.com`). Oviond uses the website to generate a card screenshot and derive a favicon automatically on the server — there's no separate screenshot, logo, or favicon field on this form. The screenshot appears on the card once it finishes generating.
Defaults to `USD`. Sets the default currency used by money widgets in this client's reports.
Defaults to your browser's timezone. Sets the default timezone for dates and scheduled delivery windows in this client's reports.
Defaults to `en-US` (`1,234.56`). Sets the thousands and decimal separators used across this client's reports — for example `1.234,56` for a German locale — independently of the currency. You can change it later under the client's **Settings → General**.
Assign a team member as the manager. Defaults to **No manager**.
Assign the client to one or more [folders](/clients/folders) to organize it. This field accepts multiple folders.
Click **Create Client** to save. Once saved, the client has an empty workspace. Next steps are usually:
1. [Create your first Project](/projects/list) — a Report or Dashboard
2. [Connect a Data Source](/data-sources/connect) from inside the project editor
Logo, favicon, theme, and branding are configured later in the client's **Settings**, not on the Add client form.
# Archive client
Source: https://docs.oviond.com/clients/archive
Soft-delete a client and restore it later from the Archive.
Archiving a client removes it from your active dashboard without permanently destroying anything. The client's projects, pages, widgets, and data connections are preserved and can be restored at any time.
## Archive a client
You can archive a single client from its settings, or several at once from the Clients list.
Open the client and go to its **Settings**, then scroll to the **Danger zone**.
Click **Archive client**. Oviond explains that the client moves to the archive and projects stay attached.
Confirm with **Archive client**. The client moves to the [Archive](/archive/view) and disappears from the active list.
To archive multiple clients at once, select them on the Clients list and click **Archive** in the action bar. See [Bulk archive](/clients/bulk-delete).
## Restore an archived client
Go to **Settings → [Archive](/archive/view)**, find the client, and click **Restore**. The client returns to your active list with all its projects intact.
## Permanent deletion
Archived clients stay in the Archive until you permanently delete them. From the Archive, select a client and click **Delete** to remove it permanently. Permanent deletion is unrecoverable, so export anything you need to keep first.
# Bulk archive
Source: https://docs.oviond.com/clients/bulk-delete
Archive multiple clients at once from your workspace.
Archiving several clients at once is the fastest way to clean up after offboarding — or to clear out test clients you no longer need. Archiving is a soft-delete: clients aren't permanently removed.
Archived clients move to **Settings → Archive** along with their projects, pages, widgets, and data-source connections. You can restore them from the Archive at any time. Permanent deletion only happens when you explicitly delete an item from the Archive — and that is unrecoverable.
Go to your home dashboard.
Click the checkbox that appears when you hover a client card, or **Ctrl/Cmd**-click cards to toggle them. Select every client you want to archive.
With clients selected, click **Archive** in the action bar.
In the **Archive Clients** dialog, review the count and click **Archive**. The selected clients move to the Archive.
## Restore archived clients
Go to **Settings → [Archive](/archive/view)**, select the clients you just archived, and click **Restore**. Their projects and data connections come back intact.
# Group clients
Source: https://docs.oviond.com/clients/folders
Group clients into folders to keep a large client list navigable.
A **folder** is an organizational bucket that groups clients together. Folders appear in the **Folders** popover on the Clients page so you can filter the list to a subset of clients.
Common patterns: grouping by industry (**E-commerce**, **Healthcare**), region (**North America**, **EMEA**), or team (**Account Manager — Jane**).
Folders are purely organizational — they don't affect permissions, billing, or reports. A client can belong to multiple folders when you assign them from the **Add client** panel or **Client Settings**.
## Create a folder
On the Clients page, open the **Folders** popover and click **Add Folder**.
Enter a **Name** (for example, **Retail Clients**).
Click **Create**. The folder appears in the **Folders** popover, ready to receive clients.
## Assign clients to a folder
There are two ways to assign clients:
* **From the Clients list** — select one or more clients to reveal the action bar, click **Add to folder**, choose a folder in the **Move to Folder** dialog, and click **Confirm**. This replaces each selected client's folder assignment with the one you pick.
* **From a client's settings** — the **Client folder** field is a multi-select, so a single client can belong to several folders at once.
## Rename or delete a folder
In the **Folders** popover, hover a folder row to reveal the **Rename** and **Delete** icons.
* **Rename** opens the **Edit Folder** dialog; change the name and click **Save**.
* **Delete** removes the folder. Clients in that folder are **not** deleted — they're simply unassigned from it.
# List clients
Source: https://docs.oviond.com/clients/list
View, search, and filter every client in your workspace.
The **Clients** page is your home dashboard — every client you've created appears here. The page heading shows your slot usage, for example **You're using 8 of 25 client slots.**
Each client card shows the website **screenshot**, a **logo** chip (favicon, logo, or initials), the client **name**, and the client's **domain**. While a screenshot is still generating, the list polls and the image appears automatically once it's ready.
## Views
* **Search** — type in the **Search clients** box to match by name.
* **Folders** — open the **Folders** popover to filter the list to a single folder, or choose **All Clients** to clear the filter. See [Group clients](/clients/folders).
* **Sort** — open the **Sort** popover. Options are **Last Updated**, **Name (A-Z)**, **Name (Z-A)**, **Created (Newest)**, and **Created (Oldest)**.
## Client card actions
* **Open** — click the card to enter the client's workspace (its Projects). Hold **Ctrl/Cmd** and click to toggle selection instead.
* **Refresh screenshot** — hover the card and click the refresh icon in the top-right to regenerate the website screenshot.
Cards don't show a project count or a folder badge, and there is no per-card three-dot menu. Rename, move to folder, and archive are available from the action bar after you select one or more clients (see below).
## Bulk actions
Select one or more clients (click the checkbox that appears on hover, or **Ctrl/Cmd**-click a card) to reveal the action bar. It shows the selected count and these actions:
* **Add to folder** — move the selected clients to a folder. See [Group clients](/clients/folders).
* **Edit** — rename the client (available when exactly one is selected).
* **Open** — go to the client (available when exactly one is selected).
* **Archive** — archive the selected clients; see [Archive client](/clients/archive).
The Clients list respects your access scope. Team members with restricted access only see the clients they're authorized to view.
# Branding
Source: https://docs.oviond.com/company/branding
Upload the logos your projects, reports, and shared links use.
Oviond branding is built around two logos: a **square logo** and a **full logo**. You can set them at two levels — for your whole account (agency branding) and for an individual client (branding defaults) — and choose which set each client uses.
## Logo types
Each branding section uploads two images:
* **Square logo** — a compact, square mark used where space is tight. Stored in the `favicon_url` field.
* **Full logo** — your complete, wider logo. Stored in the `logo_url` field.
A PNG or SVG with a transparent background works best for both.
## Agency branding
Agency logos apply across the whole account. Set them from **Settings → Company**, in the **Agency branding** section. Editing requires **Admin access**.
Go to **Settings → Company**.
In the **Agency branding** section, upload your **square logo** and your **full logo**.
Save to apply the agency logos. Any client set to use agency logos will pick these up.
## Client branding defaults
Each client has its own **Branding defaults**, found in that client's settings. Here you choose the **Logo source** for the client's projects, reports, and shared links.
The **Logo source** toggle has two options:
* **Agency logos** — the client uses the account-wide logos you set on the Company page. This is the default. When selected, the client's own logos are read-only, and Oviond shows a link to edit the agency logos in **Company** settings.
* **Client logos** — the client uses its own **square logo** and **full logo**, which you upload here.
Go to the client and open its settings, then find the **Branding defaults** section.
Select **Agency logos** to inherit the account-wide logos, or **Client logos** to use logos specific to this client.
If you chose **Client logos**, upload the **square logo** and **full logo** for this client.
Save to apply the logo settings for this client.
Changing the logo assets requires permission to edit shared assets, and saving the source requires permission to edit the client.
# Company details
Source: https://docs.oviond.com/company/overview
Set your company information and account-level branding.
The **Company details** page lives at **Settings → Company**. It holds the account-level information about your company, along with the logos your projects can use. Editing this page requires **Admin access**.
The page has two sections: **Company information** and **Agency branding**.
## Company information
These fields describe your company across the account. Edit them and then save.
| Field | Description |
| -------------------- | -------------------------------------------------------- |
| **Company name** | Your company's name. Required. |
| **Website address** | Your company website URL. |
| **City** | The city your company is based in. |
| **State** | The state or region. |
| **Country** | The country, chosen from a list. |
| **Phone number** | A contact phone number. |
| **Timezone** | Used as the starting reporting timezone for new clients. |
| **Default currency** | Used as the starting currency for new clients. |
## Agency branding
The **Agency branding** section lets you upload logos that your projects can use instead of client-specific branding. See [Branding](/company/branding) for details on how the logos work and how client-level branding overrides them.
# Delete custom data
Source: https://docs.oviond.com/custom-data/delete
Permanently remove an uploaded dataset.
Deleting a dataset removes its rows and metadata. Widgets that referenced the dataset no longer resolve their data until you re-wire them to a different source.
Deletion is permanent — custom data is hard-deleted, with no Archive recovery. Keep a copy of the original file if you might need it later.
From the **Data Query** widget's **Custom Data** source, click **Manage** next to the **Dataset** label.
Select the dataset and choose **Delete**. Confirm when prompted.
## API
`DELETE /v1/custom-data/{id}` permanently removes the dataset. It returns `404` if the dataset doesn't exist in your account.
# Duplicate custom data
Source: https://docs.oviond.com/custom-data/duplicate
Copy a dataset under a new name.
Duplicating clones a dataset — its rows, columns, and metadata — under a new name. It's useful for:
* Creating a variant before applying different transformations downstream
* Forking a dataset before a risky edit, so you can compare side by side
* Spinning up test data from a verified dataset
From the **Data Query** widget's **Custom Data** source, click **Manage** next to the **Dataset** label.
Select the dataset and choose **Duplicate**.
Enter a name for the new dataset. The copy is created with that name.
Widgets continue pointing at the original dataset — duplicating doesn't re-wire anything. To point a widget at the copy, open the widget and select the new dataset.
## API
`POST /v1/custom-data/{id}/duplicate` clones the source dataset. Send `new_name` for the copy. The response returns the new dataset `id`.
# List custom data
Source: https://docs.oviond.com/custom-data/list
Every CSV or JSON dataset uploaded to your account.
The **Manage Custom Data** slide-over lists every dataset you've uploaded — its name, row count, column count, file size, and upload date. Open it from the **Manage** button next to the **Dataset** label in the **Data Query** widget's **Custom Data** source.
## What's on a row
| Field | Description |
| ------------ | ------------------------------------------------- |
| `name` | The label you gave the dataset when you saved it. |
| `columns` | The columns parsed from the file header. |
| `row_count` | Number of data rows. |
| `file_size` | Size of the uploaded file. |
| `file_name` | The original file name, if one was provided. |
| `created_at` | When the dataset was first saved. |
| `updated_at` | When the dataset was last changed. |
## Quick actions
From the **Manage Custom Data** slide-over you can:
* **Edit** — change the data or rename the dataset. See [Update custom data](/custom-data/update).
* **Duplicate** — copy the dataset under a new name. See [Duplicate custom data](/custom-data/duplicate).
* **Delete** — remove the dataset. See [Delete custom data](/custom-data/delete).
## API
`GET /v1/custom-data` returns a lightweight list of your datasets, newest first. The list response omits `raw_data` because it can be large — fetch a single dataset with `GET /v1/custom-data/{id}` to include `raw_data`.
# Update custom data
Source: https://docs.oviond.com/custom-data/update
Edit a dataset's rows, columns, or name.
Updating changes a dataset in place. The dataset's `id` and widget bindings stay intact — every widget that references the dataset re-renders with the new data.
From the **Data Query** widget's **Custom Data** source, click **Manage** next to the **Dataset** label.
Select the dataset and edit its rows in the grid, re-upload a file, or change its name.
Widgets using this dataset pick up the changes on the next render.
If you change the columns, widgets configured against the old column names will need to be re-mapped.
## API
`PUT /v1/custom-data/{id}` applies a partial update — send only the fields you want to change. Accepted fields are `name`, `file_name`, `raw_data`, `columns`, and `file_size`. When you send `raw_data`, Oviond recalculates `row_count` (and rejects payloads over 10,000 rows). To rename a dataset, send just `name`.
# Upload custom data
Source: https://docs.oviond.com/custom-data/upload
Upload a CSV or JSON dataset to report on data that doesn't live in a connected data source.
**Custom data** lets you upload your own CSV or JSON files and use them alongside data from connected data sources. It's useful for:
* Offline sales, lead lists, or CRM exports
* Revenue forecasts and targets
* Any KPI that lives outside the data sources we support natively
## Where it lives
Custom data isn't a standalone page in the sidebar. You reach it from the **Data Query** widget while editing a project:
In the project editor, add (or select) a **Data Query** widget to open the query builder in the left panel.
In the widget's data-source dropdown, choose **Custom Data**. The picker also lists your connected data sources, **Static Value**, **Calculated Metrics**, and **Goals**.
Pick an existing dataset from the **Dataset** dropdown, or use the **Upload New File** drop-zone below the **OR** divider. You can drag a file in or click to open the file picker.
After Oviond parses the file, enter a **Dataset Name** and click **Save Dataset**. Oviond parses the headers into columns and stores the rows.
You can also start from a blank grid with **Start from Blank**, or use the **Manage** button next to the **Dataset** label to open the **Manage Custom Data** slide-over, where you can edit, rename, duplicate, and delete datasets across your account.
## Supported files
Uploads accept `.csv` and `.json` files, up to **5 MB** each.
## How a dataset is used
Once you select a dataset, its `custom_data_id` is stored on the widget query, and you map the dataset's columns to the widget's metrics and dimensions. The widget then queries the dataset alongside your connected data sources.
Custom data is account-level — any client's project can reference any dataset you've uploaded. A dataset can hold at most **10,000 rows**.
## Custom data vs a data source
* **Data sources** (Google Ads, Facebook, etc.) — live data pulled from a connected marketing platform.
* **Custom data** — static or periodically refreshed data you upload yourself.
## API
`POST /v1/custom-data` creates a dataset. Send `name`, `file_name`, `raw_data` (an array of row objects, max 10,000), `columns`, and `file_size`. The response returns the new dataset `id`.
# Add domain
Source: https://docs.oviond.com/custom-domains/add
Register a custom domain so shared reports load under your own URL.
A custom domain replaces `app.oviond.com` with a URL you own on shared report links — for example, `reports.youragency.com`. When you add a domain, Oviond detects its DNS host and shows you the exact records to add.
Go to **Settings → Custom domains** (`/settings/custom-domains`).
Click **Add domain**, then enter the subdomain you want to use — for example, `reports.youragency.com`. Don't include `https://`.
Oviond looks up the domain's nameservers and identifies the DNS host (Cloudflare, GoDaddy, Namecheap, AWS Route 53, Google Domains, or Squarespace; **Other** if it can't be matched). This is read-only — it just tells you where to add the records.
Oviond shows a `CNAME` record and, in some cases, a `TXT` ownership record. Add them exactly as shown in your DNS provider's admin panel, then click **I added the records**.
Click **Verify domain** to check the records. See [Verify domain](/custom-domains/verify) for the status flow.
## DNS records
Oviond registers the domain with Vercel and returns the records you need to add:
| Record | Purpose |
| ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CNAME` | Points your subdomain at Vercel (`cname.vercel-dns.com`) so it can serve your reports and provision SSL. |
| `TXT` | An ownership challenge (`_vercel`), returned only when the domain is already attached to another Vercel account. It can be removed once the domain is verified. |
You always add DNS records yourself in your provider's admin. Oviond detects which provider you use but never writes records on your behalf.
On **Cloudflare**, set the record's proxy status to **DNS only** (grey cloud). With the proxy enabled, Vercel can't issue the SSL certificate.
SSL is provisioned automatically by Vercel once the domain verifies. You don't need to set up a certificate manually.
Your account's first custom domain is set as the default automatically, so shared URLs have a domain to resolve against. The number of custom domains you can add depends on your plan.
# Delete domain
Source: https://docs.oviond.com/custom-domains/delete
Remove a custom domain from your account.
Deleting a domain stops it from serving reports and removes it from Vercel on Oviond's side. Shared links that used the custom domain fall back to the default `oviond.com` domain.
Go to **Settings → Custom domains** (`/settings/custom-domains`).
Click **Remove domain** on the domain, then confirm with **Remove domain** in the dialog (or **Keep domain** to cancel).
Optionally remove the `CNAME` (and any `TXT`) records in your DNS provider — Oviond doesn't touch your DNS admin.
Oviond removes the domain from Vercel and deletes its stored DNS records. If the deleted domain was the account default, set another active domain as the default so shared URLs continue to resolve under a custom domain.
# List domains
Source: https://docs.oviond.com/custom-domains/list
Every custom domain registered to your Oviond account.
By default, shared report links use an `oviond.com` subdomain. A custom domain replaces that with a URL you own — for example, `reports.youragency.com`. Clients see only your domain.
You manage custom domains under **Settings → Custom domains** (`/settings/custom-domains`). The **Connected domains** table lists every domain on your account with its current status, its DNS records, and which domain is set as the default.
## Before you start
To add a custom domain, you need:
* **A domain you own** — typically a subdomain of your main domain (recommended), such as `reports.youragency.com`.
* **Access to your domain's DNS settings** — you add the records through your domain registrar or DNS provider (for example, Cloudflare, GoDaddy, or Namecheap).
DNS changes can take anywhere from a minute to several hours to propagate, depending on your provider. Plan ahead if you have a deadline for switching clients to the new domain.
## What the list shows
For each domain, the list shows:
| Column | Description |
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Domain** | The subdomain you registered. |
| **Status** | `pending`, `verifying`, `active`, or `failed`, shown as **Active**, **Verification failed**, or **Action required**. See [Verify domain](/custom-domains/verify). |
| **Provider** | The detected DNS host (Cloudflare, GoDaddy, Namecheap, AWS Route 53, Google Domains, Squarespace, or **Other**). |
| **Default** | Whether this domain is the account default used to build shared URLs. |
| **DNS records** | The `CNAME` (and any `TXT` ownership record) you need to add. |
The page also shows how many domains you've used against your plan's limit.
## Add and verify
To register a new domain, see [Add domain](/custom-domains/add). To confirm DNS records and activate the domain, see [Verify domain](/custom-domains/verify).
## After verification
Once a domain is **Active**:
* Shared report links can use your custom domain.
* SSL is provisioned automatically by Vercel — you don't manage a certificate.
* Clients who open a shared link see your domain in the browser address bar.
To remove a domain, see [Delete domain](/custom-domains/delete).
# Verify domain
Source: https://docs.oviond.com/custom-domains/verify
Confirm DNS records are live so your custom domain activates.
After you [add a domain](/custom-domains/add), Oviond reconciles its status against Vercel. Once the records resolve and SSL is provisioned, the domain becomes **Active** and shared links start rendering under it.
## Statuses
A domain moves through these states (`pending`, `verifying`, `active`, `failed`):
| Status | Meaning |
| ----------- | ------------------------------------------------------------------- |
| `pending` | Just added. The DNS records haven't been detected yet. |
| `verifying` | Records are visible but SSL is still provisioning. |
| `active` | Records and SSL are live — the domain is fully functional. |
| `failed` | Verification didn't complete. Records are missing or misconfigured. |
In the list, these collapse into a single badge: **Active** (green), **Verification failed** (red), or **Action required** (amber, for `pending` and `verifying`).
## Trigger a re-check
Go to **Settings → Custom domains** (`/settings/custom-domains`).
Click **Show DNS records** on the domain to expand the records to add.
Click **Verify domain**. Oviond re-queries Vercel and updates the status. It also keeps the status in sync automatically via a webhook when Vercel confirms ownership or provisions the certificate.
If a domain stays in **Pending** for a while, double-check that the `CNAME` (and any `TXT` ownership record) match exactly what Oviond showed when you added the domain. DNS changes can take anywhere from a minute to several hours to propagate, depending on your provider.
## Set a default domain
The default custom domain is used to build shared report URLs when a client has no domain override of its own. Only an **Active** domain can be set as the default. Your first domain becomes the default automatically; on any other active domain, click **Set as default** (the star) from **Settings → Custom domains**.
# Connect
Source: https://docs.oviond.com/data-sources/connect
Authorize Oviond to pull data from Google Ads, Facebook, and 60+ other platforms.
Connecting a marketing platform to a client is a two-step process that happens inside a client's project editor. First, you authorize the platform — through OAuth or an API key — which creates a reusable **connection** (an auth profile) in your workspace. Second, you link a specific account, property, or page from that connection to the client. Once linked, that data source is available when you build widgets for that client.
Oviond requests read-only access to the platforms you connect. Oviond cannot make changes to your campaigns, budgets, or account settings.
## Where data sources live
You manage data sources in two places:
* **A project's Data Sources tab** — open a client's project, then click **Data Sources** in the editor sidebar. This is where you connect platforms and link them to the client. It's the primary place to wire up data.
* **Settings → Data sources** (`/settings/data-sources`) — a workspace-wide table of every connection. Use it to rename, refresh, or delete connections and to see which clients use each one. You cannot create new connections here; the empty state points you back to a project editor: *Connect data sources from a client project editor.*
## Step 1: Connect the platform
Open a client's project and click **Data Sources** in the editor sidebar.
Use the **Search data sources...** box to find the platform you want (for example, Google Ads or Facebook Ads).
Click **Connect** next to the platform. Oviond shows a **Profile Name** field so you can label this connection (for example, *Acme — Main Account*). A default name like *Default Google Analytics Connection* is prefilled.
For an OAuth platform, click **Connect** to open the authorization popup. Log in with the account that has access to this client's data, review the read-only permissions, and authorize. For an API-key platform, enter the credentials in the fields shown and click **Next** or **Save**.
After authorization, Oviond stores the connection. If the platform exposes multiple accounts, Oviond advances to account selection (Step 2). Otherwise the connection is saved and a * connected* confirmation appears.
A connection is reusable. If you already have a connection for this platform (for example, you authorized Google Ads for another client), you don't need to authorize again — select the existing profile and skip to linking in Step 2.
## Step 2: Link an account to the client
After connecting, you pick which specific account, property, or page maps to this client.
Under **Select Profile**, choose the connection to use. If you have several connections for the same platform, pick the one with access to this client's account. The connection already linked to this client sorts to the top.
Click **Link** on the connection. Oviond loads the accounts available under that connection.
Under **Select Account**, choose the specific account, property, or page for this client. Some platforms use a two-step pick — for example, Google Analytics 4 (analytics account, then property), Google Business Profile (account, then one or more locations), and Meta/Instagram Ads (Business Manager, then ad account). Use **Search...** to narrow the list.
Click **Save**. Oviond links the account to the client and shows a * linked* confirmation. The data source is now available in this client's widgets.
## Check the connection status
Each connection shows a status badge so you can tell at a glance whether its token is healthy:
* **Token Valid** — the connection is authorized and data should flow.
* **Token Expired** — the token has expired or been revoked; refresh it.
Status is set automatically by a daily auth-test check and by the OAuth token refresher. When a token expires, widgets that depend on the connection stop returning data.
## Refresh an expired connection
OAuth tokens expire or are revoked when you change a password, revoke app access inside the platform, or the platform's token policy ends the session. When that happens, the connection shows **Token Expired**.
Open the project's **Data Sources** tab (or **Settings → Data sources**) and look for a connection showing **Token Expired**.
Click **Refresh** (in the project tab) or **Refresh token** (in Settings). Oviond reopens the OAuth popup.
Complete the OAuth flow again with the same account. Oviond updates the connection with a fresh token, and the badge returns to **Token Valid**.
Refresh is shown only for OAuth platforms. API-key connections are updated by clicking **Edit** and re-entering credentials. Refreshing a connection restores every client and widget that uses it — you don't re-link each client.
## Common connection issues
If you have multiple accounts on a platform (for example, both a personal and a work Google account), the OAuth popup may default to the wrong one. To fix this:
1. Delete the incorrect connection from **Settings → Data sources** (**Delete profile**).
2. Start **Connect** again in the project's **Data Sources** tab.
3. In the OAuth window, use the account switcher or **Use a different account** and log in with the correct credentials.
Oviond requires read access to the account you connect. If authorization succeeds but no data loads, confirm the account you used has at least read-level access in the platform. For Google Ads the account needs **Read only** access or higher; for Facebook Ads the user needs the **Analyst** role or higher on the ad account.
If the account you expect doesn't appear after connecting:
* Confirm the account is accessible under the login you used (for manager accounts, check the sub-account is linked to your manager account).
* Use **Refresh** to re-authorize the connection.
* For a Google Ads manager account, allow a few minutes for the full account hierarchy to load. If accounts fail to load, Oviond shows *Unable to load accounts for .*
A **Token Valid** badge confirms the authorization works, but a widget can still be empty if:
* The widget's date range covers a period with no activity.
* The selected campaign, property, or segment has no data for that period.
* The account was created recently and hasn't accumulated data yet.
Check the widget's date range and data source settings before troubleshooting the connection.
Some browsers block popups by default. If clicking **Connect** does nothing, allow popups for your Oviond domain and try again.
# Delete Connection
Source: https://docs.oviond.com/data-sources/delete
Remove a data source connection from your workspace.
Deleting a connection removes it from your workspace and unlinks it from every client that used it. Widgets that referenced it stop displaying data until they're re-wired.
Deleting a connection may affect widgets that use it. If the connection feeds active reports, those widgets break on the next render. To remove it from one client only, **Unlink** it from that client's **Data Sources** tab instead — see [Link to Client](/data-sources/link).
Go to **Settings → Data sources** (`/settings/data-sources`).
Find the connection in the table and click **Delete profile** on its row.
Type `DELETE` in the confirmation field, then click **Delete profile**.
To be thorough, also remove Oviond from the authorized-apps list in the source platform (for example, Google Account → Third-party apps).
Deleting and renaming connections requires account-management permissions. Connecting and unlinking data sources happens in a client's project editor.
# Link to Client
Source: https://docs.oviond.com/data-sources/link
Attach a connected data source to a specific client.
A connection lives at the **workspace** level — one credential can be linked to many clients. Linking picks the account, property, or page for a client and makes that data source selectable in the client's widgets.
Open the client's project and click **Data Sources** in the editor sidebar.
Under **Select Profile**, pick a connection you've already made (or click **Connect** to make a new one — see [Connect](/data-sources/connect)).
Click **Link** on the connection. Oviond loads the available accounts.
Under **Select Account**, choose which ad account, property, or page maps to this client. See [Profiles](/data-sources/profiles).
Click **Save**. Every widget you build for this client can now pull from the linked data source.
## Unlink
On the client's **Data Sources** tab, click **Unlink** next to a linked profile. The connection stays at the workspace level — it's just no longer available in this client. Widgets in this client's project that referenced it stop returning data.
Unlink takes effect immediately and isn't confirmed by a dialog. The connection remains in **Settings → Data sources** and can be linked to the same or a different client at any time.
# List Data Sources
Source: https://docs.oviond.com/data-sources/list
Every marketing platform connected to your Oviond workspace.
Data sources are connections between Oviond and your clients' marketing platforms. Once connected, Oviond pulls live data from those platforms into your reports and dashboards — no manual exports or copy-pasting required. Each data source is linked on a per-client basis, so the data in a report always belongs to the client that report is built for.
## Supported data sources
Oviond supports 60+ marketing platforms across categories such as paid search, paid social, analytics, SEO, email marketing, and e-commerce/CRM.
| Category | Examples |
| -------------------- | ------------------------------------------------------------------------------------------------- |
| **Paid Search** | Google Ads, Microsoft Ads, ChatGPT Ads |
| **Paid Social** | Facebook Ads, Instagram Ads, LinkedIn Ads, TikTok Ads, Pinterest Ads, Snapchat Ads, Twitter/X Ads |
| **Analytics** | Google Analytics 4, Matomo, Piwik PRO, Plausible |
| **SEO** | Google Search Console, Semrush, Ahrefs, Moz, SE Ranking, Serpstat |
| **Email Marketing** | Mailchimp, Klaviyo, Campaign Monitor, ActiveCampaign, Vbout |
| **E-commerce & CRM** | Shopify, WooCommerce, HubSpot, Salesforce, Pipedrive, Stripe |
The full list of available data sources appears when you open the **Data Sources** tab in a client's project editor and search. New platforms are added regularly.
## How data sources work
When you connect a data source, Oviond guides you through an OAuth flow — or, for some platforms, an API-key form — where you authorize Oviond to read your data. Oviond stores the result as a reusable **connection** (an auth profile).
After connecting, you link a specific account, property, or page (for example, a particular Google Ads account or GA4 property) to a client. That linked data source then becomes available when you build widgets for that client.
### Connections (auth profiles)
A connection represents one authorized credential for a platform — typically tied to one login. If you manage multiple clients' accounts through a single login (such as a Google Ads manager account), one connection can cover all of those sub-accounts.
You can reuse the same connection across multiple clients. For example, if your workspace has a single Google Ads manager account containing sub-accounts for 10 clients, you authorize Google Ads once and then link each client to their respective sub-account — without re-authenticating.
## Listing your connections
To see every connection across your workspace, go to **Settings → Data sources** (`/settings/data-sources`). The table lists each connected profile with its platform, profile name, token **Status** (**Token valid** or **Token expired**), the number of clients using it, and the date it was connected. Use the toolbar to search by name or filter by status and platform.
To see the data sources linked to one client, open that client's project and click the **Data Sources** tab in the editor sidebar. This shows only the connections relevant to that client, with the linked profile sorted first.
## Checking connection status
Oviond checks token health automatically with a daily auth-test. You don't run a manual test — each connection displays a **Token valid** or **Token expired** badge. When a token expires, click **Refresh** (project tab) or **Refresh token** (Settings) to re-authorize. See [Test Connection](/data-sources/test) for details.
## Unlinking and deleting
**Unlinking** removes a data source from a specific client but keeps the connection available for reuse. **Deleting** a connection removes it from your workspace entirely and disconnects every client that used it.
### Unlink a data source from a client
1. Open the client's project and go to the **Data Sources** tab.
2. Find the linked data source.
3. Click **Unlink**.
The connection remains available and can be linked to the same or a different client at any time.
### Delete a connection
Deleting a connection removes it permanently and may affect widgets that use it. Widgets that relied on it stop displaying data. This cannot be undone.
1. Go to **Settings → Data sources**.
2. Find the connection and click **Delete profile**.
3. Type `DELETE` to confirm, then click **Delete profile**.
## Next steps
Step-by-step guide to connecting a platform and linking it to a client.
Combine metrics across data sources into custom KPIs.
# Profiles
Source: https://docs.oviond.com/data-sources/profiles
Pick which ad account, property, or page to report on for each connected data source.
A **profile** is one connection to a platform, named and reusable. When you link a data source to a client, you pick the specific account, property, or page that profile reports on — that's how you tell Oviond *which* numbers to pull for that client.
## Why the account selection matters
A single connection can see every account the authorizing login has access to. Linking resolves that ambiguity by anchoring each client to one account, property, or page:
* **Google Ads** — a Customer ID per ad account
* **Google Analytics 4** — a Property per site
* **Facebook Ads** — an Ad Account per business
* **Google Business Profile** — one or more Locations per account
## Link a profile to a client
Open the client's project and click **Data Sources** in the editor sidebar.
Under **Select Profile**, pick the connection to use, then click **Link**.
Under **Select Account**, choose the account, property, or page for this client. Some platforms (GA4, Google Business Profile, Meta/Instagram Ads) use a two-step pick. Click **Save**.
Widgets configured with this data source now pull from the account you selected. To change the account later, click **Edit** on the profile and re-select.
## Rename a profile
Give each connection a clear label (for example, *Acme — Main Site*) so your team picks the right one when linking.
* You set the name when you first connect, in the **Profile Name** field.
* To rename an existing connection, go to **Settings → Data sources**, click **Rename profile** on the row, enter a **New name**, and click **Save changes**. The rename applies everywhere the connection is used.
A profile name can't contain `.` or `$` characters.
## Manage a profile
From **Settings → Data sources**, open a connection to bring up its profile manager. In one panel you can review the profile's **status**, see the **clients linked** to it, and edit its **credentials** inline — so you can re-authorize an expired token or repoint a connection without leaving the page.
# Test Connection
Source: https://docs.oviond.com/data-sources/test
Check whether a connection's authorization is still valid.
Oviond checks the health of each connection's token automatically. A daily auth-test pings each platform with the stored credentials, and the OAuth refresher updates the status when a token refresh fails. You don't run a manual test in the app — instead, each connection shows a status badge:
* **Token Valid** — the token is authorized and data should flow.
* **Token Expired** — the token has expired or been revoked; refresh it.
You'll see this badge on the **Data Sources** tab in a client's project and in **Settings → Data sources** (where it appears as **Token valid** / **Token expired**, and you can filter the table by status).
## Where to look
* A widget shows a data error and you want to know whether re-authorization is needed.
* You just refreshed a connection and want to confirm it's working.
* You're debugging a report that depends on a specific connection.
In each case, open the connection in the **Data Sources** tab or in **Settings → Data sources** and read its status badge.
## If a connection shows Token Expired
1. Click **Refresh** (project tab) or **Refresh token** (Settings) to start a fresh OAuth flow. Your account selection is preserved.
2. Complete the OAuth flow with the same login. The badge returns to **Token Valid**.
3. If refresh doesn't resolve it, the authorizing user's access in the source platform may have been revoked — check the platform's admin for the token's status.
The API exposes a `POST /v1/datasources/test` endpoint that takes an `auth_id` and a `datasource_id` and returns `connected` plus a `message`. The result is recorded on the connection, so its status in the app reflects the test. See the API reference for details.
# Defaults
Source: https://docs.oviond.com/email-settings/defaults
How Oviond picks the default sender and email template.
Oviond doesn't have a separate **Defaults** page. Instead, "default" is a per-row setting you mark with a **star** in **Settings → Email settings** (`/settings/email-settings`): a default **sender** and a default **template**. Oviond uses these whenever a send doesn't specify a sender or template of its own.
## Default sender
In the **Sender addresses** section, one sender is the default, shown with a star. Click **Set default sender** on any saved sender to make it the default. Your first saved sender becomes the default automatically, and if you delete the default Oviond promotes the next-oldest saved sender. The built-in Oviond sender can't be your default.
See [Senders](/email-settings/senders) for the full sender setup.
## Default template
In the **Email templates** section, one template is the default, shown with a star and a **Default** badge. Click **Set template as default** on any template to change it. Each account is seeded with a built-in default template.
A template defines:
| Field | Notes |
| ------------- | ------------------------------------------------------------------- |
| `name` | Internal template name. |
| `subject` | Subject line. Supports inserted variables (type `/` to insert one). |
| `message` | Body copy, also variable-aware. |
| `button_text` | Optional CTA button label. |
| `button_top` | Whether the button appears above the message. |
There are no standalone "default subject", "default from name", or "default from email" fields — those values come from the default **template** and default **sender** described above.
# Email domains
Source: https://docs.oviond.com/email-settings/domains
Verify a sending domain so Oviond can send mail from your own addresses.
A **sending domain** is a domain authorized to send mail through Oviond's managed provider. Verifying it means adding DNS records so recipient providers trust messages from your domain. You can register one sending domain per account from **Settings → Email settings** (`/settings/email-settings`).
Lifetime plans are SMTP-only and can't register a sending domain — they send from their own [SMTP server](/email-settings/smtp) instead.
## Add a sending domain
Go to **Settings → Email settings** and start adding a sender, then choose **Sending domain**.
In **Add sending domain**, enter the domain — for example, `mail.youragency.com` — and click **Add domain**.
Oviond shows **DKIM and SPF records** to add to your DNS provider, plus a recommended **DMARC** record. Add them exactly as shown.
Click **Verify domain**. Oviond checks the live status: if the records resolve, the domain is marked verified; otherwise verification is started and the status updates on the next check or in the background.
## DNS records
The records table shows **Type**, **Host/Name**, **Value**, **TTL**, **Priority**, and **Status** for each record. A separate **DMARC** card provides a recommended `TXT` record at `_dmarc`. Each value can be copied directly from the table.
## Status
| Status | Meaning |
| --------------- | ------------------------------------------------------------------------------------- |
| **Not started** | Domain added but verification hasn't run. |
| **Pending** | Records aren't fully visible yet. |
| **Verified** | All required records resolve — senders on this domain can send. |
| **Failed** | Verification didn't complete. Re-check the records and click **Verify domain** again. |
When the domain verifies, Oviond switches the account's active provider to the sending domain so your verified senders are used.
## Remove a domain
Removing the sending domain deletes it from Oviond and the provider. If it was the active provider, Oviond falls back to the Oviond default. Removing it also invalidates any [senders](/email-settings/senders) on that domain — switch automations to a different sender first.
# Email logs
Source: https://docs.oviond.com/email-settings/logs
Every email Oviond has sent — status, events, and any errors.
The **Email activity** section of **Settings → Email settings** (`/settings/email-settings`) shows the emails Oviond has sent for your account, with their current status. Activity is sourced from the email provider, so a sending domain or SMTP server must be configured for rows to appear.
## Columns
| Column | Description |
| ------------- | ------------------------------------------------------------------------------------------------------------ |
| **Recipient** | The to-address that received the email. |
| **Subject** | The subject line as rendered. |
| **Status** | The latest delivery state — `sent`, `delivered`, `opened`, `clicked`, `bounced`, `complained`, or `delayed`. |
| **Sent** | When the email was sent. |
Click a row to open **Email details**, which shows the from-address, subject, recipients, a timeline of events (sent, delivered, bounced, clicked) with timestamps, any error, and the rendered HTML body.
## Events
Provider webhook events update each row as they arrive:
* **Delivered** — accepted by the recipient's provider.
* **Bounced** — the recipient's provider rejected the message (a hard bounce means an invalid address). Bounced and complained recipients are added to your suppression list and skipped on future sends.
* **Delayed** — temporary failure that usually retries.
* **Opened** / **Clicked** — engagement tracked by the provider.
## Filters
* **Search** — find activity by recipient or subject.
* **Status** — show only a specific status.
* **Date range** — last 24 hours, 3, 7, 14, or 30 days, or all time.
Results are paginated.
# Senders
Source: https://docs.oviond.com/email-settings/senders
Add the from-addresses Oviond uses for outgoing email.
A **sender** is a from-address (for example, `reports@youragency.com`) that Oviond sends email from. Each sender is tied to a transport — your verified **sending domain** or your own **SMTP server**. Manage senders in the **Sender addresses** section of **Settings → Email settings** (`/settings/email-settings`).
The built-in Oviond sender (`noreply@oviond.com`) is always available and is shown read-only. It isn't available on lifetime plans, which must send from their own SMTP server.
## Add a sender
Go to **Settings → Email settings** and find the **Sender addresses** section.
Click **Add Email Address**, then choose the source — **Sending domain** (an address on your verified domain) or **SMTP server** (your own server).
Set the **from name** and **from email**. For a sending-domain sender, the `from_email` must be on your verified domain. You can also set an optional **nickname**, **reply-to**, and a physical **address**, **city**, and **country**.
The sender becomes selectable when sending email. Your first saved sender is set as the default automatically.
## Fields
| Field | Notes |
| ---------------------------- | ------------------------------------------------------------------------------- |
| `source` | `resend` (sending domain) or `smtp` — the transport the sender uses. |
| `from_name` | The display name recipients see. |
| `from_email` | The from-address. For a sending-domain sender, must be on your verified domain. |
| `nickname` | Optional internal label. |
| `reply_to` | Optional reply-to address. |
| `address`, `city`, `country` | Optional physical address. |
## Default sender
One sender per account is the default, marked with a **star**. Click **Set default sender** on any saved sender to make it the default — Oviond uses the default when no specific sender is chosen. The Oviond built-in sender can't be set as your default. If you delete the default sender, Oviond promotes the next-oldest saved sender automatically.
Before you can add a sending-domain sender, configure and verify a sending domain — see [Email domains](/email-settings/domains). Before you can add an SMTP sender, configure your server — see [SMTP](/email-settings/smtp).
# SMTP
Source: https://docs.oviond.com/email-settings/smtp
Route Oviond email through your own SMTP server.
By default Oviond sends email through its managed provider. If you need every email to pass through your own SMTP server — for deliverability isolation, audit, or IP warming — configure SMTP under **Settings → Email settings** (`/settings/email-settings`). Saving an SMTP config makes SMTP your active email provider.
## Configure
Go to **Settings → Email settings** and set up SMTP (via **Set up SMTP**, or **Add Sender → SMTP server**).
Provide the **SMTP host**, **port** (default `587`), **username**, and **password**, plus the **from email** and an optional **from name**. Leave **Use TLS/SSL** checked unless your server requires otherwise.
Oviond tests the connection, then — if it succeeds — stores the password encrypted at rest and switches the account's active provider to SMTP.
## Fields
| Field | Notes |
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `host` | SMTP server hostname. |
| `port` | Server port. Most servers use `587` (STARTTLS); `465` uses implicit TLS. |
| `username` | SMTP auth username. |
| `password` | SMTP auth password. Stored encrypted and never returned by the API. |
| `secure` | Whether to connect over TLS. The server derives this from the port — `465` uses implicit TLS; `587`/`25` upgrade via STARTTLS — regardless of the **Use TLS/SSL** checkbox. |
| `from_email` | The default from-address for SMTP sends. |
| `from_name` | Optional display name. |
## Connection test
Oviond tests the connection as part of saving — there's no separate test button. When you save, it connects to the server and verifies your credentials without sending an email; if the test fails, the save is aborted and the error (usually auth, TLS, or firewall related) is shown inline.
## Remove SMTP
Deleting the SMTP config removes its credentials and cascade-deletes any senders tied to SMTP. If SMTP was the active provider, Oviond falls back to the Oviond provider.
A misconfigured SMTP server stops email from delivering. Because the save aborts on a failed connection test, a stored config has already passed the test — but verify deliverability with a real send before relying on it for client email.
# Add a goal
Source: https://docs.oviond.com/goals/add
Define a target for a metric and track progress against it.
From the client's **Projects** tab, open the report or dashboard.
In the editor sidebar, open the **Goals** tab and click **Add goal**.
Build the metric query — choose the data source, metric, and optional dimension. Only sources linked to this client are available.
Enter the **target value**, then choose the **operator** that defines success: at or above (`>=`), equal to (`=`), or at or below (`<=`).
Pick **Static** to measure against a fixed target, or **Change** to measure the change in the metric over the period. Choose a display **format** for the value — Numeric, Decimal, Percentage, or Currency.
Give the goal a clear name and save it.
## API
`POST /v1/goals` creates a goal.
# Delete a goal
Source: https://docs.oviond.com/goals/delete
Remove a goal you no longer need.
Deleting removes the goal from the project.
In the project editor, open the **Goals** tab.
Open the goal's menu and choose **Delete**.
Widgets that displayed the deleted goal stop showing its progress until you point them at another goal.
## API
`DELETE /v1/goals/{id}` removes a goal.
# Duplicate a goal
Source: https://docs.oviond.com/goals/duplicate
Start a new goal from an existing one.
Duplicating copies an existing goal's metric, target, and settings, so you can create a variant without rebuilding it.
In the project editor, open the **Goals** tab.
Open the goal's menu and choose **Duplicate**. A copy is added that you can rename and edit.
Use duplicate to set the same target across several clients or to build month-over-month variants of one goal.
## API
`POST /v1/goals/{id}/duplicate` copies a goal.
# Goals
Source: https://docs.oviond.com/goals/overview
Set targets for your metrics and track progress toward them in reports.
A **goal** is a target you set for a metric — for example *Q4 revenue ≥ $250,000* or *cost per lead ≤ $40*. A goal ties a target value to a metric query, so you can show clients how actual performance compares to the target.
Goals are managed inside the project editor, on the **Goals** tab.
## How a goal is defined
* **Metric** — a query against a connected data source (the same builder used for widgets and calculated metrics).
* **Target value** — the number to measure against.
* **Operator** — whether hitting the goal means the metric should be at or above (`>=`), equal to (`=`), or at or below (`<=`) the target.
* **Type** — **Static** measures the metric against a fixed target; **Change** measures the change in the metric over the period.
* **Symbol** — an optional unit shown with the value, such as `$` or `%`.
## Use a goal
Once saved, a goal can be displayed in a report to track progress toward its target alongside your other widgets.
## In this section
* [Add a goal](/goals/add) — define a target for a metric.
* [Duplicate a goal](/goals/duplicate) — start a new goal from an existing one.
* [Delete a goal](/goals/delete) — remove a goal you no longer need.
## API
| Action | Endpoint |
| --------- | ------------------------------- |
| List | `GET /v1/goals` |
| Create | `POST /v1/goals` |
| Update | `PUT /v1/goals/{id}` |
| Duplicate | `POST /v1/goals/{id}/duplicate` |
| Delete | `DELETE /v1/goals/{id}` |
# Connect Google Analytics 4
Source: https://docs.oviond.com/guides/connect-ga4
End-to-end GA4 setup for a client — from OAuth to your first widget.
Google Analytics 4 is one of the most common data sources in Oviond reports. This guide walks through connecting GA4 to a client inside a project and adding a first widget. GA4 uses a two-step account selection: you pick the analytics **account**, then the **property** inside it.
## Before you start
* You have at least **Viewer** access to the GA4 property you want to report on.
* You've already created an Oviond [client](/clients/add) and a [project](/projects/add) for this customer. You connect data sources from inside the project editor.
## 1. Start the connection
From the client's **Projects** tab, open the project you want to report in.
In the editor sidebar, click **Data sources**.
Use the **Search data sources...** box, then click **Connect** next to Google Analytics 4.
Oviond shows a **Profile Name** field, prefilled with *Default Google Analytics 4 Connection*. Keep it or rename it (for example, *Acme — Google*), then click **Connect**. A profile name can't contain `.` or `$`.
## 2. Authorize with Google
Oviond opens a Google sign-in popup. Pick the Google account that has access to the GA4 property.
Approve the access Oviond requests. Oviond requests read-only access — it cannot change anything in your GA4 account.
A profile is reusable. If you already authorized Google Analytics for another client, you don't need to authorize again — pick the existing profile under **Select Profile** in the next step.
## 3. Link the account and property
After authorizing, you tell Oviond which analytics account and property belong to *this* client.
Under **Select Profile**, choose the connection you just authorized, then click **Link**.
Under **Select Account**, pick the GA4 analytics account. Use **Search...** to narrow the list, then click **Next**.
The next screen (still headed **Select Account**) lists the properties inside that account. Pick the GA4 **property**, then click **Save**.
Oviond links the property to the client and shows a *Google Analytics 4 linked* confirmation. The linked profile sorts to the top of the list with a **Linked** tag and shows the selected **Account** and **Property**.
## 4. Check the connection status
Each profile shows a status badge so you can tell its token is healthy:
* **Token Valid** — the connection is authorized and data should flow.
* **Token Expired** — the token expired or was revoked; refresh it.
Status is set automatically by a daily auth-test check and the OAuth token refresher.
## 5. Refresh an expired connection
If the profile shows **Token Expired**, click **Refresh** on the profile to reopen the Google sign-in popup and re-authorize with the same account. The badge returns to **Token Valid**. There is no separate "test" or "reconnect" action — **Refresh** handles re-authorization.
## 6. Build your first GA4 widget
In the editor sidebar, open the **Add Content** tab.
Drag a **Data Query** widget onto the canvas. See [Add a widget](/widgets/add).
In the data source picker, select the GA4 source you just linked. Only sources connected to this client are available.
Start with **Sessions** — a universal GA4 metric that exists for every property. Add an optional dimension for a breakdown.
Pick a single-value KPI for a quick win, or a line chart to trend the metric over time.
Set the project's date range to a relative period (for example, last 30 days) so the widget auto-updates each time the report is opened. Oviond auto-saves the editor as you work.
## Common follow-ups
* Add a **Sessions by Source / Medium** table for a traffic breakdown.
* Add a **Conversions** widget if you've set up GA4 conversion events.
* Use [Calculated metrics](/calculated-metrics/overview) to compute engagement rate or conversion rate.
## Troubleshooting
* **No data returned** — the property is connected but empty for the selected period. Check the widget's date range and that you linked the right property.
* **Token Expired** — the OAuth token expired or access was revoked. Click **Refresh** on the profile and re-authorize.
* **Property missing from the list** — the authorizing Google account doesn't have access to that property in GA4. Re-authorize with an account that does, or click **Refresh**.
* **Accounts won't load** — Oviond shows *Unable to load accounts for Google Analytics 4.* Click **Refresh** and try again.
# Build Your First Report
Source: https://docs.oviond.com/guides/first-report
A complete walkthrough from creating a client to publishing a shared link.
This guide takes you from a fresh Oviond account to a live, shareable report for your first client. Expect it to take \~20 minutes end-to-end.
## Before you start
* You've signed up for Oviond and completed [onboarding](/onboarding/overview) — your name, company, website, client count, and first client.
* You have OAuth access (or an API key) to at least one data source, such as Google Ads, Google Analytics 4, or Facebook Ads.
## 1. Add a client
Everything in Oviond is scoped to a client. See [Add Client](/clients/add). At minimum, enter the **Client name** and **Client website**. Oviond auto-generates a thumbnail from the website URL.
## 2. Create the project
A **project** is the report or dashboard you build inside the client. See [Add Project](/projects/add).
From your **Clients** list, open the client. Everything you create here is scoped to that client.
On the client's **Projects** tab, click **Add Project**.
Pick **Start from scratch** or **Start from a template**. A [template](/templates/apply) pre-populates pages and widgets you can customize.
Choose **Report** (a point-in-time report for a specific date range) for your first build. **Dashboard** is a live, single-screen view.
Name it something like *Acme — Monthly Performance*, then click **Create project**. Oviond opens the project editor.
## 3. Connect a data source
You wire up data inside the project editor, in its **Data sources** tab. See [Connect](/data-sources/connect).
In the editor sidebar, click **Data sources**.
Search for the platform — e.g. Google Analytics 4 — and click **Connect**. Name the connection profile, then run the OAuth flow (or enter an API key). Oviond requests read-only access.
Under **Select Profile**, choose the connection and click **Link**. Then under **Select Account**, pick the specific account, property, or page for this client and click **Save**.
Each connection shows a **Token Valid** or **Token Expired** badge. If a token expires, click **Refresh** to re-authorize. See [Connect](/data-sources/connect).
## 4. Add pages and content
A report starts with one page. See [Add a page](/pages/add) to add and rename pages.
In the editor sidebar, open the **Add Content** tab.
Drag a **Data Query** onto the canvas. Pick the data source you linked, choose a metric (e.g. *Sessions*) and an optional dimension, then pick the chart type — a single-value KPI is a quick win.
Drag in a second **Data Query**, set it to a line chart of *Sessions* over the last 30 days, and place it next to the KPI.
Oviond auto-saves the editor as you work and saves the whole project — every page and widget — in one operation. See [Add a widget](/widgets/add).
## 5. Apply a theme
To make the report feel on-brand:
See [Add Theme](/themes/add). Set your client's primary color — Oviond auto-derives the full chart palette.
See [Apply Theme](/themes/apply).
## 6. Share it
See [Share Project](/projects/share). Click **Share** in the top-right of the editor to open the Share dialog.
On the **Link** tab, keep **Link is Active** on and click **Copy**. The link points to `/shared/{nano_id}` on your share host.
Toggle **Show Date Selector**, **Allow PDF Download**, or **Enable Password** as needed.
Send the link to your client. They open it in any browser — no Oviond account needed.
## Next steps
* [Schedule a Monthly Report](/guides/monthly-report) — automate delivery to your client's inbox.
* [Connect Google Analytics 4](/guides/connect-ga4) — the full GA4-specific setup.
* [Templates](/templates/add) — save this report's layout so you can spin up the same thing for your next client in minutes.
# Monthly Client Report
Source: https://docs.oviond.com/guides/monthly-report
Automate a recurring monthly report email for a client.
This guide sets up a monthly automated report that delivers to your client's inbox on the 1st of every month. You'll end with an automation that runs without any manual work month to month.
## Before you start
* You have a [project](/projects/add) — report or dashboard — ready to send.
* You've configured a [sender](/email-settings/senders) so the email comes from your own domain (optional — Oviond falls back to a default address).
* You've tested the project's widgets with live data.
## 1. Verify the report is ready to send
Make sure every widget is configured against the right data source and date range.
Plan to set the automation's date range to a relative period such as **Last Month**. Relative dates are essential for automations — each monthly run pulls its own month's data.
Open the project's **Share** dialog, switch to the **Download** tab, and click **Generate New PDF**. Generation runs in the background; check that the rendered report looks clean. See [PDF export](/automations/pdf).
## 2. Create the automation
You can create an automation from the top-level **Automations** screen or from the project editor's **Automations** tab. See [Add an automation](/automations/add).
Click **Automations** in the left sidebar, then click **New automation**. (From the project editor's **Automations** tab, click **Add automation** instead, and the project is pre-selected.)
Enter a **Name**. Set **Frequency** to **Monthly**, **Day of month** to `1`, and **Send at** to a morning hour. The schedule is evaluated against your account timezone. See [Scheduled delivery](/automations/scheduled).
Choose the **Client** and **Project** you validated, then set **Date range** to **Last Month**. The report is rendered fresh for that range on every run.
Add the client contact under **Recipients** (you can add several). Choose the **From** sender, and pick an **Email template** — or choose **Custom message** to compose a **Subject** and **Message** inline. Placeholders like the client name and date range fill in from the project. See [Email delivery](/automations/email).
Click **Create**. The automation is saved and the next run is scheduled automatically.
## 3. Test before going live
Always test before relying on an automation:
From the **Automations** list, use the row menu or open the details slide-over.
A test send bypasses the schedule and emails the report immediately. The recipient dialog is pre-filled with the saved recipients — edit it to send the test to yourself. See [Test an automation](/automations/test).
Subject, sender, body copy, and the rendered report should all look exactly how the client will see it.
A test send doesn't advance the schedule, but it does appear in run history flagged as a **Test** run.
## 4. Monitor the first real run
After the first scheduled delivery (on the 1st of next month):
From an automation, click **Executions**, or open the project's run history. See [Run history](/automations/history).
**Success** — the run rendered and sent. **Failed** — a rendering or delivery problem; the error detail is stored with the run. **Skipped** — the run was skipped, e.g. the automation was paused when it was due.
See [Email logs](/email-settings/logs) for per-recipient delivery events.
## If the client changes their address
Edit the automation, update the **Recipients** list, and save. No need to re-test unless you also changed the sender or subject.
## If you need to pause
Use **Pause / Resume** on the automation to suspend sending without losing the configuration. The schedule stops firing until you resume. See [Scheduled delivery](/automations/scheduled).
# Overview
Source: https://docs.oviond.com/guides/overview
End-to-end walkthroughs for the most common Oviond workflows.
The **Guides** tab collects step-by-step walkthroughs that cross multiple features — the kind of docs where a single feature page isn't enough. Use these when you want the full flow and decision points for a complete job.
## What's here
From creating a client to publishing your first shared link.
End-to-end GA4 setup — OAuth, property linking, your first widget.
Automate a scheduled email report for a recurring client.
## Who guides are for
* **New users** — pick *Build Your First Report* as your first read after the Quickstart.
* **Teams onboarding a new client** — the Monthly Client Report guide covers the full client-setup flow.
* **Debugging** — when a feature doesn't quite behave the way you expect, the guides show how it fits into the larger workflow.
For single-feature reference, use the **Documentation** tab's per-feature pages.
# Introduction
Source: https://docs.oviond.com/introduction
White-label marketing reporting. Build branded dashboards, connect 60+ data sources, and automate client report delivery.
Oviond is a white-label digital marketing reporting platform. Connect your clients' marketing accounts — Google Ads, Facebook, and 60+ other platforms — and build professional dashboards and reports that you deliver under your own brand. This documentation covers everything you need to get up and running, from creating your first client report to automating scheduled delivery for your entire client base.
In Oviond, every project belongs to a **client**. You create a client, build a dashboard or report inside that client, and connect the client's data sources from within the project editor as you go. The main sidebar gives you **Clients**, **Templates**, **Automations**, and **Settings**.
## Start with your goal
Create a client, connect data, and build your first report.
Assemble a report and schedule recurring delivery.
Create a dashboard that always shows the latest data.
Set up your own domain and branding for client-facing reports.
Automate Oviond from your own scripts and integrations.
Let Claude, ChatGPT, and other agents manage your account.
## How Oviond works
Create a client to hold all of one customer's data sources, dashboards, and reports.
Add a project inside the client — a **Dashboard** for a live view or a **Report** for a point-in-time snapshot. Start from scratch or from a template.
Inside the project editor, open the **Data sources** tab and link the client's marketing accounts — Google Ads, Facebook Ads, Google Analytics, and more — through OAuth or an API key in a few clicks.
Use the drag-and-drop builder to add charts, tables, and KPI widgets that pull live data from your connected data sources.
Customize the logo, colors, and fonts on every project. Set up a custom domain so clients experience your brand, not Oviond's.
Create an automation to send reports on a recurring schedule — daily, weekly, or monthly.
# Authentication
Source: https://docs.oviond.com/mcp/auth
How the Oviond MCP server authenticates AI agents — OAuth 2.1 under the hood.
The Oviond MCP server uses **OAuth 2.1 authorization-code flow with PKCE** — the same pattern the MCP spec mandates for remote servers. Clients are public clients: they use PKCE (`S256`) instead of a client secret. This section walks through what the agent and Oviond do during the handshake.
## Flow at a glance
1. **Discovery** — when the agent hits `https://api.oviond.com/mcp` without a valid token, the `WWW-Authenticate` header points it at `https://api.oviond.com/.well-known/oauth-protected-resource`. That metadata names the authorization server, which the agent then reads from `https://api.oviond.com/.well-known/oauth-authorization-server`.
2. **Client registration** — the agent dynamically registers at `/oauth/register` (RFC 7591). No manual client-secret setup is required; registered clients use `token_endpoint_auth_method: none`.
3. **Authorization request** — the agent opens a browser to `/oauth/authorize` with a PKCE `code_challenge` (`code_challenge_method=S256`).
4. **User consent** — you sign in to Oviond and approve the connection on the consent screen.
5. **Token exchange** — the agent exchanges the authorization code at `/oauth/token`, sending its `code_verifier` to satisfy PKCE.
6. **Tool calls** — every subsequent MCP request carries `Authorization: Bearer `.
## Endpoints
| Endpoint | Purpose |
| ----------------------------------------- | -------------------------------------------------------------- |
| `/.well-known/oauth-protected-resource` | Resource metadata (RFC 9728) — names the authorization server. |
| `/.well-known/oauth-authorization-server` | Authorization server metadata (RFC 8414). |
| `/oauth/register` | Dynamic client registration (RFC 7591). |
| `/oauth/authorize` | Start the authorization-code flow. |
| `/oauth/token` | Exchange a code or refresh token for an access token. |
| `/oauth/revoke` | Revoke a refresh token (RFC 7009). |
| `/oauth/jwks` | Public signing keys (ES256). |
The only supported scope is `mcp`, and the only supported PKCE method is `S256`.
## Token scope
Access tokens are scoped to **the signed-in user's role and account**. The MCP server:
* Sees only clients, projects, and data the authenticated user can see in the web app.
* Inherits the user's role (carried as a claim in the access token).
* Is scoped to a single account — you don't pass an `account_id`.
## Token lifetime
* **Access tokens** last 1 hour.
* **Refresh tokens** are issued alongside the access token and last 30 days.
* Refresh tokens rotate: each refresh returns a new refresh token and invalidates the old one. The MCP client refreshes automatically, so you won't be prompted to sign in again during normal usage.
## Revoking access
The MCP client can revoke its refresh token at `/oauth/revoke`. Once revoked, that refresh token stops working immediately; the agent re-authorizes on its next attempt. Access tokens are stateless and expire on their own within an hour.
The MCP server does **not** use the Bearer API keys you create under **API Keys**. Those are for direct REST API calls. MCP has its own OAuth flow with per-client tokens.
# Connect
Source: https://docs.oviond.com/mcp/connect
Connect Claude, ChatGPT, Cursor, VS Code, and other AI clients to your Oviond account over MCP.
Every supported AI connector reaches Oviond at the same hosted server URL over OAuth:
```
https://api.oviond.com/mcp
```
## Supported connectors
All use the standard **streamable HTTP** transport with **OAuth 2.1 + PKCE** — setup differs only in where you paste the URL.
| Connector | What it is |
| --------------------- | ----------------------------------------------------------------------- |
| **Claude** | Claude.ai web & desktop |
| **Claude Code** | Anthropic's terminal CLI |
| **ChatGPT** | OpenAI custom connectors |
| **Codex** | OpenAI's coding CLI |
| **Cursor** | AI-first code editor |
| **VS Code** | GitHub Copilot agent mode |
| **Windsurf** | Codeium's AI editor |
| **Openclaw** | Local AI agent with custom skills |
| **Other MCP clients** | Any client that speaks MCP |
| **REST API** | Call Oviond's HTTP API directly — see [Authentication](/authentication) |
## Claude (web & desktop)
On the web or in the desktop app, open **Settings → Connectors**.
Click **+ Add custom connector** and enter the URL `https://api.oviond.com/mcp`.
Claude opens a browser window to Oviond's sign-in page. Sign in and authorize the connection.
You should see Oviond in your connector list. Start a chat and ask Claude to *"list my Oviond clients"* to confirm.
## Claude Code
```bash theme={null}
claude mcp add --transport http oviond https://api.oviond.com/mcp
```
Run `/mcp` inside Claude Code and choose to authenticate — it opens a browser to complete the Oviond OAuth flow.
Ask Claude Code to *"list my Oviond clients"* to confirm.
## Cursor
**Settings → MCP** (or edit `~/.cursor/mcp.json` directly).
```json theme={null}
{
"mcpServers": {
"oviond": {
"url": "https://api.oviond.com/mcp"
}
}
}
```
Restart Cursor. On first tool call, Cursor opens a browser to complete OAuth.
## ChatGPT, Codex, VS Code, Windsurf, Openclaw & other clients
The flow is the same everywhere: add a **custom / remote MCP connector** pointing at `https://api.oviond.com/mcp`, then complete the OAuth sign-in when the client prompts you.
* **ChatGPT** — add Oviond as a custom connector in settings.
* **VS Code** — add it as an MCP server for Copilot agent mode.
* **Codex**, **Windsurf**, **Openclaw**, and any other MCP client — register a remote streamable-HTTP MCP server at the URL above.
Then verify by asking the agent to *"list my Oviond clients."*
Only **streamable HTTP** transport is supported. Stdio servers don't apply here — Oviond's MCP server is hosted by us, not run locally.
MCP access requires an eligible plan. Subscription plans include API/MCP access; lifetime plans need the API add-on. If your plan isn't entitled, the connection is rejected during sign-in.
## First prompts to try
* *"List all my Oviond clients."*
* *"Create a new client called 'Acme Corp' with website acme.example."*
* *"Build a dashboard called 'Paid Social Overview' for Acme."*
* *"Schedule the Acme monthly report to send on the 1st of every month."*
## Teach your agent the workflows
Tool descriptions say what each tool does; they can't say what order to do things
in. If your client supports the `skills` ecosystem, install the Oviond skill so
your agent has the full workflow guide:
```bash theme={null}
npx skills add oviond/skills --skill oviond
```
See [Skills](/mcp/skills) for what it covers.
# Overview
Source: https://docs.oviond.com/mcp/overview
The Oviond MCP server lets Claude and other AI agents manage your Oviond account directly.
Oviond ships a **Model Context Protocol (MCP)** server so AI agents — Claude, ChatGPT, Claude Code, Codex, Cursor, VS Code, Windsurf, and any other MCP-compatible client — can manage your Oviond account programmatically. Ask your agent to *"create a new client and an agency report for them"* and it happens.
Not everything in Oviond is reachable over MCP yet. Connecting an OAuth data
source (Google, Meta, LinkedIn, TikTok) needs a browser sign-in, file uploads
happen in the app, and anything that sends real email or deletes records should
be confirmed by a person first. [Playbooks](/mcp/playbooks) says what to hand
back to the app.
## What you can do
The MCP server exposes **179 tools** covering most of the Oviond surface area:
* **Clients & folders** — create, rename, delete, move, and organize clients.
* **Projects & pages** — create reports and dashboards, add and reorder pages, duplicate layouts, change the period a report covers.
* **Widgets** — add, update, move, and remove text, title, image, embed, button, and data widgets.
* **Data sources** — connect one with an API key, link it to a client, test it, and refresh what it feeds.
* **Data** — discover a datasource's metrics and dimensions, configure a data widget, and pull its numbers.
* **Templates & themes** — browse the template library, apply themes to projects.
* **Automations** — schedule, pause, and test automated report deliveries.
* **Branding & company** — update logo, favicon, and company details.
* **Workflows** — multi-step actions, like creating a client with a starter report or auditing a report's health.
* **Assets, media, domains, users, goals, calculated metrics, notifications, email, billing**, and search.
## How it works
* **Transport** — streamable HTTP at `https://api.oviond.com/mcp`.
* **Auth** — OAuth 2.1 authorization-code flow with PKCE. Your AI agent launches a browser, you sign into Oviond, and the agent gets a scoped access token.
* **Isolation** — every tool call is scoped to the signed-in account. The agent can only touch data the authenticated user has permission for.
## Next steps
* [Connect](/mcp/connect) — wire up Claude, Cursor, or your MCP client to Oviond.
* [Authentication](/mcp/auth) — what the OAuth flow does under the hood.
* [Available tools](/mcp/tools) — the full catalog of MCP tools.
* [Playbooks](/mcp/playbooks) — copy-paste prompts for common jobs.
* [Skills](/mcp/skills) — install Oviond as a reusable skill for your agent.
* [Troubleshooting](/mcp/troubleshooting) — what the common errors mean.
# Playbooks
Source: https://docs.oviond.com/mcp/playbooks
Copy-paste prompts for common Oviond jobs an AI agent can do over MCP — with the tools each one uses and safety notes.
These playbooks are prompts you can give an MCP client (Claude, Cursor, etc.) connected to Oviond. Each lists the tools the agent will reach for and any safety note. Tool names and the full catalog are on [Available tools](/mcp/tools).
Every call is automatically scoped to your authenticated account — you never pass an account ID, and the agent can only see your own clients and projects.
## 1. List and inspect clients
> "List my Oviond clients grouped by folder, and tell me which ones have no active projects."
**Tools:** `list_clients`, `list_folders`, `list_projects`, `search`
**What happens:** the agent pages through your clients, groups them by folder, and cross-references each client's projects. Read-only — nothing changes.
## 2. Create a client with a report (from a template)
> "Create a client called Acme Demo with a Google Ads dashboard."
**Tools:** `list_templates` (find the template) → `create_client_with_project`
**What happens:** the agent finds the matching template with `list_templates` (filter `datasources=gadw`, `type=DASHBOARD` → "Google Ads Dashboard"), then `create_client_with_project` creates the client and clones that template into the first project — pages and widgets included.
The create step is smart about the project:
* **"…with a Google dashboard"** → the agent passes the matched `template_id`.
* **"…with a blank report"** → pass `blank: true` for an empty project.
* **"…with a report"** (unspecified) → a matching **Starter** template is cloned automatically.
To add a template-based report to an **existing** client, use `create_project_from_template`.
This creates real records in your account. Confirm the client and report names before the agent runs it.
## 3. Duplicate a report for another client
> "Duplicate the 'Monthly Marketing Overview' report for the client Beta Corp."
**Tools:** `search` / `list_projects` → `duplicate_project` → `update_project`
**What happens:** the agent finds the source report, duplicates it, and re-points the copy at the new client. Layout and widgets carry over.
## 4. Add a saved section to a report or dashboard
> "Add my 'Executive Summary' section to the Acme dashboard."
**Tools:** `list_assets` (find the section) → `add_project_section`
**What happens:** the agent finds the saved section with `list_assets` (search by name), then `add_project_section` places its widgets on the project. A single-page project (typical dashboard) uses its one page automatically; a multi-page report returns its pages so the agent can pick the right `page_id`.
## 5. Apply branding
> "Set Acme Demo's brand color to #1E88E5 and generate a matching palette."
**Tools:** `get_branding`, `update_branding`, `generate_company_palette`
**What happens:** the agent reads current branding, generates a palette, and updates the logo/colors. Review the palette before applying.
## 6. Connect a data source and attach it to a client
> "Connect our Stripe account and use it for Acme Demo."
**Tools:** `datasources` → `create_connection` → `link_datasource`
**What happens:** two separate steps, and it helps to know why. A **connection** belongs to your account (one Stripe login); a **link** points one client at it — so several clients can share one connection while each reports on its own account.
* `create_connection` — call it with the datasource and a name, and it replies with the exact fields that datasource needs (`api_key`, `api_url`, …). Call it again with the values.
* `link_datasource` — call it with the client and datasource, and it lists the accounts to choose from. Some datasources take two picks (Meta Ads: Business Manager, then ad account; Business Profile takes several locations at once).
Datasources that sign in on the vendor's website — Google, Meta, LinkedIn, TikTok — need a browser, so `create_connection` refuses them and says so. Connect those once in the app; the agent can still link them to clients afterwards.
## 7. Build a data widget and pull its numbers
> "Add a GA4 sessions-by-day chart to the Acme dashboard for the last 30 days."
**Tools:** `datasources` → `describe_datasource` → `add_data_widget` → `refresh_widgets`
**What happens:** the agent looks up the `datasource_id`, then `describe_datasource` returns that datasource's data views with their metrics, dimensions and any required settings — so nothing is guessed. `add_data_widget` writes the widget, and **the series is fetched server-side straight after the write**. `refresh_widgets` re-runs it on demand.
A widget pointed at a datasource the client hasn't connected renders **demo data**. That's the product behaviour, not an error — link the datasource and refresh to replace it with real numbers.
## 8. Change the period a report covers
> "Switch the Acme monthly report to last 7 days."
**Tools:** `change_project_date_range` (or `refresh_project` to re-pull the current period)
**What happens:** the range is stored as the preset itself, so "Last 7 Days" keeps meaning the last 7 days as the calendar moves. The server resolves it to concrete dates and refreshes every widget on the project.
## 9. Audit a report's health
> "Audit the 'Monthly Marketing Overview' report — what data sources are connected and are any automations paused?"
**Tools:** `audit_project_health` (one call), or `get_project` + `connected_datasources` + `list_automations`
**What happens:** the `audit_project_health` workflow tool gathers the connected data sources and automation state in one step and flags likely issues (nothing connected, paused automations). Read-only.
## 10. Schedule a monthly report (with confirmation)
> "Schedule the Acme monthly report to email on the 1st of each month to [me@acme.com](mailto:me@acme.com) — but show me the settings and ask before you activate it."
**Tools:** `create_automation`, `test_automation`, `pause_automation` / `unpause_automation`, `get_automation_history`
**What happens:** the agent drafts the automation (recipient, cadence, timezone), can send a test, and should leave it **paused** until you confirm activation.
This changes delivery state and sends real email. Ask the agent to create it paused and send a test to yourself first.
## What MCP can't do yet
* **Connect an OAuth data source.** Google, Meta, LinkedIn, TikTok and the rest sign in on the vendor's own website, which needs a browser. Do it once in the app — everything after that (linking to clients, building widgets, pulling data) works over MCP. Datasources that use an API key **can** be connected with `create_connection`.
* **Upload files.** Media and custom-data uploads happen in the app; MCP can list, rename and delete what is already there.
# Skills
Source: https://docs.oviond.com/mcp/skills
Install Oviond as a reusable skill for AI agents
You can install Oviond as a reusable skill for AI agents that support the `skills`
ecosystem. This gives your agent a versioned workflow guide for operating Oviond
instead of leaving it to infer how the pieces fit together each time.
## Install
```bash theme={null}
npx skills add oviond/skills --skill oviond
```
## What the skill covers
The `oviond` skill helps your agent:
* understand the shape of an account — client → project → page → widget, and where
a datasource connection sits
* discover a datasource's data views, metrics and dimensions before configuring a
widget, rather than guessing field ids
* know that data is fetched **server-side after a widget is written**, and that
`refresh_widgets` / `refresh_project` re-run it — there is no ad-hoc query tool
* connect a datasource by API key, and recognise which datasources need a browser
sign-in and must be handed back to the app
* build the four widget types that are not vendor datasources — static value,
goals, uploaded data, calculated metrics — each of which binds differently
* treat a date range as a preset that re-resolves ("Last 30 Days" keeps meaning
the last 30 days), not a fixed pair of dates
* create automations paused, send a test, and wait for confirmation before
activating
It also names the behaviours that read as failures but are not: demo data on a
datasource the client has not connected, a widget briefly in `loading` while the
fetch runs, and datasources like Stripe that have no accounts to choose from.
## Why use a skill
Without one, your agent has to work out Oviond's workflows from tool descriptions
alone. A description says what one tool does; it cannot say what order to do
things in. With a skill you give it:
* a stable reference for how the product fits together
* use-case driven guidance instead of tool-by-tool guessing
* explicit caveats for what MCP cannot do and should hand back to the app
* a versioned source of truth you can update as Oviond evolves
## Repository
The public source lives here:
* [Oviond Skills on GitHub](https://github.com/oviond/skills)
## Install notes
* After installing, restart your AI tool if it does not pick up the new skill
immediately
* Pair it with the [MCP connector](/mcp/connect) — the skill explains the
workflows, the connector executes them
* The skills ecosystem is supported by Claude Code and claude.ai. If you use
Oviond through another client, the connector still ships the essentials in its
own instructions
## Documentation index
Agents can discover every page in these docs at
[docs.oviond.com/llms.txt](https://docs.oviond.com/llms.txt).
# Available tools
Source: https://docs.oviond.com/mcp/tools
The full catalog of tools the Oviond MCP server exposes.
The Oviond MCP server exposes **179 tools** across 29 groups. Most map to a single REST
operation; a few chain several. Tool names are verb-first — `create_client`, `list_projects`,
`add_data_widget` — so an agent can guess the right one from the action.
## Tool catalog
### Account
| Tool | What it does |
| ------------------- | ------------------------------------------------------------------- |
| `get_account` | Get account details for the authenticated user |
| `get_account_usage` | Get current account usage stats (clients, projects, users, storage) |
### Activity
| Tool | What it does |
| --------------- | ----------------------------------------------------------------------------------- |
| `list_activity` | List the account activity / audit log (who changed what), paginated and filterable. |
### API keys
| Tool | What it does |
| ------------------- | ----------------------------------------------------------------------------------------------------- |
| `list_api_keys` | List the account's API keys (prefixes + status only — the full key is never returned after creation). |
| `revoke_api_key` 🔒 | Revoke an API key (soft — it stops working but stays listed as revoked). |
| `delete_api_key` 🔒 | Permanently delete an API key record. |
### Archive
| Tool | What it does |
| ---------------------- | ---------------------------------------------------------------------------------------------- |
| `list_archive` | List soft-deleted (archived) items across clients, projects, media, automations and templates. |
| `get_archive_counts` | Get the count of archived items per type. |
| `restore_from_archive` | Restore archived items of one type back to active. |
### Assets
| Tool | What it does |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `list_assets` | List saved widget-section assets for the account (with optional filters). |
| `get_asset` | Get a single asset by ID. |
| `create_asset` | Save widgets as a reusable section, the same way the editor does when you select widgets and save them: each widget is copied onto the section with a fresh id, and its type and datasources are… |
| `update_asset` | Update asset metadata. Only include fields you want to change. |
| `archive_asset` 🔒 | Archive a saved section and its widget rows. It goes to the archive, not away — `list_archive` shows it and `restore_from_archive` brings it back. |
| `duplicate_asset` | Duplicate an asset (and its widgets) under a new name. |
| `list_asset_widgets` | List the widgets that belong to an asset (useful for previewing what add\_asset\_to\_page will instantiate). |
| `add_asset_to_page` | Instantiate an asset's widgets onto a project page. |
| `list_asset_tags` | List every tag used across the account's saved sections (useful for filtering list\_assets by tag). |
### Automations
| Tool | What it does |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `list_automations` | List automations with optional filtering by project or client |
| `get_automation_history` | Get send history for an automation |
| `create_automation` | Create a new automation. Pick an existing email template + sender by id (from email\_templates / email\_senders), or pass template\_id:"custom" together with a `custom` payload to save a new named… |
| `update_automation` | Update an existing automation — only include the fields you want to change |
| `archive_automation` 🔒 | Archive an automation, stopping its scheduled deliveries. `restore_from_archive` brings it back, rescheduled. |
| `pause_automation` | Pause an automation |
| `unpause_automation` | Unpause an automation |
| `test_automation` | Send a test email for an automation |
### Billing
| Tool | What it does |
| --------------- | ------------------------------------------------------------------------------ |
| `get_billing` | Get the current billing summary for the account (plan, status, limits, trial). |
| `list_invoices` | List the account's invoices. |
### Branding
| Tool | What it does |
| --------------------------- | ------------------------------------------------------------------------------------------------ |
| `get_branding` | Get the account's white-label branding (logo, favicon) |
| `update_branding` | Update branding settings — only include the fields you want to change. |
| `refresh_account_favicon` | Re-derive the account's favicon from its website, cache-bust it, save it and return the new URL. |
| `remove_account_logo` 🔒 | Remove the account's full logo. It falls back to the default Oviond branding. |
| `remove_account_favicon` 🔒 | Remove the account's square logo (favicon). |
### Calculated metrics
| Tool | What it does |
| ------------------------------ | -------------------------------------------------------------------------------------- |
| `list_calculated_metrics` | List calculated metrics for the account (custom KPI formulas). |
| `create_calculated_metric` | Create a calculated metric — a custom KPI from a formula over other metrics. |
| `update_calculated_metric` | Update a calculated metric. Full replacement — you must send name, formula AND symbol. |
| `archive_calculated_metric` 🔒 | Archive a calculated metric by ID. Restorable from the archive. |
| `duplicate_calculated_metric` | Duplicate a calculated metric, optionally with a new name. |
### Clients
| Tool | What it does |
| --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `list_clients` | List all clients with optional filtering and pagination |
| `count_clients` | Get total count of clients for the account |
| `get_client` | Get a single client by ID |
| `create_client` | Create a new client |
| `update_client` | Update an existing client — only include the fields you want to change |
| `archive_client` 🔒 | Archive a client by ID, with its projects, exports and automations. Restorable from the archive. |
| `archive_clients` 🔒 | Archive several clients by ID in one call. Restorable from the archive. |
| `remove_client_logo` 🔒 | Remove a client's full logo (logo\_url). It falls back to the agency branding. |
| `remove_client_favicon` 🔒 | Remove a client's square logo/favicon (favicon\_url). |
| `refresh_client_favicon` | Re-derive a client's square favicon from its stored website (Google favicon service), cache-bust it, save it, and return the new favicon URL. |
| `refresh_client_screenshot` | Re-take the screenshot of a client's website and save it, returning the new URL. |
| `move_client_to_folder` | Move a client to one or more folders |
### Company
| Tool | What it does |
| -------------------------- | ----------------------------------------------------------------------------------------- |
| `get_company` | Get company settings |
| `update_company` | Update company settings |
| `generate_company_palette` | Generate a color palette from a hex color (read-only — computes shades, changes nothing). |
### Custom data
| Tool | What it does |
| ------------------------ | ------------------------------------------------------------------------------------------------------ |
| `list_custom_data` | List uploaded custom-data (CSV) datasets for the account — summaries without the row data. |
| `get_custom_data` | Get a single custom-data dataset by ID, including its parsed rows. |
| `create_custom_data` | Create a custom-data dataset from parsed CSV rows (max 10,000 rows). |
| `update_custom_data` | Update a custom-data dataset — send only the fields you want to change (e.g. \{ raw\_data, columns }). |
| `archive_custom_data` 🔒 | Archive a custom-data dataset by ID. Restorable from the archive. |
| `duplicate_custom_data` | Duplicate a custom-data dataset with a new name. |
### Datasources
| Tool | What it does |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `datasources` | List every datasource Oviond supports, with the `id` (the datasource\_id used everywhere else — e.g. ga4, gadw, fb-ads), name, category, and data views. |
| `describe_datasource` | Describe a datasource the way the report builder sees it, in one call: its data views, the `advanced` settings each view requires, its default view and defaults, and its metric and dimension catalogs… |
| `connected_datasources` | List the datasource connections this account has made. |
| `create_connection` | Create a datasource connection from credentials — the connect panel's credential form, as a tool. |
| `link_datasource` | Point a client at one of the account's datasource connections — the connect panel's account picker, as a tool. |
| `test_connection` | Test whether a client's connected datasource is still working (e.g. the OAuth token is valid). |
| `rename_connection` | Rename a datasource connection |
| `unlink_datasource` 🔒 | Detach a connected datasource from a client so its widgets no longer pull from that connection. |
| `delete_connection` 🔒 | Delete a datasource connection — every widget pulling data from it will break |
### Domains
| Tool | What it does |
| ------------------ | ------------------------------------------------------------------------------------------------------------------ |
| `list_domains` | List custom domains registered on the account, including DNS verification records |
| `add_domain` | Add a custom domain. The backend detects the DNS provider and returns the DNS records the user needs to configure. |
| `remove_domain` 🔒 | Remove a custom domain by its ID |
### Email
| Tool | What it does |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `send_email` | Send an email. Either pass template\_id (a saved template) OR subject+html (free-form). Sends are queued and paced; poll email logs for delivery. |
| `list_email_logs` | List sent-email history / delivery logs. |
| `list_email_senders` | List configured "From" senders and the active provider. |
| `create_email_sender` | Create a "From" sender. |
| `update_email_sender` | Update a sender — only the fields you want to change. |
| `delete_email_sender` 🔒 | Delete a sender by ID. |
| `set_default_email_sender` | Make a sender the account default. |
| `list_email_templates` | List reusable email templates. |
| `get_email_template` | Get a single email template by ID. |
| `create_email_template` | Create an email template. |
| `update_email_template` | Update an email template — only the fields you want to change. |
| `delete_email_template` 🔒 | Delete an email template by ID (refused if it is the default). |
| `set_default_email_template` | Make an email template the account default. |
| `list_email_domains` | List verified sending domains. |
| `add_email_domain` | Add a sending domain (returns DNS records to configure). |
| `verify_email_domain` | Re-check DNS and verify a sending domain. |
| `remove_email_domain` 🔒 | Remove a sending domain by ID. |
| `get_email_provider` | Get the account's active email provider. |
| `set_email_provider` | Set the account's email provider. |
### Exports
| Tool | What it does |
| ------------------- | ----------------------------------------------------------------------- |
| `list_exports` | List PDF export history for a project (one row per generation attempt). |
| `archive_export` 🔒 | Archive a PDF export record by ID. Restorable from the archive. |
### Folders
| Tool | What it does |
| ------------------ | --------------------------------------- |
| `list_folders` | List all client folders for the account |
| `create_folder` | Create a new client folder |
| `update_folder` | Rename a client folder |
| `delete_folder` 🔒 | Delete a client folder |
### Goals
| Tool | What it does |
| ----------------- | --------------------------------------------------------------------- |
| `list_goals` | List goals for the account (targets tracked against a metric query). |
| `create_goal` | Create a goal — a target value + comparison for a saved metric query. |
| `update_goal` | Update a goal — only include the fields you want to change. |
| `archive_goal` 🔒 | Archive a goal by ID. Restorable from the archive. |
| `duplicate_goal` | Duplicate a goal, optionally with a new name. |
### Media
| Tool | What it does |
| ------------------------ | --------------------------------------------------------------------------------------------------- |
| `list_media` | List media files |
| `rename_media_file` | Rename a media file |
| `archive_media_file` 🔒 | Archive a media file. The file leaves storage only when it is permanently deleted from the archive. |
| `archive_media_files` 🔒 | Archive several media files by ID in one call. Restorable from the archive. |
| `move_media_to_folder` | Move one or more media files into a media folder. |
| `list_media_folders` | List the account's media folders. |
| `create_media_folder` | Create a new media folder. |
| `update_media_folder` | Rename a media folder. |
| `delete_media_folder` 🔒 | Delete a media folder (its media are not deleted, just un-foldered). |
### Notifications
| Tool | What it does |
| --------------------------------- | ---------------------------------------------------------------------------------------------- |
| `list_notifications` | List in-app notifications for the account (paginated). |
| `count_unread_notifications` | Get the number of unread notifications. |
| `mark_notifications_read` | Mark notifications as read — specific ids, or all of them. |
| `archive_notification` 🔒 | Archive a single notification by ID. It leaves the inbox but is not erased. |
| `archive_notifications` 🔒 | Archive several notifications by ID in one call. They leave the inbox but are not erased. |
| `clear_read_notifications` 🔒 | Delete all notifications that have already been read. |
| `get_notification_preferences` | Get the per-event notification delivery preferences (which channels fire for each event type). |
| `update_notification_preferences` | Change how you are notified for specific events. |
| `list_notification_channels` | List the account's configured Slack/Discord notification channels (webhook + enabled state). |
| `set_notification_channel` | Configure a Slack or Discord notification channel with an incoming-webhook URL. |
| `delete_notification_channel` 🔒 | Remove a configured Slack or Discord notification channel. |
### Pages
| Tool | What it does |
| ---------------- | -------------------------------------------------------------------- |
| `list_pages` | List pages for a project or template, ordered by position |
| `create_page` | Add a page to a project or template. Appended at the end by default. |
| `update_page` | Update a page — only include the fields you want to change |
| `delete_page` 🔒 | Delete a page by ID |
### PDF
| Tool | What it does |
| ---------------- | --------------------------------------------------------------------------------------------------------------------- |
| `generate_pdf` | Queue a PDF render of a project. Returns a job\_id — poll get\_pdf\_status until it completes, then download the URL. |
| `get_pdf_status` | Poll a PDF job. status is pending → processing → complete (with a url) or failed. |
### Projects
| Tool | What it does |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `list_projects` | List report/dashboard projects for the account, optionally filtered by client. |
| `get_project` | Get a single project by ID |
| `create_project` | Create a new report/dashboard project for a client. |
| `update_project` | Update a project — only include the fields you want to change |
| `archive_project` 🔒 | Archive a project by ID. Its pages and widgets stay attached and come back with it. Restorable from the archive. |
| `archive_projects` 🔒 | Archive several projects by ID in one call. Restorable from the archive. |
| `duplicate_project` | Duplicate a project with a new name |
| `change_project_date_range` | Set the period a project reports on. Every data widget on it is re-fetched for the new range and the results are saved — widgets on their own custom range keep it. A rolling preset ("Last 30 Days")… |
| `refresh_project` | Re-fetch every data widget on a project with its current config and the project date range, saving the results. |
### Search
| Tool | What it does |
| -------- | ---------------------------------------------------------- |
| `search` | Search clients and projects by name (minimum 2 characters) |
### Templates
| Tool | What it does |
| ----------------------- | ---------------------------------------------------------------------------------- |
| `list_templates` | List project templates with optional filtering and pagination |
| `get_template` | Get a single template by ID |
| `create_template` | Create a template from an existing project. |
| `update_template` | Update a template — only include the fields you want to change |
| `archive_template` 🔒 | Archive a template by ID. Restorable from the archive. |
| `list_template_widgets` | List the widgets that belong to a template (optionally filtered to a single page). |
### Themes
| Tool | What it does |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `list_themes` | List all themes available to the account (own + shared) |
| `get_theme` | Get a single theme by ID |
| `create_theme` | Create a new visual theme. Supply the complete tokens map (primary, font, radius, shadow, canvas, surface, chart1-10, etc.) — tokens are the single source of truth for every visual property. A theme… |
| `update_theme` | Update a theme — only include the fields you want to change. |
| `archive_theme` 🔒 | Archive a theme by ID. Projects using it fall back to the default. Restorable from the archive. |
### Users
| Tool | What it does |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `get_current_user` | Get the currently authenticated user profile |
| `list_users` | List all team members on the account |
| `invite_user` | Invite a new user to join the account. admin has full account access; clients gives read+write to assigned clients; readonly is view-only on assigned clients. |
| `update_user` | Edit a team member — only include the fields you want to change |
| `remove_user` 🔒 | Remove a team member from the account |
| `update_my_profile` | Update the authenticated user's profile — only include the fields you want to change |
| `update_my_avatar` | Update the authenticated user's profile picture |
| `change_my_email` | Change the authenticated user's email address |
### Widgets
| Tool | What it does |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `list_widgets` | List all widgets for a source (project or template). |
| `get_widget` | Get a single widget by ID. |
| `add_title_widget` | Add a title widget to a page. Position, width, and height use sensible defaults. |
| `add_text_widget` | Add a rich-text widget to a page. Position, width, and height use sensible defaults. |
| `add_image_widget` | Add an image widget to a page. Position, width, and height use sensible defaults. |
| `add_button_widget` | Add a button widget to a page. Position, width, and height use sensible defaults. |
| `add_embed_widget` | Add an embed widget to a page. Position, width, and height use sensible defaults. |
| `add_data_widget` | Add a DATA widget to a page and configure it, applying the same rules as the report builder: the datasource's defaults, the generated name, sort and row limit, and validation of the… |
| `update_title_widget` | Update a TITLE widget. |
| `update_text_widget` | Update a TEXT widget. Replaces the entire text content. |
| `update_image_widget` | Update an IMAGE widget. |
| `update_button_widget` | Update a BUTTON widget. |
| `update_embed_widget` | Update an EMBED widget. |
| `update_data_widget` | Update a DATA widget — its name, datasource, data view, metrics, dimensions, filters, advanced settings, chart type, date range, sort and row limit. |
| `move_widget` | Move or resize a widget. Works for any widget type. Pass only the dimensions you want to change. |
| `delete_widget` 🔒 | Delete a widget by ID. |
| `delete_widgets` 🔒 | Delete multiple widgets by ID in one call. |
| `refresh_widgets` | Re-fetch specific widgets with their saved config and save the results. |
| `datasource_resources` | List the selectable values behind a widget's advanced settings and filters — campaigns, ad sets, forms, videos, alerts, and so on. |
### Workflows
| Tool | What it does |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `create_client_with_project` | Create a new client and its first report/dashboard in one step. |
| `create_project_from_template` | Create a report or dashboard for an existing client by cloning a template (its pages + widgets). |
| `add_project_section` | Add a saved section (asset) to a project — works for both reports and dashboards. |
| `audit_project_health` | Audit a report or dashboard: report its connected data sources and automation state, and flag likely issues (no data sources connected, paused automations). |
🔒 = flagged destructive, so a client can prompt before running it.
## Conventions
* **Identifiers** — calls return IDs the agent chains into later calls. It is instructed to refer
to records by name in chat, never by ID.
* **Multi-tenancy** — every call is scoped to the authenticated account. You never pass an
`account_id`.
* **Discovery first** — `datasources`, then `describe_datasource`, before configuring a data
widget: the second returns that datasource's data views, metrics, dimensions and required settings.
* **Metrics and dimensions are objects** — pass `[{ "value": "clicks" }]`, not `["clicks"]`. Only
`value` is required; Oviond fills in the rest from the catalog. The same shape is used by the
widget, goal and calculated-metric tools.
* **Data is fetched server-side** after a widget is written. `refresh_widgets` or `refresh_project`
force it.
## Reference
Each tool wraps an Oviond REST operation. For exact parameters and response shapes, see the
[API Reference](/api/introduction).
# Troubleshooting
Source: https://docs.oviond.com/mcp/troubleshooting
What the common Oviond MCP errors mean and how to recover from them.
Every failure returns the standard error envelope, so an agent can read the
message and correct itself. The ones below are the errors worth recognising.
## Connection and access
### "Invalid or expired token"
The OAuth access token has expired or been revoked. Reconnect the connector — your
client re-runs the sign-in flow and gets a fresh token. If it keeps happening
immediately after connecting, check that the account still exists and the user
still has access to it.
### "Your plan does not include API/MCP access"
MCP is included on subscription plans; lifetime plans need the API add-on. The
sign-in completes and then the first tool call is rejected, so this reads like a
broken connector when it's a billing state. Check **Settings → Billing**.
### "MCP access is disabled for this account"
An account-level switch under **Settings → Security** is off. Turning it off is an
instant disconnect — existing tokens stop working straight away. Turn it back on
and reconnect.
### Rate limited (429)
Programmatic access is capped at **300 requests per minute per account**, shared
across API keys and MCP. The response carries `Retry-After`. An agent looping over
many clients or widgets is the usual cause — batch where a bulk tool exists
(`delete_widgets`, `archive_projects`) instead of calling one at a time.
The web app is never rate limited. This applies only to programmatic access.
## Configuring data widgets
### "Invalid widget configuration: …"
`add_data_widget` and `update_data_widget` validate the whole selection the way
the report builder does. The message names the specific problem — a metric that
doesn't belong to the chosen data view, a missing required setting, a dimension
that must be the only one.
Recover by calling `describe_datasource` for that datasource. It returns the data
views, the metrics and dimensions inside each, and the `advanced` keys a view
requires. A metric is only valid inside its own data view.
### The widget renders demo data
Expected, not an error. A widget pointed at a datasource the client has not
connected shows demo numbers so the layout is still reviewable.
Fix it by connecting the datasource and linking it to that client:
```
connected_datasources → is it connected at account level?
link_datasource → point this client at it
refresh_widgets → replace the demo numbers
```
### The widget is stuck on `loading`
Give it a moment. The fetch runs server-side after the write and the tool returns
before the numbers land.
If it stays there, the fetch failed rather than the write. Run `test_connection`
for that client and datasource — an expired token is the usual cause.
## Datasources
### "This … connection shows no accounts, so there is nothing to link"
The connection exists but the vendor returned no accounts. That means the
connection is broken — an expired token, revoked access, or a login with no
accounts on it. `test_connection` says which. Reconnect it in the app.
### `create_connection` refuses a datasource
Google, Meta, LinkedIn, TikTok and the rest sign in on the vendor's own website,
which needs a browser an agent doesn't have. Connect those once in the Oviond app;
everything afterwards — linking to clients, building widgets, pulling data — works
over MCP.
### "A … connection called '…' already exists"
Names identify connections, so re-using one would replace its credentials for
every client using it. Pick a different name, or rename the existing one with
`rename_connection`.
## Archived, not gone
### "I archived the wrong thing"
Anything named `archive_*` is recoverable. `list_archive` shows what's there and
`restore_from_archive` brings it back, with its children — restoring a client
restores its projects, restoring a project keeps its pages and widgets attached.
The tools named `delete_*` really do destroy: widgets, pages, folders, media
folders, datasource connections, notification channels, API keys, email senders
and templates, custom domains, and removing a user. Those have no undo.
`archive_notification` sits in between — it leaves your inbox and isn't erased,
but it doesn't appear in the archive list yet either.
## Permissions
### "Access denied" on a client or project
The signed-in user's role limits which clients they can see. A user scoped to
specific clients can only act on those. Check the user's role under
**Settings → Users** — the MCP connection has exactly the permissions that person
has in the app, no more.
## Still stuck
* [Available tools](/mcp/tools) — the full catalog
* [Playbooks](/mcp/playbooks) — the common jobs end to end
* [Skills](/mcp/skills) — install the workflow guide so your agent makes fewer
wrong turns in the first place
# Bulk delete
Source: https://docs.oviond.com/media/bulk-delete
Soft-delete multiple media items at once.
Bulk delete is the fastest way to clear out leftover screenshots, duplicate uploads, or files from an offboarded client.
Media is **soft-deleted** — each row is marked deleted (`is_deleted`) and the underlying S3 file is retained. Anything that references a deleted item shows a broken image until you point it at a different file. Review references first if you're removing a file currently in use.
## In the Media Library
Open the **Media Library** modal from any image picker and stay on the **Library** tab.
Check the checkbox on each tile you want to remove. Selecting two or more enables the bulk action.
Click **Archive (N)** to soft-delete the selected items.
Bulk archiving requires the **Edit shared assets** permission. Uploading and selecting media are open to all roles.
Archived items are recoverable from **Settings → Archive** — filter by **Media** and restore.
## API
`DELETE /v1/media/bulk` with an `ids` array soft-deletes those items. Only items in your account are affected.
# Delete media
Source: https://docs.oviond.com/media/delete
Soft-delete a single media item.
Deleting a media item soft-deletes it: the row is marked deleted (`is_deleted`) and the underlying S3 file is retained, so nothing is permanently destroyed at this step. You can restore it later from **Settings → Archive**.
Open the **Media Library** modal from any image picker and stay on the **Library** tab.
Click the `⋯` menu on the tile.
The item is soft-deleted and removed from the library grid.
Archiving a media item requires the **Edit shared assets** permission.
## Restore an archived item
Soft-deleted media stays recoverable. Go to **Settings → Archive**, filter by **Media**, and restore the item to return it to the library.
## What references see
Anything that referenced the deleted item — a widget image, a report cover, or a branding logo — shows a broken image until you edit it and pick a different file.
## API
`DELETE /v1/media/{id}` soft-deletes a single item. It returns `404` if the item doesn't exist (or is already deleted) in your account.
# Folders
Source: https://docs.oviond.com/media/folders
Group related media into folders via the API.
Media folders group related items in your library. Each folder has an `id`, a `name`, and an `account_id`, and media items track folder membership through a `folders` array.
Folders are an API-level feature. The in-app **Media Library** modal shows a single flat grid and doesn't expose folder browsing or management — use the API to create, rename, and assign folders.
## Create a folder
`POST /v1/media/folders` with a `name` creates a folder and returns its `id`.
## List folders
`GET /v1/media/folders` returns your folders, newest first.
## Rename a folder
`PUT /v1/media/folders/{id}` with a new `name` renames the folder. Returns `404` if the folder doesn't exist in your account.
## Delete a folder
`DELETE /v1/media/folders/{id}` deletes the folder. The folder's `id` is removed from every media item's `folders` array first, so no items are left pointing at a deleted folder.
Deleting a folder **does not delete the media inside it** — those items remain in your library with the folder removed from their `folders`.
## Move items into a folder
`PUT /v1/media/group` with `ids` (the media items to move) and `folder_id` sets each item's folder membership to that single folder. This replaces any existing folder assignment rather than appending.
# List media
Source: https://docs.oviond.com/media/list
Browse the images in your Media Library.
The **Media Library** modal lists your uploaded images in a flat, paginated grid, most recent first. Open it from any image picker (an **Image** widget's source, a report cover, or a branding logo control), then use the **Library** tab.
## Browsing
* **Search** — the **Search media…** box matches by `name` (server-side).
* **Pagination** — the grid shows a page of items at a time, with **Prev** and **Next** controls.
## What's on a tile
| Field | Description |
| ----------- | ------------------------------------------------------------ |
| Thumbnail | A preview of the image. |
| `name` | The item's display name — see [Rename media](/media/update). |
| `size` | The file size in bytes. |
| `mime_type` | The image's content type. |
| `url` | The direct file URL. |
## Per-item actions
Each tile has a `⋯` menu with:
* **Crop** — open the cropper to adjust the image.
* **Archive** — soft-delete the item. See [Delete media](/media/delete).
To pick an image, select a tile (or double-click) and choose **Use selected**.
## API
`GET /v1/media` lists your media, newest first, in pages. Query parameters: `page`, `limit` (max 100), `search` (matches `name`), and `folder_id`. The response includes a `meta` object with `page`, `limit`, and `total`. Soft-deleted items (`is_deleted`) are excluded.
# Rename media
Source: https://docs.oviond.com/media/update
Change the display name of a media item.
Renaming a media item updates its display name only. The underlying file keeps the same `url`, so widgets and branding that reference the item don't need to be re-wired.
## What rename changes
* The `name` shown in the Media Library, in image pickers, and in search.
## What rename doesn't change
* The file's `url` and S3 `key` (both are immutable).
* The `size` or `mime_type`.
* Any widget or branding that references the file — it keeps working.
Renaming also runs as part of the upload flow: after the file uploads, Oviond confirms the item's display name with the same update call.
## API
`PUT /v1/media/{id}` with a `name` renames the item. It returns `404` if the item doesn't exist in your account.
# Upload media
Source: https://docs.oviond.com/media/upload
Upload images into the Oviond Media Library.
The **Media Library** is where the images you reference from widgets, report covers, and branding live. It isn't a standalone page — it opens as a modal wherever you choose an image, such as an **Image** widget's source, report cover and theme backgrounds, and the company, account, and client branding settings.
Uploads go to S3-backed storage. Oviond generates a pre-signed URL, the file uploads directly from your browser, and the metadata row is committed once the upload finishes.
Trigger it from any image picker — for example, an **Image** widget's source or a branding logo control.
The modal has a **Library** tab and an **Upload** tab. Open **Upload**.
Drag images onto the drop-zone or click to open the file picker. You can select multiple files at once.
Click **Upload files**. Each file uploads in parallel, then appears in the **Library** tab.
## Supported files
The Upload tab accepts images only: **JPEG, PNG, GIF, SVG, and WebP**.
## Limits
* Up to **25 MB** per file.
* Up to **10 files** per upload batch.
For logos and branding, prefer **SVG** — it stays crisp at every report resolution and renders cleanly in PDF export.
## API
The upload flow is two steps. `POST /v1/media/presigned-url` (send `file_name`, `content_type`, and `size`) creates the media row and returns an `upload_url`, the S3 `key`, and the new `media_id`. Upload the file with an HTTP `PUT` to `upload_url`, then confirm the display name with `PUT /v1/media/{id}`.
# Preferences
Source: https://docs.oviond.com/notifications/preferences
Choose which events notify you and through which channels.
**Preferences** are per-user — each team member controls which events notify them and over which channels. Manage them under **Settings → Notifications** (`/settings/notifications`).
## Channels
* **In-app** — the bell icon. Always on for every event, so there's no toggle for it.
* **Email** — to your account email. Personal, toggled per event.
* **Slack** — posts to your account's Slack webhook.
* **Discord** — posts to your account's Discord webhook.
The settings matrix shows a toggle column for **Email**, **Slack**, and **Discord**. Slack and Discord are **team channels** — their toggles stay disabled until an admin connects the webhook for the account (see below).
## Events
Events are grouped by category. Toggle Email, Slack, and Discord per event.
| Category | Event | Event key |
| -------------- | -------------------- | ------------------------ |
| Data Sources | Data source issue | `datasource_error` |
| Automations | Automation sent | `automation_success` |
| Automations | Automation failed | `automation_failed` |
| PDF Export | Export ready | `pdf_completed` |
| PDF Export | Export failed | `pdf_failed` |
| Email Delivery | Email bounced | `email_bounced` |
| Account | Email changed | `email_changed` |
| Account | Role changed | `role_changed` |
| Account | Removed from account | `removed_from_account` |
| Account | Invite accepted | `invite_accepted` |
| Account | Domain verified | `custom_domain_verified` |
## Configure Slack and Discord
Slack and Discord are **account-wide** delivery channels backed by an incoming webhook. Configuring them requires the **manage account** permission (admin).
From **Settings → Notifications**, open the Slack or Discord channel.
Enter the incoming webhook URL for your Slack or Discord workspace.
Once enabled, any user can route events to that channel from their own preferences.
Preferences are per-user — your toggles don't affect teammates. Slack and Discord webhooks, however, are account-wide: one webhook per channel for the whole account, managed by an admin.
# View notifications
Source: https://docs.oviond.com/notifications/view
In-app alerts from your Oviond account.
Oviond surfaces events as **Notifications** in the bell icon, with an unread badge showing your count. Notifications cover things you may need to react to, such as:
* A data source failed to load widget data
* An automation finished or failed
* A PDF export is ready or failed
* An email bounced
* An account change — your role changed, an invite was accepted, or you were removed from an account
Notifications are **per-user** — each person sees their own. Each one carries a severity (`info`, `warning`, `error`, or `success`) and belongs to a category. Open the inbox at `/notifications`; the bell and unread badge live in the sidebar user menu.
## In the inbox
* **Filter by category** — All, Data Sources, Automations, PDF Export, Email, or Account.
* **Mark as read** — click a notification to mark it read, or select several and **Mark as read** in bulk.
* **Delete** — select the notifications you want to remove and delete them in bulk.
Choose which events reach you, and through which channels, under **Settings → Notifications**. See [Preferences](/notifications/preferences).
# Onboarding
Source: https://docs.oviond.com/onboarding/overview
The 6-step setup flow shown after your first sign-in.
After your first sign-in, Oviond opens a full-page setup flow at `/onboarding`. It walks you through six steps: your details, your company, and your first client. The flow is blocking — until you finish it, every other page redirects you back here, and there is no skip or dismiss control. Most steps are a single field, so the whole thing takes about a minute.
Once you finish, Oviond creates your account, company, theme, first client, and a starter project, then drops you on that client's **Projects** page. The flow is gated by the `account.onboarding` flag, which the backend sets when your account is created, so the flow never appears again.
## The 6 steps
Enter your **Full Name**. This is your name as it appears throughout the app and in activity-log entries.
Enter your **Company name**. This is the company name used on report headers, email footers, and shared links unless you override it with [white-label branding](/company/branding).
Enter your **Website** (for example, `yourcompany.com`). If you leave off `http://` or `https://`, Oviond adds `https://` automatically.
Pick one option: **1 - 5**, **6 - 20**, **21 - 100**, or **100+**. This isn't a hard limit — it's used to tailor your setup.
Enter your first client's details. **Client Name** and **Client Website** are required. You can also set **Select Currency** and **Client Timezone**. This step only collects the details — Oviond creates the client in the final step.
Oviond finalizes your setup automatically. You'll see **Setting up your workspace** while it detects your branding, applies your theme, and prepares your first project. No action is needed.
## Buttons
* Steps 1 to 4 show a **Continue** button. It stays disabled until the field is filled in and valid. Pressing Enter also advances these steps.
* Step 5 shows a **Finish** button. It stays disabled until the client form is valid.
* Step 6 has no buttons. If finalizing fails, it shows a **Retry** button.
## What happens next
When you finish, Oviond makes a single `POST /v1/onboarding` call that:
* Creates your account and saves your name, company name, and website.
* Records your client-count bucket on the account.
* Applies a default theme.
* Creates your first client and a starter project.
* Sets the account's `onboarding` flag to done so the flow doesn't show again.
* Sends you to the new client's **Projects** page.
You can update your name later under [My account](/account/overview) and your company details under [Company](/company/overview).
## Troubleshooting
* **You can't advance** — each step validates its field before you can continue. Fix any inline error, then the button becomes active.
* **Website rejected** — enter a simple domain (for example, `yourcompany.com`). Leave off paths and trailing slashes.
* **The flow reappears on a different device** — it follows your account, not the device. Finish it on this device and it syncs.
* **Setup failed** — if the final step shows an error, click **Retry**. If your email is already registered, sign in instead of going through onboarding again.
# Add a page
Source: https://docs.oviond.com/pages/add
Add a new section page to a report.
A **page** is a section inside a report. Each page has its own grid layout and holds any number of widgets. Viewers move between pages to explore different parts of the report — for example, one page per marketing channel.
Pages apply to **reports** only. A dashboard is a single full-screen view with no pages, so the **Pages** tab appears only for projects of type **Report**.
Every report starts with at least one page. Add more at any time.
## Add a page
From the client's **Projects** tab, open the report.
In the editor sidebar, open the **Pages** tab.
Click **New page**. The page enters inline rename — type a clear name like *Google Ads — Overview* or *SEO Performance* and press Enter.
Plan pages before adding widgets. Grouping related data per page (one page per channel) keeps reports scannable for clients.
## API
`POST /v1/pages` adds a page to a project or template.
# Delete a page
Source: https://docs.oviond.com/pages/delete
Remove a page from a report.
Deleting a page removes the page and **every widget on it**.
In the report editor, open the **Pages** tab.
Click the menu on the page you want to remove.
Choose **Delete page**. The page and its widgets are removed.
A report must keep at least one page. Deleting a page can't be undone — duplicate it first if you might need the layout again.
## API
`DELETE /v1/pages/{page_id}` removes a page and its widgets.
# Duplicate a page
Source: https://docs.oviond.com/pages/duplicate
Copy a page and its widgets.
Duplicating a page copies the page and every widget on it, so you can reuse a layout without rebuilding it.
In the report editor, open the **Pages** tab.
Click the menu on the page you want to copy.
Choose **Duplicate page** to copy the page and its widgets, or **Add page below** to insert a fresh empty page right after it.
Build one channel page exactly how you like it, then duplicate it for each remaining channel and swap the data source on each copy.
# Rename & reorder pages
Source: https://docs.oviond.com/pages/rename
Rename a page and change the order pages appear in a report.
## Rename a page
Choose **Rename page** from the page's menu and edit the name inline, or rename a page right after you create it. The name shows in the report's page navigation and in the table of contents on the shared report.
## Reorder pages
Drag pages in the **Pages** tab to change their order. Each page keeps a `position` value that sets where it appears in the report.
Order pages the way you'd walk a client through the report — a summary page first, then a page per channel.
## API
`PUT /v1/pages/{page_id}` updates a page, including its name and `position`.
# Add Project
Source: https://docs.oviond.com/projects/add
Create a new report or dashboard inside a client's workspace.
A **project** is a named report or dashboard that lives inside a specific client's workspace. Every project holds its own pages and widgets and can be shared publicly via a link.
From your Clients list, open the client you want to create the project under. Everything you create from inside the client's workspace is scoped to that client — you don't pick a client again.
On the client's **Projects** tab, click **Add Project** to open the new-project panel.
Pick **Start from scratch** or **Start from a template**. Starting from a [template](/templates/list) pre-populates pages and widgets you can customize.
When starting from scratch, choose **Dashboard** (a live view that always shows the latest data) or **Report** (a point-in-time report for a specific date range).
The name appears on the shared link, in PDF exports, and in the email subject when the project is automated.
Click **Create project**. Oviond opens the project editor.
A **Report** is paged and has a [Pages](/pages/add) tab; a **Dashboard** is a single full-screen view with no pages.
# Archive Project
Source: https://docs.oviond.com/projects/archive
Soft-delete a project and restore it from the Archive.
Archiving a project removes it from your active **Projects** list without destroying the project's pages, widgets, or settings. When you archive a project, Oviond also archives everything under it — pages, widgets, and automations. You can restore the project from the [Archive](/archive/view) at any time.
## Archive a project
From the client's **Projects** tab, open the three-dot menu on the project card, or open the project and use its header menu.
The project disappears from the active list and moves to the [Archive](/archive/view), along with its pages, widgets, and automations.
## Restore
From the Archive, find the project, click **Restore**, and it reappears under its original client with all pages and widgets intact.
Archiving a client also archives every project under it. Restoring the client restores those projects too.
## Permanent delete
Archived projects stay in the Archive until you permanently delete them — there's no automatic time-based purge. Permanent deletion is **admin-only** and is irreversible. Export anything you need first.
# Bulk Delete
Source: https://docs.oviond.com/projects/bulk-delete
Remove multiple projects at once.
Bulk delete speeds up cleanup when you're archiving a batch of old reports — for example, rolling over to a new fiscal year or removing drafts after a client offboards.
Deleted projects move to the [Archive](/archive/view) along with all their pages, widgets, and automations. You can restore them from the Archive at any time, or permanently delete them there. Permanent deletion is irreversible — export anything you need first.
Open the client whose projects you want to clean up.
Select the projects you want to remove using the project cards' checkboxes.
Check every project you want to delete.
Confirm the deletion. The selected projects and everything under them move to the Archive.
Each project you delete must belong to a client you have permission to edit. Read-only users and users scoped to other clients can't delete it.
# Duplicate Project
Source: https://docs.oviond.com/projects/duplicate
Copy a project — pages, widgets, and settings — under a new name.
Duplicating creates an exact clone of a project, including every page, widget, and setting. The copy stays under the **same client** as the original. Useful for:
* Reusing a reporting structure for a new month
* Creating a variant without editing the original
* Testing layout changes on a copy before applying to the live report
On the client's **Projects** tab, locate the project you want to copy.
Click the three-dot menu on the project card and choose **Duplicate**.
The **Duplicate Project** dialog opens pre-filled with `[original] (Copy)`. Edit the name if you like, then click **Duplicate**.
The duplicate keeps the original's client. A project can't be reassigned to a different client — to reuse the structure elsewhere, save it as a template and apply it under that client.
If you want a reusable starting point rather than a one-off copy, [create a Template](/templates/add) from the project instead — templates keep a live library you can re-apply to any future project.
# List Projects
Source: https://docs.oviond.com/projects/list
Browse, search, and filter the projects inside a client's workspace.
Every project lives inside a client. Open a client to reach its **Projects** tab, which lists every report and dashboard for that client. Use it to find, open, or manage any project.
## Filter and search
* **Search** — type in the search bar to match by project name.
* **Type filter** — show only **Reports** or only **Dashboards**.
* **Sort** — switch between recent activity, name, type, and date created.
## What's on a project card
| Element | Description |
| --------------- | ------------------------------------------- |
| **Name** | Click the name to open the project editor. |
| **Type** | Report or Dashboard badge. |
| **Automations** | Count of active automations on the project. |
| **Last edited** | Timestamp of the most recent save. |
Use consistent project naming — including month and year (e.g. *Paid Social — March 2026*) — to make the list searchable as it grows.
## Quick actions
From any project card's three-dot menu:
* **Open** — enter the editor.
* **Duplicate** — see [Duplicate Project](/projects/duplicate).
* **Share** — see [Share Project](/projects/share).
* **Delete** — moves the project to the [Archive](/projects/archive).
# Share Project
Source: https://docs.oviond.com/projects/share
Publish a project via a shareable public link.
Share a project with a client, stakeholder, or prospect via a public URL. The recipient opens the link in any browser — **no Oviond account required** — and sees the report with live data.
From the client's **Projects** tab, click the project.
The **Share** button sits in the top-right of the editor and opens the Share panel.
On the **Link** tab, click **Copy** to copy the share URL. The link points to `/shared/{short-id}` on your share host.
Under **Sharing Options**, keep **Link is Active** on so anyone with the link can view the report. Turn it off to disable the link.
Toggle **Enable Password** and set a passphrase, **Allow PDF Download** to let viewers export a PDF, and **Show Date Selector** to let viewers change the date range.
## Share tabs
The Share panel has four tabs:
* **Link** — copy the public link and configure sharing options.
* **Email** — send the report to recipients by email.
* **Download** — generate a PDF (available when **Allow PDF Download** is on).
* **Embed** — copy an `