# Yurbi API — Full Developer Documentation > Reference for the Yurbi API — authenticate, manage users, configure apps, and refresh licenses on your own Yurbi server. JSON over HTTPS. This is the complete, self-contained reference for the Yurbi API. Every endpoint is an HTTP `POST` that accepts and returns JSON and runs on your own self-hosted Yurbi server — no data leaves your infrastructure. Authenticate once with `DoLogin` to receive a session token, then pass that token on every other call. The base URL is your own instance; the path is `/api` on Linux/Docker and `/yurbi/api` on Windows. Source docs: https://developers.yurbi.com/ =============================================================== GETTING STARTED =============================================================== # Introduction Source: https://developers.yurbi.com/ ## What the Yurbi API is The Yurbi API lets your application drive a Yurbi instance programmatically: authenticate users, create and manage users and groups, configure data security, run reports, and embed dashboards directly in your product. It runs on **your own Yurbi server** — no data leaves your infrastructure. The API is intentionally simple: - **One transport.** Every endpoint is an HTTP `POST` that accepts and returns JSON. - **One base path.** All endpoints live under `https://your-yurbi-server.com/api/...`. - **One auth model.** You log in once to get a *session token*, then pass that token on every other call. ## What you can do with it - **Embed analytics** — drop a Yurbi dashboard or report into your own app, branded as yours, scoped to each customer's data. See the [Embedding guide](/guides/embedding/). - **Single sign-on** — sign users in with no second login using a session token. See [Single Sign-On](/guides/single-sign-on/). - **Provision access** — create users, build security groups, and assign roles so each customer sees only what they should. - **Enforce isolation** — attach groups to AppShield data-security policies. - **Automate operations** — configure email, instance settings, and licensing as part of your own deployment pipeline. ## Where to go next 1. **[Quickstart](/quickstart/)** — make your first successful call in a few minutes. 2. **[Authentication & sessions](/authentication/)** — how tokens work and stay alive. 3. **[Conventions & errors](/conventions/)** — the patterns shared across every endpoint. 4. **[API Reference](/reference/)** — every endpoint, with live, runnable examples. > The Reference page has a built-in "Try it": enter your server's Base URL and a > token, edit any request, and send it live (or copy a ready-to-run cURL). # Quickstart Source: https://developers.yurbi.com/quickstart/ ## 1. Log in to get a session token Every call needs a session token. Get one by posting your credentials to `DoLogin`. Replace the host with your own Yurbi server. ```bash curl -X POST "https://your-yurbi-server.com/api/login/DoLogin" \ -H "Content-Type: application/json" \ -d '{ "bolForceLogin": true, "isGuest": false, "UserId": "admin", "UserPassword": "your-password" }' ``` A successful response has `ErrorCode: 0` and your token at `LoginSession.SessionToken`: ```json { "ErrorCode": 0, "ErrorMessage": "", "LoginSession": { "SessionToken": "LVPACMJFBMZKUHRIXMQSTUZUY", "isGuestSession": false, "SessionExpir": "2025-09-02T13:27:43.382837-04:00" } } ``` Bad credentials return `ErrorCode: 101` with "Login Failed - Username or Password is invalid." and a null `LoginSession`. ## 2. Use the token on a call Pass the token in the JSON body of every other request — it is **not** an HTTP header. For example, list the users on the instance: ```bash curl -X POST "https://your-yurbi-server.com/api/Contact/GetContactList" \ -H "Content-Type: application/json" \ -d '{ "sessionToken": "LVPACMJFBMZKUHRIXMQSTUZUY" }' ``` That's the whole pattern: **log in once, reuse the token.** > **Linux/Docker vs Windows paths.** These examples use the Linux/Docker base > `/api`. On Windows (IIS), Yurbi is served under `/yurbi`, so the path is > `/yurbi/api/...` (e.g. `/yurbi/api/login/DoLogin`). See > [Conventions](/conventions/#platform-where-yurbi-is-served), or just use the > platform toggle on the [Reference](/reference/) page. ## 3. Try it without writing code Open the [API Reference](/reference/), paste your Base URL and token into the bar at the top, and every code sample updates with your values. Hit **Send** to run a call live against your server, or copy the ready-to-run cURL. ## Next - [Authentication & sessions](/authentication/) — keeping tokens alive, logging out. - [Conventions & errors](/conventions/) — the rules shared by every endpoint. - [Embedding guide](/guides/embedding/) — put a dashboard in your app. # Authentication & sessions Source: https://developers.yurbi.com/authentication/ Every Yurbi API call except [`GetInstallationID`](/reference/#get-installation-id) requires a session token, sent as a field in the request body. ## Getting a token [`DoLogin`](/reference/#do-login) exchanges credentials for a token: ```bash curl -X POST "https://your-yurbi-server.com/api/login/DoLogin" \ -H "Content-Type: application/json" \ -d '{ "bolForceLogin": true, "isGuest": false, "UserId": "apiuser", "UserPassword": "YOUR_PASSWORD" }' ``` The token is in `LoginSession.SessionToken`, and `LoginSession.SessionExpir` gives the moment it lapses. Call this from your server so credentials never reach a browser. The response also describes the signed-in user: their groups, their application roles, and the instance's licensed features. It is around 200 KB, because it includes the interface phrase table. ## One session per user **Yurbi maintains a single session per user account.** Each successful login issues a new token and ends that user's previous session. A token from an earlier login stops working and returns `ErrorCode 101`. This shapes how an integration should be built: - **Cache the token on your server and reuse it** across requests, rather than calling `DoLogin` per request. - **Give each integration its own Yurbi user.** A scheduled export, an embedded dashboard and an interactive application should not share one account. - **When embedding for end users, create a Yurbi user per end user.** Sharing one account across several people means each new sign-in ends the previous person's session. ## Session lifetime A session lasts for the instance's `SESSION_TIMEOUT`, which is 20 minutes by default and readable through [`GetAppSettings`](/reference/#get-app-settings). The window is a rolling one: **every authenticated call moves the expiry forward** to the time of the call plus the timeout. An integration that makes regular requests keeps its own session alive. Two endpoints manage the session explicitly: - [`CheckSession`](/reference/#check-session) reports whether a token is still valid. `ErrorCode 0` means valid; `ErrorCode 101` means expired or unknown. - [`RefreshSession`](/reference/#refresh-session) extends a session without performing any other work — useful for a dashboard left open with no traffic. [`DoLogout`](/reference/#do-logout) ends a session immediately. Call it when a short-lived script finishes. ## Handling expiry An expired token shows up in one of two ways: a `204` response with an empty body, or `ErrorCode 101`. Handle both by logging in again and retrying. ``` if response is empty (204) or ErrorCode == 101: token = DoLogin(...) # replaces any earlier session retry the request once ``` Because a fresh login ends the user's previous session, a retry loop should be per-account rather than per-request: two workers sharing an account will repeatedly evict each other. ## Permissions The built-in `admin` account is a super-admin and bypasses application and group permissions. Any other administrator must be granted a role on each application it uses and added to the groups whose content it needs. See [Permissions and the super-admin account](/conventions/#permissions-and-the-super-admin-account) for what to grant a service account. ## Guest sessions Set `isGuest` true to create a guest session for anonymous content. Guest sessions are also returned by `DoLogin`, and `LoginSession.isGuestSession` identifies them. For public content with no sign-in at all, enable anonymous view on the item and use the public view URL instead — see [Embed dashboards & reports](/guides/embedding/). ## Reserved accounts The `scheduler` and `yurbi` accounts are reserved for internal services and cannot sign in through the API. # Conventions & errors Source: https://developers.yurbi.com/conventions/ ## Requests Every endpoint in this reference is a **`POST`** carrying a JSON body, and every authenticated call takes the session token as a **field in that body** rather than a header: ```bash curl -X POST "https://your-yurbi-server.com/api/Session/CheckSession" \ -H "Content-Type: application/json" \ -d '{ "sessionToken": "YOUR_SESSION_TOKEN" }' ``` ### Platform: where Yurbi is served | Deployment | API base | |---|---| | Linux / Docker | `https://your-server.com/api` | | Windows (default) | `https://your-server.com/yurbi/api` | | Windows (IIS root web) | `https://your-server.com/api` | Endpoint paths are case-insensitive. ## Status codes Yurbi reports application errors **in the response body with a 200 status**. The HTTP status tells you whether the request reached the endpoint, not whether it succeeded. | Status | Meaning | |---|---| | `200` | The call reached the endpoint. Check the body for an error code. | | `204` | Empty response. The session token was rejected, or the caller lacks permission for the object. | | `404` | No such path. Check the endpoint name and the platform prefix. | | `500` | A required parameter was missing from the body. | A `204` with an empty body is the most common sign of an expired token. Confirm with [`CheckSession`](/reference/#check-session). ## Error reporting Most endpoints return an envelope with `ErrorCode` and `ErrorMessage`, where `0` means success: ```json { "ErrorCode": 0, "ErrorMessage": "" } ``` Three variations appear across the API: - **Per-item errors.** List endpoints return a bare array, and each item carries its own `ErrorCode`. There is no wrapper object around the array. - **Alternative field names.** Some endpoints use `ERROR_CODE` / `ERROR_MESSAGE`, `error_code` / `error_message`, `returncode` / `message`, or `Code` / `Message`. Each endpoint page shows the shape it returns. - **`HasError` on report execution.** [`GetReportData`](/reference/#get-report-data) reports failures through `HasError` and leaves `ErrorCode` at `0`. **When you run a report, branch on `HasError`.** ### Error codes | Code | Meaning | |---|---| | `0` | Success | | `101` | Login failed, or the session has expired | | `200` | No licence available for the requested action | | `586` | The report does not exist | | `9000` | Unexpected exception. The request was malformed or a required field was missing | | `9001` | The endpoint could not complete the request | | `9002` | The registered server could not be reached | ### Bare values Some endpoints return a single value rather than an envelope, and **that value is served as plain text, not JSON**. `JSON.parse()` will fail on these responses — read the body as text instead. ``` POST /api/library/FavReport -> 0 POST /api/RegServers/TestConnection -> Passed POST /api/Group/AddUser -> User Added Successfully. POST /api/LicenseManager/GetInstallationID -> 4446-4836-3034-3631-4452-3666 ``` [`DoLogout`](/reference/#do-logout) returns `0`, [`GetSQL`](/reference/#get-sql) returns the generated SQL, and [`TestConnection`](/reference/#test-connection) returns `Passed` or a failure message. Each endpoint page shows its exact response. An empty array means either no matching records or a rejected token, so check the session when an empty result is unexpected. ## Working with objects: fetch, modify, send Endpoints that create, update or delete an object take the **whole object**, not an ID. The pattern is the same throughout the API: 1. Fetch a starting object — a `New…` template when creating, or a `Get…` call when changing or removing something that exists. 2. Modify the fields you care about. 3. Send the complete object back. ``` # create a user POST /api/Contact/NewContact -> template POST /api/Contact/SaveContact -> { user: } # delete a user POST /api/Contact/GetContactList -> find the user object POST /api/Contact/DeleteContact -> { user: } ``` Building an object by hand tends to omit collections the endpoint expects, which surfaces as `ErrorCode 9000`. Starting from a template avoids that, and keeps your integration working as fields are added in later releases. Create and update are the same call on most objects, distinguished by the identifier: send `null` (or `""` for reports) to create, or an existing ID to update. ## Permissions and the super-admin account The built-in `admin` account is a **super-admin**. It bypasses application and group permissions entirely, so every API call succeeds regardless of how content is scoped. **Every other administrator is subject to permissions**, including one you add to the Administrators group. Before an integration user can work with an application through the API, grant it a role on that application — Architect for App Builder work, for example — and add it to the groups whose content it needs to reach. If you register a new application, existing administrators will not see it until they are granted a role on it. This matters when moving from a proof of concept to production: work that succeeded under `admin` can return empty results or `204` responses under a purpose-made service account that has not been granted access. ## Response size Responses are not paged. Several endpoints return substantially more than they appear to: - [`DoLogin`](/reference/#do-login) returns around 200 KB, most of it the interface phrase table. - [`GetApplicationList`](/reference/#get-app-list) and [`GetAllSecurityGroups`](/reference/#get-all-security-groups) embed full user records for everyone they touch. - [`GetReportData`](/reference/#get-report-data) returns every row the report produces. A detail report over a large table can return several megabytes. Where volume matters, run reports built with a `TopN` limit or an aggregate rather than fetching detail rows and reducing them in your own code. ## Field type codes Report metadata describes each field with a short code, in `Fieldtype` and `yurbitype`. The full list is available from [`GetDataTypes`](/reference/#get-data-types). | Code | Meaning | |---|---| | `cha` | Character | | `num` | Numeric | | `dat` | SQL datetime — the client applies a timezone offset | | `dtz` | SQL datetime, no timezone conversion | | `doz` | Date only, no timezone conversion | | `udt` | Unix datetime | | `tsp` | Oracle timestamp | | `ddn` | Drill-down field | | `lnk` | Link field | | `flk` | File download link | | `for` | SQL formula field | | `cur` | Formatted as currency | | `per` | Formatted as a percentage | Date codes are not interchangeable. `dat` carries a time component and is offset for the viewer's timezone; `doz` is a plain date and is returned exactly as stored. ## Output types A report's `OutputType` — and the `itemtype` returned in library listings — identifies how the report is rendered. The current list is available from [`GetOutputTypes`](/reference/#get-output-types). | ID | Output | |---|---| | `0`, `1` | Data grid | | `2` | Chart | | `3` | KPI text | | `4` | KPI gauge | | `6` | Pie chart | | `7` | Combo chart | | `8` | Pivot grid | | `9` | Tree map | | `10` | Vector map | | `11` | Skyline | | `12` | Aggregate grid | | `13` | Advanced pivot grid | | `14` | Chart v2 | Library listings return dashboards alongside reports, with `itemtype` `0`. Filter them out before passing IDs to report endpoints. ## Roles | ID | Role | Applies to | |---|---|---| | `0` | None | Group membership | | `1` | Admin | Group membership | | `2` | View | Group membership | | `3` | Modify | Group membership | | `4` | Delete | Group membership | | `5` | Builder | Application assignment | | `6` | Agent | Application assignment | | `7` | Architect | Application assignment | Roles 1–4 control what a user may do with content in folders scoped to a group. Roles 5–7 are assigned per application through `UserApplications` on [`SaveContact`](/reference/#save-contact) and consume a licence seat. ## Cross-origin requests The API returns `Access-Control-Allow-Origin: *`, so browser-based applications can call it directly. Because the session token travels in the request body, authenticate on your server rather than exposing credentials in client-side code. # Finding more endpoints Source: https://developers.yurbi.com/finding-endpoints/ ## What's documented here This reference focuses on the calls a software vendor actually needs: **authenticating users, provisioning them (users, groups, roles, AppShield policies), discovering content, and rendering or embedding it.** That's the stable, supported core. Behind the scenes, Yurbi exposes an API for **every action in the interface** — building reports, designing dashboards, scheduling delivery, managing data sources, and more. Those calls exist, but most aren't part of a typical embed/provision integration, so they're not documented here. ## How to discover any endpoint If you need to automate something you can do in the Yurbi UI, you can see exactly which call it makes using your browser's developer tools: 1. Open Yurbi in your browser and sign in. 2. Open **DevTools** (F12, or right-click → Inspect) and select the **Network** tab. 3. Filter to **Fetch/XHR**. 4. Perform the action in the Yurbi UI (e.g. favorite a report, save a dashboard). 5. Click the `/api/...` request that appears. The **Payload/Request** tab shows the URL and JSON body; the **Response** tab shows what comes back. 6. Replicate that request from your own code, passing your `sessionToken` in the body. Everything you find follows the same [conventions](/conventions/): `POST` + JSON, `sessionToken` in the body, the `ErrorCode` / `ErrorMessage` envelope, and the read-modify-write pattern for `Save*` calls. ## A caveat — and an offer Undocumented endpoints are internal: they can change between versions without notice, and their request/response shapes aren't guaranteed. The endpoints in this reference are the ones we intend to keep stable for integrators. If you find a call you'd like us to **document and support**, tell us what you're trying to accomplish — we're happy to help, and to add it here if it fits the embedding/provisioning story. # API spec & tooling Source: https://developers.yurbi.com/spec/ These files are generated automatically from the same source as this site, so they always match the published reference. Endpoints held back with a `draft` flag are excluded. ## Import into Postman 1. In Postman, choose **Import** and select the downloaded `yurbi-api.postman_collection.json` (or paste the URL `{{ site.url }}/yurbi-api.postman_collection.json`). 2. Open the collection's **Variables** tab and set: - **`baseUrl`** — your Yurbi host, e.g. `https://your-yurbi-server.com`. On a default Windows install add the `/yurbi` prefix: `https://your-yurbi-server.com/yurbi`. - **`sessionToken`** — leave empty. 3. Run **Authentication → Log in** (`DoLogin`) with your credentials. The collection captures the returned token into the `sessionToken` variable automatically, and every other request is ready to send. ## Import into Insomnia / Swagger UI / code generators Point any OpenAPI-aware tool at `{{ site.url }}/openapi.json`. The server URL in the spec is a placeholder — replace it with your own Yurbi host. The same file works with `openapi-generator` and similar tools to scaffold a typed client. ## For LLMs and answer engines If you're feeding these docs to an AI assistant, the [`llms.txt`]({{ site.url }}/llms.txt) index and the full [`llms-full.txt`]({{ site.url }}/llms-full.txt) corpus are the most useful entry points — both are also generated from the published endpoints. =============================================================== GUIDES =============================================================== # Single Sign-On Source: https://developers.yurbi.com/guides/single-sign-on/ ## The short answer We get asked constantly: *how do we do single sign-on with Yurbi?* For almost every integration the answer is the **session-token flow** — you already authenticate the user in your own app, so: 1. Call [`DoLogin`](/reference/#do-login) to get a session token. 2. Use that token to either **send the user into the full Yurbi interface**, or **embed a specific dashboard or report** in your app. No separate Yurbi login screen, no extra credentials for the user. > Want your identity provider (e.g. Microsoft Entra ID) to authenticate users and > have Yurbi log them in automatically — without your app calling `DoLogin`? That's > a special case: see [Header-based SSO (advanced)](/guides/sso-header/). Most > integrations don't need it. ## 1. Get a session token Call `DoLogin` (do this **server-side** so credentials are never exposed in the browser): ```bash curl -X POST "https://your-yurbi-server.com/api/login/DoLogin" \ -H "Content-Type: application/json" \ -d '{ "bolForceLogin": true, "isGuest": false, "UserId": "user", "UserPassword": "password" }' ``` The token comes back in `LoginSession.SessionToken`. (For more on tokens, see [Authentication & sessions](/authentication/).) > **Create a Yurbi user for each of your end users.** Yurbi maintains one session > per user account, so a new login ends that account's previous session. If several > people share a single Yurbi account, each sign-in signs the others out. Provision > users as part of onboarding — see > [Multi-tenant provisioning](/guides/multi-tenant-provisioning/). ## 2. Option A — Sign users into the full Yurbi interface Append the token to `sso.html` and the user lands inside Yurbi, already signed in. By default they land on the **Dashboard**; add `h` to choose a starting view: ``` Dashboard (default): https://your-yurbi-server.com/sso.html?s={sessionToken} Library: https://your-yurbi-server.com/sso.html?s={sessionToken}&h=1 Builder: https://your-yurbi-server.com/sso.html?s={sessionToken}&h=2 ``` Use this as the target of a button or redirect in your app. (Path shown is Linux/Docker; on a default Windows install use `/yurbi/sso.html`, and with the IIS root web configured it's `/sso.html` — see [Platform paths](/conventions/#platform-where-yurbi-is-served).) ## 3. Option B — Embed specific content Use the same token to drop a single dashboard or report into your own page via an iframe: ``` https://your-yurbi-server.com/embed.html?t=d&i={dashboardId}&s={sessionToken} ``` The [Embedding guide](/guides/embedding/) covers this in full — finding IDs, iframes, and report prompts. ## 4. Keep the session alive A token expires at its `SessionExpir` time, which defaults to 20 minutes after the last call. The window rolls forward on every authenticated request, so an active session generally sustains itself. For a session that may sit idle — a dashboard left open on a screen, for example — call [`RefreshSession`](/reference/#refresh-session) before the expiry to extend it, and [`CheckSession`](/reference/#check-session) to test validity. ## Endpoints used - [`DoLogin`](/reference/#do-login) — mint the token - [`RefreshSession`](/reference/#refresh-session) — keep it alive - [`CheckSession`](/reference/#check-session) — validate it # Multi-tenant provisioning Source: https://developers.yurbi.com/guides/multi-tenant-provisioning/ This guide covers the recommended structure for serving many customers from one Yurbi instance, and the API calls that create it. The shape is simple: **one security group per tenant, one library folder scoped to that group, and a data security policy that constrains every query to the tenant's own rows.** Users belong to exactly one tenant group, which is what keeps tenants invisible to one another. ## Before you start Two settings belong to the instance rather than to any tenant. **Turn on Tenant Mode.** Under **Settings → Server Settings → Application Settings**, enable Tenant Mode. It restricts Builder and Architect users to the All Users group, so they cannot reach across tenants when saving or sharing. Confirm it from the API with [`GetAppSettings`](/reference/#get-app-settings), which returns `TENANT_MODE_ENABLED`. **Keep shared folders on All Users only.** Any folder everyone should see — shared templates, for example — carries the All Users group and nothing else. With Tenant Mode on, users can view that content but cannot save, edit or delete within it. **Give your provisioning account the access it needs.** Only the built-in `admin` account bypasses application and group permissions. If you provision with a purpose-made service account, grant it a role on each application it will assign to users. See [Permissions and the super-admin account](/conventions/#permissions-and-the-super-admin-account). ## Onboarding a tenant ### 1. Create the tenant's security group ```bash curl -X POST "https://your-yurbi-server.com/api/Group/SaveSecurityGroup" \ -H "Content-Type: application/json" \ -d '{ "sessionToken": "YOUR_SESSION_TOKEN", "group": { "GroupId": null, "GroupName": "Tenant A", "GroupDescription": "All users for Tenant A", "GroupStatus": 0, "AllUsers": [], "AllRoles": [] } }' ``` The response carries the new `GroupId`. Keep it: the folder, the data tag and the policy all reference it. **Never create a group that spans tenants.** All Users is the only group tenants have in common. Because each user belongs to just their own tenant group, the people picker when scheduling a report, and the group picker when saving one, show that user only their own colleagues. ### 2. Create the tenant's library folder Start from [`NewLibraryFolder`](/reference/#new-library-folder), set `fname`, and scope the folder by giving it a single permission entry pointing at the tenant group: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "isShared": true, "currentUserId": "", "libraryfolder": { "id": 0, "fname": "Tenant A", "isParent": false, "isHidden": false, "InheritPermissions": false, "Permissions": [ { "LeftID": "", "RightID": "12", "RelationshipType": "fld_grp", "RelationType": "fld_grp", "PermissionTypeEnum": 2 } ] } } ``` `RightID` is the tenant's `GroupId`. A folder scoped this way is visible only to members of that group — it will not appear in [`GetAllLibraryTree`](/reference/#get-all-library-tree) for anyone else, including other administrators. Within their folder, a tenant's Builder can save reports and share them with colleagues, and nothing they do is visible to another tenant. ### 3. Create the data tag that carries the tenant's identity A data tag holds a value that varies per group. Row-level security then compares a column against that value, so one report serves every tenant. ```json { "sessionToken": "YOUR_SESSION_TOKEN", "datatag": { "ID": "", "Label": "tenantid", "TagGroup": "Tenancy", "DataTypeEnum": 1, "isGroup": true, "isUser": false, "isActive": true, "DefaultValue": "NONE", "Contacts": [], "Index": 0, "SecurityGroups": [ { "LeftID": "", "RightID": "12", "RelationshipType": "tag_grp", "RelationType": "tag_grp", "Option1": "TENANT-A", "PermissionTypeEnum": 0 } ] } } ``` `RightID` is the tenant's group and `Option1` is that tenant's value. Create the tag once, then add a `SecurityGroups` entry per tenant as you onboard them. `DefaultValue` applies to anyone with no assigned value. Setting it to something that matches no rows means a misconfigured user sees nothing rather than everything. **Alternative: profile tags.** Instead of a data tag you can put the value directly on the user, in `Tag1` through `Tag4`, and reference it as `/#tag1#/` in the constraint. That suits per-user values, and it can be set at user creation time in the same call — see step 5. ### 4. Create the data security policy The policy applies a constraint to an application and report type, comparing a column to the tag value. Build it from [`NewPolicy`](/reference/#new-policy) so its collections are initialised, then save it: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "policy": { "id": null, "Name": "Tenant row-level security", "Description": "Constrains every query to the caller's tenant", "Constraints": [], "Groups": [], "Users": [], "isActive": false }, "isDeepSave": true, "groups": [], "users": [] } ``` In the constraint, compare the tenant column to the tag — `/#tenantid#/` for a data tag, or `/#tag1#/` for a profile tag. **Assign the policy to All Users.** Every account is then constrained, and the tag decides what each one sees. Assigning to individual tenant groups also works, but means remembering to attach each new group. Set `isActive` true once you have verified the constraint. Steps 1 to 4 are per tenant, and only step 3's group entry and step 1 repeat as you add more. ### 5. Create each user One call sets identity, credentials, profile tags and application access: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "withpin": true, "user": { "ID": null, "LoginName": "jsmith", "FirstName": "Jane", "LastName": "Smith", "EmailAddress": "jsmith@tenant-a.example.com", "Company": "Tenant A", "Pin": "GENERATED_PASSWORD", "AuthType": "PIN", "twofa": "none", "Tag1": "TENANT-A", "timezone": -5, "timezonename": "Eastern Standard Time", "SecurityGroups": [], "UserApplications": [ { "ApplicationID": "1001", "ApplicationName": "Sales", "ApplicationRoleID": "6", "ApplicationRoleName": "Agent", "ApplicationRoleType": "0", "applicationUserDataSourceID": "" } ] } } ``` `UserApplications` grants application access, and the role there decides what the user can do with data: | Role | ID | The user can | |---|---|---| | Agent | 6 | View and run content | | Builder | 5 | Build reports and dashboards | | Architect | 7 | Build applications and report types | These roles consume licence seats. ### 6. Add the user to their tenant group ```json { "sessionToken": "YOUR_SESSION_TOKEN", "GroupId": "12", "ContactId": "639234395265102835", "RoleId": "3" } ``` The group role decides what the user may do **with content in the tenant's folder**: `2` View, `3` Modify, `4` Delete. The two roles answer different questions. The application role is what a user can do with data; the group role is what they can do with the tenant's saved content. ### 7. Confirm the result [`GetContactById`](/reference/#get-contact-by-id) returns the user with their groups and application assignments, and [`GetSecurityGroupById`](/reference/#get-security-group-by-id) confirms membership. ## Creating a user for an existing tenant Once a tenant exists, adding a person is two calls: ``` SaveContact -> create the user, set Tag1, assign applications AddUser -> add to the tenant group with a library role ``` ## Sessions and end users Yurbi maintains **one session per user account**. A new login ends that account's previous session, so give every end user their own Yurbi account rather than sharing one, and cache each user's token on your server instead of logging in per page view. See [Authentication & sessions](/authentication/). This is why provisioning a user per end user matters even when your application handles its own authentication: the Yurbi account is what carries the tenant's data constraint and the session behind an embed. ## Offboarding Remove in the reverse order of creation, since deletes take the whole object: ``` GetContactList -> DeleteContact (each user) GetAllLibraryTree -> DelFolder (the tenant folder) GetAllDataTags -> SaveDataTag (drop the tenant's SecurityGroups entry) GetAllSecurityGroups -> DeleteSecurityGroup (the tenant group) ``` Deleting users first releases their licence seats. ## Endpoints used - [`SaveSecurityGroup`](/reference/#save-security-group) · [`DeleteSecurityGroup`](/reference/#delete-security-group) · [`AddUser`](/reference/#add-user) - [`NewLibraryFolder`](/reference/#new-library-folder) · [`SaveLibraryFolder`](/reference/#save-library-folder) · [`DelFolder`](/reference/#del-folder) - [`SaveDataTag`](/reference/#save-data-tag) · [`GetAllDataTags`](/reference/#get-all-data-tags) - [`NewPolicy`](/reference/#new-policy) · [`SaveAppShieldPolicy`](/reference/#save-appshield-policy) - [`NewContact`](/reference/#new-contact) · [`SaveContact`](/reference/#save-contact) · [`DeleteContact`](/reference/#delete-contact) # Run reports from your app Source: https://developers.yurbi.com/guides/running-reports/ Yurbi reports can be run through the API and the results rendered anywhere. This guide covers the full sequence, including prompts, which is where most integrations need the detail. ## The sequence ``` SearchReports find the report ID GetReportMetadataById fetch the report's runtime object ReplacePromptCollection supply values, if the report has prompts GetReportData run it and read Columns + Data ``` The metadata object returned in step two is what step four executes. Pass it through unchanged apart from prompt values. ## 1. Find the report [`SearchReports`](/reference/#search-reports) matches on name and returns items the calling user can see: ```bash curl -X POST "https://your-yurbi-server.com/api/library/SearchReports" \ -H "Content-Type: application/json" \ -d '{ "sessionToken": "YOUR_SESSION_TOKEN", "searchstring": "Revenue" }' ``` Results include dashboards as well as reports. Dashboards have `itemtype` `0` and are not valid report IDs, so filter them out. To browse rather than search, use [`GetAllLibraryTree`](/reference/#get-all-library-tree) followed by [`GetListByFolderID`](/reference/#get-list-by-folder). ## 2. Get the report metadata ```bash curl -X POST "https://your-yurbi-server.com/api/Report/GetReportMetadataById" \ -H "Content-Type: application/json" \ -d '{ "sessionToken": "YOUR_SESSION_TOKEN", "ReportID": "1738259678", "isTarget": false, "PreviousMetadata": null, "Criteria": null }' ``` The response has two parts: `Report`, the definition, and `Prompts`, an array of any values the report asks for at run time. When `Prompts` is empty or null, skip to step four. An unknown ID returns `ErrorCode 586` inside `Report`. ## 3. Supply prompt values Each prompt describes one input. The fields that matter are: | Field | Purpose | |---|---| | `PromptField.DisplayFieldName` | What to label the input in your interface | | `PromptField.Fieldtype` | The value's type — `num`, `cha`, `dat` and so on | | `isBetween` | The prompt takes a range, so set both values | | `isInList` | The value may be a comma-separated list | | `isSkipable` | The prompt may be skipped by setting `isSkipped` | | `LowValue` | **Where you set the value** | | `HighValue` | The upper bound when `isBetween` is true | **Set values on `LowValue` and `HighValue`.** Those are the fields the API reads. To offer a picker rather than a free-text box, call [`GetFieldValues`](/reference/#get-field-values) with the prompt object; it returns the selectable values as `{key, val}` pairs. Apply the values with [`ReplacePromptCollection`](/reference/#replace-prompt-collection), sending the prompts back in the order and length the metadata gave you — values are matched to prompts by position: ```json { "Reportobj": { "...": "the metadata object from step 2" }, "Prompts": [ { "...": "prompt 0", "LowValue": "1115", "HighValue": "" }, { "...": "prompt 1", "LowValue": "2024-01-01", "HighValue": "2026-12-31" } ] } ``` The response is the metadata with those values compiled into the report's criteria. Pass that to step four. Two notes on values: - **Send explicit dates.** For a date prompt, `GetFieldValues` returns relative expressions such as `[Today]` and `[Last Month]` for use in interface pickers. Resolve them to a date before sending. - **Applying one prompt at a time.** [`ReplacePrompt`](/reference/#replace-prompt) applies a single prompt and returns updated metadata. It compiles only the prompt you pass, so call it once per prompt, feeding each response into the next call as `Reportobj`. ## 4. Run the report ```json { "sessionToken": "YOUR_SESSION_TOKEN", "IsDrillDown": false, "DrillDownCriteria": null, "Reportobj": { "...": "metadata, with prompts applied" }, "TargetReportobj": null } ``` **Check `HasError`, not `ErrorCode`.** On this endpoint a failed execution returns `HasError: true` with the reason in `ErrorMessage`, while `ErrorCode` stays `0`. ```javascript const res = await runReport(metadata); if (res.HasError) { throw new Error(res.ErrorMessage); } ``` ## 5. Read the results `Columns` describes the shape and `Data` holds the rows, one object per row keyed by column: ```json { "HasError": false, "Columns": [ { "headerText": "Customer", "key": "Customer_ID", "dataType": "number", "yurbitype": "num", "dataFormatString": null, "columngroup": "" }, { "headerText": "Tickets", "key": "Ticket_ID", "dataType": "number", "yurbitype": "num", "dataFormatString": null, "columngroup": "" } ], "Data": [ { "Customer_ID": 1115, "Ticket_ID": 10 } ], "etime": "79" } ``` Use `headerText` for column labels and `key` to read each row. `yurbitype` tells you how to format the value — see [Field type codes](/conventions/#field-type-codes). `etime` is the execution time in milliseconds. Rendering a table takes only `Columns` and `Data`; the remaining fields are interface bindings used by Yurbi's own components. ```javascript const rows = res.Data.map(row => res.Columns.map(col => row[col.key]) ); ``` ## Practical notes **Results are not paged.** A report returns every row it produces, so a detail report over a large table can return several megabytes. Where you need a summary, run a report built with an aggregate or a `TopN` limit rather than fetching detail rows and reducing them in your own code. **Running without prompts.** Set `supressprompts` true on [`GetReportData`](/reference/#get-report-data) to run a prompted report without supplying values. The result is unfiltered by those prompts, which suits scheduled extracts where the filtering happens downstream. **Reuse metadata across runs.** The metadata object for a given report is stable, so an application that runs the same report with different prompt values can fetch it once and apply values per run. **Row-level security still applies.** Data security policies constrain results by the calling user, so run reports under the end user's own session rather than a shared account if tenants must stay separated. See [Multi-tenant provisioning](/guides/multi-tenant-provisioning/). ## Endpoints used - [`SearchReports`](/reference/#search-reports) · [`GetListByFolderID`](/reference/#get-list-by-folder) - [`GetReportMetadataById`](/reference/#get-report-metadata) - [`GetFieldValues`](/reference/#get-field-values) · [`ReplacePromptCollection`](/reference/#replace-prompt-collection) · [`ReplacePrompt`](/reference/#replace-prompt) - [`GetReportData`](/reference/#get-report-data) # Row-level data security Source: https://developers.yurbi.com/guides/data-security/ Row-level security in Yurbi has two parts. A **data tag** holds a value that varies by group or by user. An **AppShield policy** applies a constraint that compares a column to that value. Together they let a single report serve everyone while returning only the rows each viewer is entitled to. Nothing changes in the report itself. Constraints are applied when the report runs, so they cover the API, the interface, embeds, exports and scheduled delivery alike. ## When to use which | Approach | Value lives on | Good for | |---|---|---| | **Data tag, group-scoped** | A security group | Tenants, regions, departments — anywhere a set of people shares one value | | **Data tag, user-scoped** | A single user | Values that differ per person | | **Profile tag** | `Tag1`–`Tag4` on the user record | Values you already hold in your own system and can set when creating the user | Profile tags are often simplest for a multi-tenant deployment, because the value can be set in the same call that creates the user. ## 1. Create a data tag Start from [`NewDataTag`](/reference/#new-data-tag), then save it with a value for each group: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "datatag": { "ID": "", "Label": "tenantid", "TagGroup": "Tenancy", "DataTypeEnum": 1, "isGroup": true, "isUser": false, "isActive": true, "DefaultValue": "NONE", "Contacts": [], "Index": 0, "SecurityGroups": [ { "LeftID": "", "RightID": "12", "RelationshipType": "tag_grp", "RelationType": "tag_grp", "Option1": "TENANT-A", "PermissionTypeEnum": 0 }, { "LeftID": "", "RightID": "13", "RelationshipType": "tag_grp", "RelationType": "tag_grp", "Option1": "TENANT-B", "PermissionTypeEnum": 0 } ] } } ``` Each `SecurityGroups` entry maps one group to one value: `RightID` is the group ID, `Option1` is the value. Use `Contacts` the same way for per-user values. `DefaultValue` applies to anyone with no assigned value. Set it to something that matches no rows, so a user who has been missed sees nothing rather than everything. `Label` is the name the constraint refers to, written as `/#tenantid#/`. Adding a tenant later means saving the tag again with an extra `SecurityGroups` entry. Read the current tag with [`GetAllDataTags`](/reference/#get-all-data-tags) first so you send back the entries that already exist. ## 2. Create the policy Build it from [`NewPolicy`](/reference/#new-policy) so its collections are initialised, then save: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "policy": { "id": null, "Name": "Tenant row-level security", "Description": "Every query is constrained to the caller's tenant", "Constraints": [], "Groups": [], "Users": [], "isActive": false }, "isDeepSave": true, "groups": [], "users": [] } ``` A constraint targets one application and report type, and compares a column to the tag: ``` customer_id = /#tenantid#/ ``` Use `/#tag1#/` instead when the value is a profile tag on the user record. ## 3. Assign and activate Assign the policy to **All Users** so every account is constrained and the tag decides what each one sees. Assigning to individual tenant groups also works, but means attaching each new group as you create it. [`AddGroup`](/reference/#appshield-add-group) and [`RemoveGroup`](/reference/#appshield-remove-group) adjust assignments on an existing policy without rewriting it. Set `isActive` true when you are ready to enforce the policy. Leaving it false while you verify the constraint lets you save and review it first. ## Verifying a policy The most direct check is to run a report as a user in the constrained group and inspect the SQL: 1. Sign in as that user with [`DoLogin`](/reference/#do-login). 2. Fetch the report with [`GetReportMetadataById`](/reference/#get-report-metadata). 3. Call [`GetSQL`](/reference/#get-sql) and confirm the WHERE clause contains the tenant's value. 4. Run the report with [`GetReportData`](/reference/#get-report-data) and confirm the rows. Test with two tenants and a user in neither. The third case is the one that catches a `DefaultValue` set too permissively. ## Notes **Policies apply everywhere.** A constrained report returns the same restricted rows through the API, the interface, an embed and a scheduled email. There is no separate configuration per channel. **Keep tenants in separate groups.** A user in two tenant groups may match more than one tag value. One tenant group per user keeps the constraint unambiguous — see [Multi-tenant provisioning](/guides/multi-tenant-provisioning/). **The super-admin account is not constrained.** The built-in `admin` bypasses these checks, so verify policies with an ordinary user account. ## Endpoints used - [`NewDataTag`](/reference/#new-data-tag) · [`SaveDataTag`](/reference/#save-data-tag) · [`GetAllDataTags`](/reference/#get-all-data-tags) · [`DeleteDataTag`](/reference/#delete-data-tag) - [`NewPolicy`](/reference/#new-policy) · [`SaveAppShieldPolicy`](/reference/#save-appshield-policy) · [`GetAllAppshieldPolicies`](/reference/#get-all-appshield-policies) · [`DeletePolicy`](/reference/#delete-policy) - [`AddGroup`](/reference/#appshield-add-group) · [`RemoveGroup`](/reference/#appshield-remove-group) # Building apps & reports Source: https://developers.yurbi.com/guides/building-apps-and-reports/ ## What this is for Most integrations only *read* from Yurbi. This guide covers writing: creating the semantic layer and the reports on top of it, entirely through the API. Two situations need it: - **Dynamic data sources.** A tenant's schema isn't known ahead of time, so the report type has to be built at provisioning time rather than by hand in App Builder. - **Migration.** Bringing reports in from another BI tool. Those tools usually store joins *per report*; Yurbi stores them in the **report type**, so the report type has to exist before the report can be created. ## The two layers | Layer | Holds | Written with | |---|---|---| | **Report type** | Tables, joins, the field tree | [`SaveAnyDbModule`](/reference/#save-anydb-module) | | **Report** | Selected fields, filters, formulas, sort | [`SaveReport`](/reference/#save-report) | A report names its report type **by name**, not by ID. Two report types sharing a name inside one app makes every report on that name ambiguous, so keep names unique. ## 1. Find the app [`GetAnyDbModulesList`](/reference/#get-anydb-modules-list) returns every AnyDB app with the two identifiers everything else needs: ```json { "ID": "17779219821", "ReportModule": { "ID": "1005", "Name": "AssetWorks Source ORACLE" } } ``` `ID` is the **RegServerID**, `ReportModule.ID` is the **ModuleID**. ## 2. Read before you write [`GetAnyDbModule`](/reference/#get-anydb-module) returns the app's report types. Read it first, always — for two reasons: - to compute the next free `RepTypeID` (`max + 1`) - to snapshot the current state, because the write is destructive Look at `ReportTypes[].SQLTables` to see what tables an app already has. `DBSQLTableList.AllDbtables` is live introspection of the database server and comes back empty when the app has no live connection. > These responses get large. An app with a couple of hundred tables and their > columns runs to tens of megabytes. ## 3. Build the report type A report type is `SQLTables` plus `FieldTree`. ### Tables and joins Each table carries a single `join` describing how it attaches to the model: ```json { "tablename": "UNIT_MAIN", "tableowner": "", "tablealias": "UNIT_MAIN", "join": { "table1": "VIEW_ALL_WORK_ORDERS", "field1": "UnitNo", "table2": "UNIT_MAIN", "field2": "UNIT_NO", "jointype": "Inner Join", "joinop": "=", "filter": "", "index": 1 } } ``` `table1` is the **parent** — the table already in the model. `table2` is the one being attached. One table (the root) has an empty join. Because each table has exactly one join, **the join model is a tree, not a graph**. Every table has one parent. That rules out: - the same pair of tables joined on two column pairs (composite keys) - a table reachable from two different parents - cycles `jointype` is `"Inner Join"`, `"Left Join"` and so on — mixed case, no `OUTER`. `joinop` is a bare `"="` with no padding. `filter` is appended to the join clause verbatim if set. `tableowner` should match whatever the app already uses. Many AnyDB apps register tables with an empty owner even when the underlying database has a schema — check `SQLTables` on an existing report type rather than assuming. ### The field tree `FieldTree` is the field picker: folder nodes (`nodetype: "G"`) with field nodes (`nodetype: "F"`) beneath them. `flevel` is a colon-delimited materialised path made of **the parent's path plus the node's own id**: ``` id 0 flevel "0" G VIEW_ALL_WORK_ORDERS (root folder) id 1 flevel "0:1" F WorkOrderNo id 2 flevel "2" G UNIT_MAIN id 3 flevel "2:3" F Make ``` Two things that are easy to get wrong: - `tablealias` on a field node is **its own** table's alias. - `parenttablealias` is the **root table of the whole report type**, the same value on every field node — not the field's immediate join parent. `idx_order` starts at 1. Common `datatype` codes: `cha` text, `num` numeric, `dat` timestamp, `doz` date-only. The date codes are not interchangeable — see [Dates](#dates-pick-the-right-code) below. ### Writing it [`SaveAnyDbModule`](/reference/#save-anydb-module) **deletes and re-inserts every report type in the payload**. Report types you leave out are untouched, so send only the ones you are creating: ```json { "sessionToken": "…", "anydbmodule": { "ReportTypes": [ { /* just the new one */ } ], "DBSQLTableList": { "AllDbtables": [] }, "isExcelCSV": false, "ApiEndpointList": null } } ``` Posting a whole 16 MB module back means deleting and re-inserting thousands of rows that were fine. It returns `1` on success. Errors are swallowed and returned as `0`, so **verify by reading the module back** rather than trusting the return value. ## 4. Build the report Start from [`NewReport`](/reference/#new-report) so you inherit the current defaults, then add fields. The reliable way to add a field is to read the report type's tree with [`GetReportTree`](/reference/#get-report-tree) and pass nodes to [`NewField`](/reference/#new-field), which fills in derived values like `RenamedField` (the SELECT alias) rather than making you reproduce the rules. ### Filters Put structured criteria on the field and leave the compiled strings empty — `SaveReport` compiles them: ```json { "DisplayFieldName": "Status", "Criteria": [ { "Index": 0, "Field": "Status", "Op": "inlist", "Value1": "D,O", "Value2": "", "Logical": "And", "cond": "is" } ], "SearchCriteria": "" } ``` `Criteria.Field` must be the field's **display name**. It is the key binding a criteria back to its field on load; if it doesn't match, the criteria is orphaned and rebuilt from a compiled string, which changes the operator's casing and breaks the criteria editor. Operators are lowercase: `=`, `<`, `>`, `<>`, `between`, `inlist`, `like`, `not like`, `null`, `empty`. `cond` is `is` or `isnot`. Multi-value lists are comma-separated in `Value1` — values containing a comma will be split. ### Formulas `Formula` holds raw SQL in the target dialect. `?` is replaced with the field's own column, alias-qualified: ``` Formula: "ROUND((SYSDATE - ?), 0)" becomes: ROUND((SYSDATE - "VIEW_ALL_WORK_ORDERS"."OpenDate"), 0) ``` Reference a *different* column by qualifying it explicitly with its table alias — `"UNIT_MAIN"."MAKE"`. Quoting follows the platform (`"x"` on Oracle and PostgreSQL, `[x]` on SQL Server). Set `Fieldtype` to what the formula **returns**, not what it reads. `ROUND(SYSDATE - "OpenDate", 0)` reads a date and returns a number, so it is `num`. ### Aggregates There is no aggregate flag. Put an aggregate function in `Formula` and the engine detects it and groups every non-aggregated column automatically: ```json { "DisplayFieldName": "Ticket Count", "Formula": "count(?)", "Fieldtype": "num" } ``` Recognised: `sum(`, `avg(`, `min(`, `max(`, `count(`, `stddev(`. A formula that is a subquery will not be treated as an aggregate. ### Saving Build the object you save from [`NewReport`](/reference/#new-report) rather than assembling it from scratch. The template initialises collections such as `linkreports` that the save expects to be present; a hand-built object that omits them returns `ErrorCode 9000`. [`SaveReport`](/reference/#save-report) branches on `ReportID`: - **empty string** → create; the server mints an ID and returns it - **existing ID** → update Sending an ID that doesn't exist fails with `9001 Permission Denied` — the permission check runs against a report that isn't there. Never invent an ID. `folderid` must be a library folder the user can modify, or the save fails with `Folder Permission Denied`. Get candidates from [`GetAllLibraryTree`](/reference/#get-all-library-tree); its real tree is nested under a `rootnode` key on each entry, and `isUserAdmin`/`isUserModify` tell you what's writable. ## 5. Validate before you commit Two endpoints run the pipeline without saving anything: - [`GetSQL`](/reference/#get-sql) takes a whole report object and returns the SQL it would generate. - [`ReportProcUI`](/reference/#report-proc-ui) compiles criteria and totals and hands the object back. `GetSQL` does **not** compile criteria, so a freshly built object produces SQL with no `WHERE` clause. Chain them — `ReportProcUI` first, then `GetSQL` — to preview the whole statement. This is the cheapest possible feedback loop: build the object, look at the SQL, fix it, and only then write. ## Dates: pick the right code `dat` and `doz` are both dates, and they behave differently: | Code | Renders as | Note | |---|---|---| | `dat`, `dtz`, `tsp` | `'2024-12-01 00:00:00'` | timestamp; the client applies a browser timezone offset | | `doz`, `idt`, `dpo` | `'2024-12-01'` | date only, no offset | For values that are literal dates with no timezone, `doz` reproduces them exactly. `dat` is right when time of day genuinely matters. Either way, check period boundaries: with `doz`, `Between '2024-12-01' and '2024-12-31'` excludes times later on the 31st. ## Putting it together ``` GetAnyDbModulesList find the app GetAnyDbModule read current state, snapshot, next RepTypeID ↓ SaveAnyDbModule create the report type (send only the new one) GetAnyDbModule verify it was written ↓ GetReportTree read the new field tree NewReport + NewField assemble the report ReportProcUI → GetSQL preview the SQL, no writes ↓ GetAllLibraryTree pick a writable folder SaveReport ReportID: "" → returns the new ID ``` ## Things worth knowing - **Report types are referenced by name.** Re-creating one with the same name but a different join graph breaks existing reports on it. Check for an existing match before creating. - **`SaveAnyDbModule` returns `0` on error**, with no message. Verify by reading back. - **Only the tables a report uses are joined.** Selecting fields from two tables of a ten-table report type generates a two-table query, and intermediate tables needed to connect them are pulled in automatically. A broad report type therefore costs a narrow report nothing — one report type can serve many reports. - **Snapshot before writing.** `GetAnyDbModule` output is your rollback. - **Reports can be removed.** [`DelReport`](/reference/#del-report) deletes a report by ID and returns `0` on success, which makes it straightforward to roll back an automated build that produced the wrong result. - **Grant your integration user access to the app.** Only the built-in `admin` account bypasses application permissions. Any other account needs an Architect role on the application before these calls will see it. # Embed dashboards & reports Source: https://developers.yurbi.com/guides/embedding/ Yurbi embeds through the same session-token system as the rest of the API. The flow: get a token, build an embed URL with it, drop that URL in an iframe. Optionally log users straight into the full Yurbi interface. ## 1. Get a session token Call [`DoLogin`](/reference/#do-login) to get a token (see [Authentication & sessions](/authentication/)): ```bash curl -X POST "https://your-yurbi-server.com/api/login/DoLogin" \ -H "Content-Type: application/json" \ -d '{ "bolForceLogin": true, "isGuest": false, "UserId": "user", "UserPassword": "password" }' ``` The token comes back in `LoginSession.SessionToken`. > **One Yurbi user per end user.** Yurbi maintains a single session per account, so > a new login ends that account's previous session. Embedding for several people > through one shared account means each page load signs the previous viewer out. > Provision a user per end user, and cache each user's token on your server rather > than logging in on every page view. ## 2. Build the embed URL Append the token to an embed URL. Use `t=d` for a dashboard, `t=r` for a report, and `i=` for the item's ID: ``` Dashboard: https://your-yurbi-server.com/embed.html?t=d&i={dashboardId}&s={sessionToken} Report: https://your-yurbi-server.com/embed.html?t=r&i={reportId}&s={sessionToken} ``` Place either URL in an ` ``` > **Path note.** `/embed.html` is the Linux/Docker (and Windows root-web) path. On a > default Windows install it's `/yurbi/embed.html`. The API base is separate — see > [Platform paths](/conventions/#platform-where-yurbi-is-served). ## 3. Find dashboard & report IDs Edit the dashboard or report in Yurbi; the ID appears at the top-right of the edit sidebar. You can also resolve IDs programmatically with the [Library](/reference/#get-all-library-tree) calls. > **All you need to embed is the item's ID and a valid session token.** The > "Allow embed" checkbox in the library is cosmetic — it only adds a Share action to > the library menu; it is *not* required for an embed to work. If you want a view with > **no login at all**, enable **Anonymous / Public view** when saving the item. ## 4. Pass report prompts (optional) If a report has prompts, you can pre-fill them in the URL with `isprompt=true` and indexed `prmpt*` parameters — the Embed Library in Yurbi builds these for you: ``` https://your-yurbi-server.com/embed.html?t=r&i=1739550061&isprompt=true&prmpt0low=11000&prmpt0skipped=false&s={sessionToken} ``` ## 5. Keep the session alive A token expires at its `SessionExpir` time, 20 minutes after the last call by default. The window rolls forward on every authenticated request, so an embed someone is interacting with keeps itself alive. For an embed that may sit untouched, call [`RefreshSession`](/reference/#refresh-session) before the expiry and [`CheckSession`](/reference/#check-session) to test validity. > **The token is visible in the embed URL.** It appears in the iframe `src`, and so > in browser history and any referrer headers. Use a per-user token, keep the > session timeout short, and prefer anonymous view for content that needs no user > identity at all. ## 6. Seamless login to the full app Beyond single items, you can drop a user directly into the Yurbi interface with a valid token via `sso.html` — see [Single Sign-On](/guides/single-sign-on/) for the full walkthrough: ``` Dashboard: https://your-yurbi-server.com/sso.html?s={sessionToken} Library: https://your-yurbi-server.com/sso.html?s={sessionToken}&h=1 Builder: https://your-yurbi-server.com/sso.html?s={sessionToken}&h=2 ``` For provider-driven login (where your identity provider authenticates the user and Yurbi logs them in automatically, no `DoLogin` call), see [Header-based SSO (advanced)](/guides/sso-header/). ## Endpoints used - [`DoLogin`](/reference/#do-login) — get the token - [`CheckSession`](/reference/#check-session) — validate it - [`RefreshSession`](/reference/#refresh-session) — extend it # Branding & white-labeling Source: https://developers.yurbi.com/guides/branding/ For an embedding vendor, branding is half the integration: it's how Yurbi stops looking like Yurbi and starts looking like *your* product. Most of it is configured in the **Branding** area of the Yurbi admin, and it can also be automated through the API when you provision tenants at scale. It's extensive — logos, colors, fonts, which features are visible, the login page, public views, and the embedded experience. Branding profiles can apply to **all users, a specific group, or a specific user**, which ties directly into how you [provision groups](/reference/#get-all-security-groups) for multi-tenant setups. This page is a map; each link goes to the full guide in the Yurbi knowledge base. ## Where to start - **[Branding Guide Overview](https://help.yurbi.com/admin-guides/branding-guide-overview)** — the white-labeling capabilities at a glance, and how branding profiles work. - **[Branding Best Practices & Common Scenarios](https://help.yurbi.com/admin-guides/branding-best-practices-and-common-scenarios)** — practical patterns for multi-tenant environments and tiered (per-plan) feature sets. ## The four surfaces you can brand - **[Application Branding (logged-in users)](https://help.yurbi.com/admin-guides/application-branding-logged-in-users)** — the full experience for users who log into Yurbi (Dashboard, Library, Builder): appearance plus which features each audience can see. - **[Embedded Report & Dashboard Branding](https://help.yurbi.com/admin-guides/embedded-report-and-dashboard-branding)** — the most relevant for embedding: fine-tune exactly which features appear inside an embed, so you can ship a clean, simplified view in your app. Pair this with the [Embedding guide](/guides/embedding/). - **[Login Page Branding](https://help.yurbi.com/admin-guides/login-page-branding)** — a branded (optionally per-tenant) login experience, when users hit Yurbi directly rather than via [single sign-on](/guides/single-sign-on/). - **[Guest / Anonymous / Public View Branding](https://help.yurbi.com/admin-guides/guest-anonymous-public-view-report-branding)** — control appearance and available features for public, no-login content. ## Automating branding Branding profiles can be created and assigned through the API, which is how a multi-tenant deployment gives each customer their own look without an administrator configuring it by hand. The Branding endpoints cover creating a profile, assigning it to groups and users, activating it, and uploading logo and background images. A typical tenant onboarding creates the branding profile alongside the tenant's security group, then assigns the profile to that group so every member inherits it. See [Multi-tenant provisioning](/guides/multi-tenant-provisioning/) for where this fits in the wider sequence. ## Going beyond the settings When the built-in options don't reach a specific element, Branding profiles include a **Custom CSS** area. That's how you match fonts, spacing, and component styling exactly to your app — see the [Custom CSS guide](/guides/custom-css/). > Tiered products: because a branding profile can be scoped to a group, you can map > profiles to your own plan tiers — e.g. "Basic" sees an embedded dashboard only, > "Premium" gets the builder and scheduler — all without code. # Custom CSS Source: https://developers.yurbi.com/guides/custom-css/ Every [Branding profile](/guides/branding/) has a **Custom CSS** area under **Advanced Customizations**. Anything you put there is injected into the Yurbi interface for whichever audience the profile is assigned to — so you can match fonts, colors, spacing, and component styling exactly to your application. ## The workflow 1. **Inspect the element.** In Yurbi, right-click the thing you want to restyle and choose **Inspect**. Find its class name in the DevTools elements panel. 2. **Write a rule with `!important`.** Yurbi's built-in stylesheets use specific selectors, so your rule needs `!important` to win: ```css .some-yurbi-class { color: #ffffff !important; } ``` 3. **Paste it into Branding.** Admin → **Branding** → edit/create a profile → **Advanced Customizations** → **Custom CSS**. 4. **Assign the audience.** All Users, or a specific Group or User. 5. **Save & Apply.** It takes effect the next time that user logs in and views the affected screen. ## Worked example: grid column headers Grid headers are a common request. Yurbi uses two different grid components, so the selector depends on which one you're styling: - **Default Data Grid** → `.jqx-grid-column-header` - **Aggregate Grid visualization** → `.dx-datagrid-headers` (plus the inner `.dx-header-row > td` for text color/size/weight) ```css /* Default Data Grid headers */ .jqx-grid-column-header { background-color: #48cae4 !important; color: #ffffff !important; font-weight: bold !important; } ``` The full snippet for both grid types is in the knowledge base: [Customize Grid Column Header Styling via Custom CSS](https://help.yurbi.com/admin-guides/how-to-customize-grid-column-header-styling-background-font-weight-via-custom-css). ## Tips - **Always add `!important`** — without it, Yurbi's default styles override yours. - **Use valid 6-digit hex** (`#ffffff`, not `#fffff`) — a bad value is silently ignored. - **Test on yourself first** — assign the profile to your own user before rolling it out to a group or everyone. - **Class names can shift between versions.** Re-inspect after an upgrade if something stops applying. If you're hunting for the right selector, send us the element and we'll help. # Header-based SSO (advanced) Source: https://developers.yurbi.com/guides/sso-header/ > **Most integrations don't need this.** If your application can call `DoLogin`, > use [Single Sign-On](/guides/single-sign-on/) — that's the standard answer, and > it's simpler. Header-based SSO is for the specific case where you want your > **identity provider** (e.g. Microsoft Entra ID) to authenticate the user and > have Yurbi log them in automatically from a trusted header, with **no `DoLogin` > call from your side**. With header-based SSO, your identity provider authenticates the user, passes their Yurbi **login ID** to Yurbi in a trusted HTTP header, and Yurbi signs them in. Before you start: - **Existing users only.** SSO signs in users who already exist in Yurbi; it does not create accounts. The header value must match an existing user's login ID. - **Any auth type.** The user can be a standard password user. - **The endpoint must be protected.** Because Yurbi trusts the header, the SSO endpoint must be reachable only through your trusted proxy (see Securing the endpoint). ## 1. Enable SSO in Yurbi 1. Go to **Settings → Server Settings → Security Settings**. 2. Under **SSO Settings**, turn on **Enable SSO**. 3. In **SSO Header**, enter the header name your proxy will send (choose a non-obvious value, e.g. `ssoheadertoken`). 4. Save. The header *name* identifies which header carries the identity; the header *value* is the user's login ID. So your proxy sends, for an existing user `jsmith`: ``` ssoheadertoken: jsmith ``` Leave **Enable IIS Passthrough** off for header-based SSO. You can confirm the saved configuration from the API: [`GetAppSettings`](/reference/#get-app-settings) returns `SSOEnabled`, `SSOHeader` and `IIS_PASSTHROUGH_ENABLED`, which is a quick way to verify a deployment without opening the admin interface. ## 2. The SSO endpoint Once enabled, your proxy sends an authenticated request to Yurbi's SSO endpoint with the identity header attached. The path differs by platform: ``` Linux: https://your-yurbi-server.com/sso Windows: https://your-yurbi-server.com/yurbi/sso ``` (On a Windows install with the [IIS root web configured](/conventions/#platform-where-yurbi-is-served), the SSO endpoint is reachable at `/sso` even though the API stays at `/yurbi/api`.) By default the user lands on the Dashboard. Add `h` to choose a starting view: ``` Dashboard (default): /sso Library: /sso?h=1 Builder: /sso?h=2 ``` (On Windows use `/yurbi/sso` in place of `/sso`.) ## 3. Securing the endpoint (required) Because the endpoint trusts the login ID in the header, it must only be reachable by your trusted proxy — never directly from the internet. Choose one: - **Shared secret (recommended).** Your proxy attaches an extra secret header with a long random value; the proxy in front of Yurbi rejects any request without it. - **IP allowlist.** Accept SSO requests only from your identity proxy's IP. - **Mutual TLS (mTLS).** Your proxy presents a client certificate Yurbi's front-end verifies. Strongest, most setup. Always serve the endpoint over **HTTPS**, and bind the Yurbi app so it can't be reached except through your proxy. ### NGINX (Linux) — shared-secret example ```nginx location = /sso { if ($http_x_sso_secret != "REPLACE_WITH_LONG_RANDOM_SECRET") { return 403; } proxy_pass http://127.0.0.1:5000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } ``` ### IIS (Windows) Use a request-filtering / URL Rewrite rule on `/yurbi/sso` to require the secret header, or **IP Address and Domain Restrictions** scoped to that path, or client-certificate negotiation for mTLS. ## 4. Supported identity providers Header-based SSO is vendor-neutral — any system that can authenticate a user and forward their login ID in a header works. Common choices: - **Microsoft Entra application proxy** (most common) — supports header-based SSO natively; map a user attribute to your SSO Header name. - **Identity-aware proxies** — oauth2-proxy, Authelia, Authentik, or forward-auth in NGINX / Traefik / Envoy. - **Enterprise access managers** — SiteMinder, Oracle Access Manager, IBM Security Verify Access, F5 BIG-IP APM, PingAccess. > Need help mapping your specific provider? Reach out to the Yurbi team. =============================================================== API REFERENCE =============================================================== Base: /api · Format: JSON · Method: POST · Auth: session token Full interactive reference: https://developers.yurbi.com/reference/ --------------------------------------------------------------- ## Authentication --------------------------------------------------------------- ### Log in POST /api/login/DoLogin Auth: none (this call issues the token) Reference: https://developers.yurbi.com/reference/#do-login Authenticate a user and receive a session token. On success the token is in LoginSession.SessionToken and ErrorCode is 0. Invalid credentials return ErrorCode 101 with "Login Failed - Username or Password is invalid." and a null session. Yurbi maintains one session per user: each successful login issues a new token and ends that user's previous session. The full response is around 200 KB, because LoginUser.Language.phraselist carries the interface phrase table. The sample below shortens that list. Common use: Start here. Run this once, copy the returned token into the Session token field at the top of the page, and every other sample is ready to send. Because a new login ends the previous session, cache the token on your server and reuse it across requests rather than logging in per call, and give each integration its own Yurbi user. The accounts scheduler and yurbi are reserved for internal services and cannot sign in. Body parameters: - UserId (string, required): The user's login name. - UserPassword (string, required): The user's PIN or password. - isGuest (boolean, required): Set true only for a guest login; otherwise false. - bolForceLogin (boolean, required): Send true. The field is required; omitting it returns ErrorCode 9000. Example request body: ```json { "bolForceLogin": true, "UserId": "admin", "UserPassword": "YOUR_PASSWORD", "isGuest": false } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": "", "LoginSession": { "ErrorCode": 0, "ErrorMessage": "", "SessionToken": "QK[OFHLQSDQROJQULKPJQPGXG", "SessionFlag": 0, "isGuestSession": false, "SessionTimeLeft": 0, "SessionExpir": "2026-08-27T14:33:48.4458383+00:00", "Duo2FA_State": "", "Duo2FA_AuthURI": null, "Duo2FA_AuthStatus": null }, "LoginUser": { "ErrorCode": 0, "ErrorMessage": "", "ID": "639234363032231617", "LoginName": "apitest", "FirstName": "API", "LastName": "Test", "EmailAddress": "", "Company": "", "twofa": "none", "CreateDate": "2026-08-27T14:05:03", "ModifyDate": "2026-08-27T14:05:03", "LoginDate": "2026-08-27T14:05:03", "Pin": null, "AuthType": "PIN", "isAdmin": true, "isSuperAdmin": false, "isBuilder": false, "isAgent": false, "isArchitect": true, "SecurityGroups": [ { "GroupId": "1", "GroupName": "Administrators", "GroupDescription": "Yurbi Admins", "GroupRoles": [ { "RoleId": "1", "RoleName": "Admin" } ], "GroupStatus": 0 } ], "ComboName": "Test, API", "FullName": "API Test", "UserApplications": [ { "ApplicationID": "1001", "ApplicationName": "Sample Data", "ApplicationRoleID": "7", "ApplicationRoleName": "Architect", "ApplicationRoleType": "0", "applicationUserDataSourceID": "" } ], "Language": { "id": 1, "nativename": "English", "englishname": "English", "iso_name": "EN", "phraselist": [ { "internalname": "Login", "text": "Log In", "dialog": "Main" } ] }, "timezone": -6, "timezonename": "America/Bahia_Banderas", "isFastCache": 0, "FastCacheLimit": 30, "bforcepasschange": false }, "Tenant_Mode": false, "ProductName": "Yurbi", "ProductType": 2, "ProductVersion": "12.26.08.24", "LicensedFeatures": [ { "Feature": "monthly active users", "count": "100", "id": "86" } ], "maustate": "Normal", "maxrecords": "500000" } ``` ### Check session POST /api/Session/CheckSession Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#check-session Confirm a session token is still valid. A valid token returns ErrorCode 0 with the session's current SessionExpir. An expired or unknown token returns ErrorCode 101 with "Session Expired" and a SessionExpir of 0001-01-01T00:00:00. Common use: Cheap to call before a long-running job. Like any authenticated request, it also extends the session, resetting the expiry to the current time plus the server's session timeout. Body parameters: - sessionToken (string, required): The session token to validate. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": "", "SessionToken": "QK[OFHLQSDQROJQULKPJQPGXG", "SessionFlag": 0, "isGuestSession": false, "SessionExpir": "2026-08-27T14:41:05.1956089+00:00" } ``` ### Refresh session POST /api/Session/RefreshSession Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#refresh-session Extend a session token's lifetime without a full re-login, resetting SessionExpir to the current time plus the server's session timeout. That timeout is SESSION_TIMEOUT in app settings and defaults to 20 minutes. Common use: Use this to keep a session alive across a long idle period, such as an embedded dashboard left open on a wall display. Integrations that make requests regularly do not need it: every authenticated call already moves the expiry forward. Body parameters: - sessionToken (string, required): The session token to extend. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": "", "SessionToken": "JDEJGZRMSTXHYJJTOEHMSNYMN", "SessionFlag": 0, "isGuestSession": false, "SessionExpir": "2026-08-27T14:41:01.738885" } ``` ### Reset session passport POST /api/Session/ResetPassport Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#reset-passport Rebuild the session's passport — its cached licence and permission state — and return it. The response describes licensed modules, registered servers and SMTP configuration for the instance. Common use: Use it after changing a user's group membership or roles so the change applies to their current session instead of waiting for their next login. Yurbi also refreshes the passport internally after a report is saved, to recalculate embedded and anonymous licence consumption. Body parameters: - sessionToken (string, required): The session token whose passport should be rebuilt. - withReturn (boolean, optional): Reserved. Send false. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "withReturn": false } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": "", "isFirstRun": true, "isExpiredBase": false, "isValidBase": false, "isValidTrial": false, "Version": 0, "ProdType": 0, "TotalReportCount": 0, "TotalUserCount": 0, "YurbiModuleProfiles": [], "isSchedulerLicensed": false, "isConnectLicensed": false, "isRolesLicensed": false, "isLDAPLicensed": false, "isAppShieldLicensed": false, "RegisteredServerList": [], "YurbiLicenses": [], "TrialLicenses": [], "TeamLicenses": [], "EnterpriseLicenses": [], "SMTPServerList": [] } ``` ### Log out POST /api/login/DoLogout Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#do-logout End a session and release its token. Returns a bare 0 rather than a JSON object. Afterwards the token returns ErrorCode 101 from Check session. Common use: Call this when a script finishes so you don't leave sessions open on the server. Body parameters: - sessionToken (string, required): The session token to end. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json 0 ``` --------------------------------------------------------------- ## Users --------------------------------------------------------------- ### New user template POST /api/Contact/NewContact Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#new-contact Return an empty user object with every collection initialised. Fill it in and pass it to Save user. Common use: Start every user creation here rather than hand-building the object, so new fields added in later Yurbi releases are present with sensible defaults. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": null, "ID": null, "LoginName": null, "FirstName": null, "LastName": null, "EmailAddress": null, "Company": null, "Tag1": null, "twofa": null, "Pin": null, "AuthType": null, "isAdmin": false, "isSuperAdmin": false, "isBuilder": false, "isAgent": false, "isArchitect": false, "SecurityGroups": [], "UserApplications": [], "Preferences": [], "timezone": 0, "timezonename": null, "isFastCache": 0 } ``` ### Create or update a user POST /api/Contact/SaveContact Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#save-contact Create a user or update an existing one. user.ID decides which: send null to create, or an existing ID to update. Set withpin to true when the payload carries a Pin to apply. App access is assigned in the same call through user.UserApplications, and Profile Tags through Tag1–Tag4. Common use: The core of user provisioning. A complete provision is this call followed by Add user to group: this sets identity, credentials, Profile Tags and app roles; that sets the library role inside the tenant's group. Body parameters: - sessionToken (string, required): A valid session token. - withpin (boolean, required): True when user.Pin should be applied. - user (object, required): The user object. Start from New user template. ID null creates; an existing ID updates. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "withpin": true, "user": { "ID": null, "LoginName": "jsmith", "FirstName": "Jane", "LastName": "Smith", "EmailAddress": "jsmith@example.com", "Company": "Acme", "Pin": "1234", "AuthType": "PIN", "twofa": "none", "Tag1": "TENANT-A", "timezone": -5, "timezonename": "Eastern Standard Time", "SecurityGroups": [], "UserApplications": [ { "ApplicationID": "1001", "ApplicationName": "Sample Data", "ApplicationRoleID": "7", "ApplicationRoleName": "Architect", "ApplicationRoleType": "0", "applicationUserDataSourceID": "" } ] } } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": "", "ID": "639234395265102835", "LoginName": "jsmith", "FirstName": "Jane", "LastName": "Smith", "EmailAddress": "jsmith@example.com", "Company": "Acme", "Tag1": "TENANT-A", "Tag2": "", "Tag3": "", "Tag4": "", "twofa": "none", "CreateDate": "2026-08-27T14:58:46", "ModifyDate": "2026-08-27T14:58:47", "LoginDate": "2026-08-27T14:58:46", "Pin": null, "AuthType": "PIN", "Description": "", "isAdmin": false, "isSuperAdmin": false, "isBuilder": false, "isAgent": false, "isArchitect": true, "SecurityGroups": [ { "GroupId": "12", "GroupName": "Tenant A", "GroupRoles": [ { "RoleId": "3", "RoleName": "Modify" } ], "GroupStatus": 0 } ], "ComboName": "Smith, Jane", "FullName": "Jane Smith", "UserApplications": [ { "ApplicationID": "1001", "ApplicationName": "Sample Data", "ApplicationRoleID": "7", "ApplicationRoleName": "Architect", "ApplicationRoleType": "0", "applicationUserDataSourceID": "" } ], "Preferences": [], "UserState": 0, "Language": { "id": 1, "nativename": "English", "englishname": "English", "iso_name": "EN", "phraselist": null }, "timezone": -5, "timezonename": "America/New_York", "isFastCache": 0, "FastCacheLimit": 0, "lockdate": "0001-01-01T00:00:00", "bforcepasschange": false } ``` ### Update my profile POST /api/Contact/SaveMYContact Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#save-my-contact Update the profile of the user who owns the session. Same payload shape as Save user, scoped to the caller. Common use: Use this for a self-service profile screen in your own application, so users can change their name or email without an administrator. Body parameters: - sessionToken (string, required): A valid session token. - withpin (boolean, required): True when a new Pin is being set. - user (object, required): The signed-in user's object with the fields to change. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "withpin": false, "user": { "ID": "639234395265102835", "FirstName": "Jane", "LastName": "Smith", "EmailAddress": "jane@example.com", "Description": "" } } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": "", "ID": "639234395265102835", "LoginName": "jsmith", "FirstName": "Jane", "LastName": "Smith", "EmailAddress": "jsmith@example.com", "Company": "Acme", "Tag1": "TENANT-A", "Tag2": "", "Tag3": "", "Tag4": "", "twofa": "none", "CreateDate": "2026-08-27T14:58:46", "ModifyDate": "2026-08-27T14:58:47", "LoginDate": "2026-08-27T14:58:46", "Pin": null, "AuthType": "PIN", "Description": "", "isAdmin": false, "isSuperAdmin": false, "isBuilder": false, "isAgent": false, "isArchitect": true, "SecurityGroups": [ { "GroupId": "12", "GroupName": "Tenant A", "GroupRoles": [ { "RoleId": "3", "RoleName": "Modify" } ], "GroupStatus": 0 } ], "ComboName": "Smith, Jane", "FullName": "Jane Smith", "UserApplications": [ { "ApplicationID": "1001", "ApplicationName": "Sample Data", "ApplicationRoleID": "7", "ApplicationRoleName": "Architect", "ApplicationRoleType": "0", "applicationUserDataSourceID": "" } ], "Preferences": [], "UserState": 0, "Language": { "id": 1, "nativename": "English", "englishname": "English", "iso_name": "EN", "phraselist": [] }, "timezone": -5, "timezonename": "America/New_York", "isFastCache": 0, "FastCacheLimit": 0, "lockdate": "0001-01-01T00:00:00", "bforcepasschange": false } ``` ### List users POST /api/Contact/GetContactList Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-contact-list Return every user on the instance as an array. Each entry carries its own ErrorCode; there is no wrapper object. Common use: Use it to resolve a login name to an ID, to audit tenant membership, or to fetch the full object a delete requires. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json [ { "ErrorCode": 0, "ErrorMessage": "", "ID": "639234395265102835", "LoginName": "jsmith", "FirstName": "Jane", "LastName": "Smith", "EmailAddress": "jsmith@example.com", "Company": "Acme", "Tag1": "TENANT-A", "Tag2": "", "Tag3": "", "Tag4": "", "twofa": "none", "CreateDate": "2026-08-27T14:58:46", "ModifyDate": "2026-08-27T14:58:47", "LoginDate": "2026-08-27T14:58:46", "Pin": null, "AuthType": "PIN", "Description": "", "isAdmin": false, "isSuperAdmin": false, "isBuilder": false, "isAgent": false, "isArchitect": true, "SecurityGroups": [ { "GroupId": "12", "GroupName": "Tenant A", "GroupRoles": [ { "RoleId": "3", "RoleName": "Modify" } ], "GroupStatus": 0 } ], "ComboName": "Smith, Jane", "FullName": "Jane Smith", "UserApplications": [ { "ApplicationID": "1001", "ApplicationName": "Sample Data", "ApplicationRoleID": "7", "ApplicationRoleName": "Architect", "ApplicationRoleType": "0", "applicationUserDataSourceID": "" } ], "Preferences": [], "UserState": 0, "Language": { "id": 1, "nativename": "English", "englishname": "English", "iso_name": "EN", "phraselist": [] }, "timezone": -5, "timezonename": "America/New_York", "isFastCache": 0, "FastCacheLimit": 0, "lockdate": "0001-01-01T00:00:00", "bforcepasschange": false } ] ``` ### Get a user POST /api/Contact/GetContactById Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-contact-by-id Return a single user by ID, including group memberships, app assignments and Profile Tags. Common use: Cheaper than listing every user when you already hold an ID — for example to confirm a provisioning run applied the roles you expected. Body parameters: - sessionToken (string, required): A valid session token. - ContactId (string, required): The user's ID. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "ContactId": "639234395265102835" } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": "", "ID": "639234395265102835", "LoginName": "jsmith", "FirstName": "Jane", "LastName": "Smith", "EmailAddress": "jsmith@example.com", "Company": "Acme", "Tag1": "TENANT-A", "Tag2": "", "Tag3": "", "Tag4": "", "twofa": "none", "CreateDate": "2026-08-27T14:58:46", "ModifyDate": "2026-08-27T14:58:47", "LoginDate": "2026-08-27T14:58:46", "Pin": null, "AuthType": "PIN", "Description": "", "isAdmin": false, "isSuperAdmin": false, "isBuilder": false, "isAgent": false, "isArchitect": true, "SecurityGroups": [ { "GroupId": "12", "GroupName": "Tenant A", "GroupRoles": [ { "RoleId": "3", "RoleName": "Modify" } ], "GroupStatus": 0 } ], "ComboName": "Smith, Jane", "FullName": "Jane Smith", "UserApplications": [ { "ApplicationID": "1001", "ApplicationName": "Sample Data", "ApplicationRoleID": "7", "ApplicationRoleName": "Architect", "ApplicationRoleType": "0", "applicationUserDataSourceID": "" } ], "Preferences": [], "UserState": 0, "Language": { "id": 1, "nativename": "English", "englishname": "English", "iso_name": "EN", "phraselist": [] }, "timezone": -5, "timezonename": "America/New_York", "isFastCache": 0, "FastCacheLimit": 0, "lockdate": "0001-01-01T00:00:00", "bforcepasschange": false } ``` ### Delete a user POST /api/Contact/DeleteContact Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#delete-contact Remove a user. The request takes the whole user object under user, not an ID, so fetch it first with List users or Get a user. The deleted record is echoed back with ErrorCode 0; group membership and application assignments are already detached, so those collections come back null or empty. Common use: Deprovisioning. Removing the user releases the licence seats consumed by their application assignments. Body parameters: - sessionToken (string, required): A valid session token. - user (object, required): The complete user object to delete. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "user": { "ID": "639234395265102835", "LoginName": "jsmith" } } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": "", "ID": "639234395265102835", "LoginName": "jsmith", "FirstName": "Jane", "LastName": "Smith", "EmailAddress": "jsmith@example.com", "Company": "Acme", "Tag1": "TENANT-A", "Tag2": "", "Tag3": "", "Tag4": "", "twofa": "none", "CreateDate": "2026-08-27T14:58:46", "ModifyDate": "2026-08-27T14:58:47", "LoginDate": "2026-08-27T14:58:46", "Pin": null, "AuthType": "PIN", "Description": "", "isAdmin": false, "isSuperAdmin": false, "isBuilder": false, "isAgent": false, "isArchitect": false, "SecurityGroups": null, "UserApplications": [], "Preferences": [], "UserState": 0, "ComboName": "Smith, Jane", "FullName": "Jane Smith", "Language": { "id": 1, "nativename": null, "englishname": null, "iso_name": null, "phraselist": null }, "timezone": -5, "timezonename": "America/New_York", "isFastCache": 0, "FastCacheLimit": 0, "lockdate": "0001-01-01T00:00:00", "bforcepasschange": false } ``` ### Unlock a user POST /api/Contact/UnlockContact Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#unlock-contact Clear a lockout applied after repeated failed sign-ins. Like Delete a user, it takes the whole user object under user. The account's lockdate is reset. The response returns the account record; membership and application collections are not populated on this call. Common use: Wire this to a help-desk action so support staff can restore access without an administrator opening Yurbi. Body parameters: - sessionToken (string, required): A valid session token. - user (object, required): The complete user object to unlock. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "user": { "ID": "639234395265102835", "LoginName": "jsmith" } } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": "", "ID": "639234395265102835", "LoginName": "jsmith", "FirstName": "Jane", "LastName": "Smith", "EmailAddress": "jsmith@example.com", "Company": "Acme", "Tag1": "TENANT-A", "Tag2": "", "Tag3": "", "Tag4": "", "twofa": "none", "CreateDate": "2026-08-27T14:58:46", "ModifyDate": "2026-08-27T14:58:47", "LoginDate": "2026-08-27T14:58:46", "Pin": null, "AuthType": "PIN", "Description": "", "isAdmin": false, "isSuperAdmin": false, "isBuilder": false, "isAgent": false, "isArchitect": false, "SecurityGroups": null, "UserApplications": [], "Preferences": [], "UserState": 0, "ComboName": "Smith, Jane", "FullName": "Jane Smith", "Language": { "id": 1, "nativename": null, "englishname": null, "iso_name": null, "phraselist": null }, "timezone": -5, "timezonename": "America/New_York", "isFastCache": 0, "FastCacheLimit": 0, "lockdate": "0001-01-01T00:00:00", "bforcepasschange": false } ``` --------------------------------------------------------------- ## Groups & Roles --------------------------------------------------------------- ### List security groups POST /api/Group/GetAllSecurityGroups Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-all-security-groups Return every security group with its full membership. Each member is a complete user object, so responses grow with the size of the instance. Common use: Use it to audit which tenants exist and who belongs to them, and to fetch the group object required by Delete a security group. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json [ { "ErrorCode": 0, "ErrorMessage": "", "GroupId": "12", "GroupName": "Tenant A", "GroupDescription": "All users for Tenant A", "GroupCreated": "2026-08-27T14:58:49", "GroupModified": "2026-08-27T14:58:49", "GroupRoles": [], "Membership": [ { "ErrorCode": 0, "ErrorMessage": "", "ID": "639234395265102835", "LoginName": "jsmith", "FirstName": "Jane", "LastName": "Smith", "EmailAddress": "jsmith@example.com", "Company": "Acme", "Tag1": "TENANT-A", "Tag2": "", "Tag3": "", "Tag4": "", "twofa": "none", "CreateDate": "2026-08-27T14:58:46", "ModifyDate": "2026-08-27T14:58:47", "LoginDate": "2026-08-27T14:58:46", "Pin": null, "AuthType": "PIN", "Description": "", "isAdmin": false, "isSuperAdmin": false, "isBuilder": false, "isAgent": false, "isArchitect": true, "SecurityGroups": [ { "GroupId": "12", "GroupName": "Tenant A", "GroupRoles": [ { "RoleId": "3", "RoleName": "Modify" } ], "GroupStatus": 0 } ], "ComboName": "Smith, Jane", "FullName": "Jane Smith", "UserApplications": [ { "ApplicationID": "1001", "ApplicationName": "Sample Data", "ApplicationRoleID": "7", "ApplicationRoleName": "Architect", "ApplicationRoleType": "0", "applicationUserDataSourceID": "" } ], "Preferences": [], "UserState": 0, "Language": { "id": 1, "nativename": null, "englishname": null, "iso_name": null, "phraselist": [] }, "timezone": -5, "timezonename": "America/New_York", "isFastCache": 0, "FastCacheLimit": 0, "lockdate": "0001-01-01T00:00:00", "bforcepasschange": false } ], "AllUsers": [], "AllRoles": [], "GroupStatus": 0 } ] ``` ### Get a security group POST /api/Group/GetSecurityGroupById Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-security-group-by-id Return a single group with its membership. Common use: The quickest way to confirm that Add user to group or Remove user from group did what you expected. Body parameters: - sessionToken (string, required): A valid session token. - GroupId (string, required): The group's ID. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "GroupId": "12" } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": "", "GroupId": "12", "GroupName": "Tenant A", "GroupDescription": "All users for Tenant A", "GroupCreated": "2026-08-27T14:58:49", "GroupModified": "2026-08-27T14:58:49", "GroupRoles": [], "Membership": [ { "ErrorCode": 0, "ErrorMessage": "", "ID": "639234395265102835", "LoginName": "jsmith", "FirstName": "Jane", "LastName": "Smith", "EmailAddress": "jsmith@example.com", "Company": "Acme", "Tag1": "TENANT-A", "Tag2": "", "Tag3": "", "Tag4": "", "twofa": "none", "CreateDate": "2026-08-27T14:58:46", "ModifyDate": "2026-08-27T14:58:47", "LoginDate": "2026-08-27T14:58:46", "Pin": null, "AuthType": "PIN", "Description": "", "isAdmin": false, "isSuperAdmin": false, "isBuilder": false, "isAgent": false, "isArchitect": true, "SecurityGroups": [ { "GroupId": "12", "GroupName": "Tenant A", "GroupRoles": [ { "RoleId": "3", "RoleName": "Modify" } ], "GroupStatus": 0 } ], "ComboName": "Smith, Jane", "FullName": "Jane Smith", "UserApplications": [ { "ApplicationID": "1001", "ApplicationName": "Sample Data", "ApplicationRoleID": "7", "ApplicationRoleName": "Architect", "ApplicationRoleType": "0", "applicationUserDataSourceID": "" } ], "Preferences": [], "UserState": 0, "Language": { "id": 1, "nativename": null, "englishname": null, "iso_name": null, "phraselist": [] }, "timezone": -5, "timezonename": "America/New_York", "isFastCache": 0, "FastCacheLimit": 0, "lockdate": "0001-01-01T00:00:00", "bforcepasschange": false } ], "AllUsers": [], "AllRoles": [], "GroupStatus": 0 } ``` ### New group template POST /api/Group/NewSecurityGroup Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#new-security-group Return an empty security group object ready to fill in and pass to Save a security group. Common use: Start here when creating a group so every collection is initialised. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": null, "GroupId": null, "GroupName": null, "GroupDescription": null, "GroupCreated": "2026-08-27T14:58:48.6587525+00:00", "GroupModified": "2026-08-27T14:58:48.658753+00:00", "GroupRoles": [], "Membership": [], "AllUsers": [], "AllRoles": [], "GroupStatus": 0 } ``` ### Create or update a group POST /api/Group/SaveSecurityGroup Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#save-security-group Create a security group or update an existing one. group.GroupId decides which: null creates and the server returns the new ID; an existing ID updates. Common use: In a multi-tenant deployment you create one group per tenant, then scope that tenant's library folder to it. Keep tenants in separate groups so scheduling and sharing pickers only ever show a user their own colleagues. Body parameters: - sessionToken (string, required): A valid session token. - group (object, required): The group object. Start from New group template. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "group": { "GroupId": null, "GroupName": "Tenant A", "GroupDescription": "All users for Tenant A", "GroupStatus": 0, "AllUsers": [], "AllRoles": [] } } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": "", "GroupId": "12", "GroupName": "Tenant A", "GroupDescription": "All users for Tenant A", "GroupCreated": "0001-01-01T00:00:00", "GroupModified": "0001-01-01T00:00:00", "GroupRoles": [], "Membership": [], "AllUsers": [], "AllRoles": [], "GroupStatus": 0 } ``` ### Delete a security group POST /api/Group/DeleteSecurityGroup Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#delete-security-group Remove a security group. The request takes the whole group object under group, so fetch it first with List security groups. The deleted record is echoed back with ErrorCode 0. Common use: Tenant offboarding. Remove the tenant's users first, then the folder, then the group. Body parameters: - sessionToken (string, required): A valid session token. - group (object, required): The complete group object to delete. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "group": { "GroupId": "12", "GroupName": "Tenant A" } } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": "", "GroupId": "12", "GroupName": "Tenant A", "GroupDescription": "All users for Tenant A", "GroupCreated": "2026-08-27T14:58:49", "GroupModified": "2026-08-27T14:58:49", "GroupRoles": [], "Membership": [], "AllUsers": [], "AllRoles": [], "GroupStatus": 0 } ``` ### Add user to group POST /api/Group/AddUser Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#add-user Add a user to a security group with a role. The role controls what the user may do with content in folders scoped to that group. Returns the plain-text string User Added Successfully. Supply valid IDs: an unrecognised ContactId returns an error message rather than a status. Common use: The second half of user provisioning. Role IDs come from List roles: 2 View, 3 Modify, 4 Delete are the usual library roles. Body parameters: - sessionToken (string, required): A valid session token. - GroupId (string, required): The group to add the user to. - ContactId (string, required): The user's ID. - RoleId (string, required): The role to grant within the group. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "GroupId": "12", "ContactId": "639234395265102835", "RoleId": "3" } ``` Example response: ```json "User Added Successfully." ``` ### Remove user from group POST /api/Group/RemoveUser Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#remove-user Remove a user from a security group. Returns the plain string "User Removed Successfully.". Common use: Use it when a person moves between tenants or leaves a team, without deleting their account. Body parameters: - sessionToken (string, required): A valid session token. - GroupId (string, required): The group to remove the user from. - ContactId (string, required): The user's ID. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "GroupId": "12", "ContactId": "639234395265102835" } ``` Example response: ```json "User Removed Successfully." ``` ### List roles POST /api/Contact/GetRolesList Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-roles-list Return the fixed role list used by group membership and app assignment. Note these entries use ERROR_CODE and ERROR_MESSAGE rather than the usual casing. Common use: Roles 1–4 govern what a user can do with library content inside a group. Roles 5–7 are licence-consuming application roles assigned through UserApplications on Save user. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json [ { "ERROR_CODE": 0, "ERROR_MESSAGE": "", "RoleId": "0", "RoleName": "None", "RoleDescription": "No access to resources within this group" }, { "ERROR_CODE": 0, "ERROR_MESSAGE": "", "RoleId": "1", "RoleName": "Admin", "RoleDescription": "Full access to resources assigned to this group" }, { "ERROR_CODE": 0, "ERROR_MESSAGE": "", "RoleId": "2", "RoleName": "View", "RoleDescription": "Read-Only access to resources within this group" }, { "ERROR_CODE": 0, "ERROR_MESSAGE": "", "RoleId": "3", "RoleName": "Modify", "RoleDescription": "Edit permissions granted on resources assigned to this group" }, { "ERROR_CODE": 0, "ERROR_MESSAGE": "", "RoleId": "4", "RoleName": "Delete", "RoleDescription": "Delete permissions granted on resources assigned to this group" }, { "ERROR_CODE": 0, "ERROR_MESSAGE": "", "RoleId": "5", "RoleName": "Builder", "RoleDescription": "Consumes Builder License Type" }, { "ERROR_CODE": 0, "ERROR_MESSAGE": "", "RoleId": "6", "RoleName": "Agent", "RoleDescription": "Consumes Agent License Type" }, { "ERROR_CODE": 0, "ERROR_MESSAGE": "", "RoleId": "7", "RoleName": "Architect", "RoleDescription": "Consumes Architect License Type" } ] ``` --------------------------------------------------------------- ## Data Security --------------------------------------------------------------- ### New data tag template POST /api/DataTag/NewDataTag Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#new-data-tag Return an empty data tag object ready to fill in and pass to Save a data tag. Common use: A data tag holds a value that differs per group or per user — a tenant id, a region, a cost centre. An AppShield policy then references that tag in a constraint, so one report serves every tenant while returning only their rows. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json { "ID": "", "Label": "New Data Tag", "SecurityGroups": [], "Contacts": [], "DataTypeEnum": 1, "isGroup": false, "isUser": true, "isActive": true, "DefaultValue": "", "TagGroup": "", "Index": 0, "ErrorCode": 0, "ErrorMessage": "", "ModifiedDate": "0001-01-01T00:00:00", "CreatedDate": "0001-01-01T00:00:00" } ``` ### Create or update a data tag POST /api/DataTag/SaveDataTag Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#save-data-tag Create a data tag or update an existing one. An empty ID creates and the server returns the new one. Per-group values go in SecurityGroups: set RelationshipType and RelationType to tag_grp, RightID to the group's ID, and the value itself in Option1. Per-user values use the Contacts collection the same way. DefaultValue applies to anyone with no specific value assigned. Common use: Create one tag per security dimension, then add a value for each tenant group as you onboard them. Set isGroup true and isUser false for group-scoped tagging. Body parameters: - sessionToken (string, required): A valid session token. - datatag (object, required): The data tag object. Start from New data tag template. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "datatag": { "ID": "", "Label": "tenantid", "TagGroup": "Tenancy", "DataTypeEnum": 1, "isGroup": true, "isUser": false, "isActive": true, "DefaultValue": "NONE", "Contacts": [], "Index": 0, "SecurityGroups": [ { "LeftID": "", "RightID": "12", "RelationshipType": "tag_grp", "RelationType": "tag_grp", "Option1": "TENANT-A", "PermissionTypeEnum": 0 } ] } } ``` Example response: ```json { "ID": "639234411252055064", "Label": "tenantid", "SecurityGroups": [ { "ErrorCode": 0, "ErrorMessage": "", "LeftID": "639234411252055064", "RightID": "12", "RelationshipType": "tag_grp", "RelationType": "tag_grp", "Option1": "TENANT-A", "Option2": "", "Option3": "", "Option4": "", "Option5": "", "Option6": "", "Option7": "", "Option8": "", "Option9": "", "Option10": "", "PermissionTypeEnum": 20 } ], "Contacts": [], "DataTypeEnum": 1, "isGroup": true, "isUser": false, "isActive": true, "DefaultValue": "NONE", "TagGroup": "Tenancy", "Index": 0, "ErrorCode": 0, "ErrorMessage": "", "ModifiedDate": "2026-08-27T15:25:25", "CreatedDate": "2026-08-27T15:25:25" } ``` ### List data tags POST /api/DataTag/GetAllDataTags Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-all-data-tags Return every data tag with its group and user value assignments. Common use: Use it to confirm a tenant's value was written, and to fetch the object required by Delete a data tag. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json [ { "ID": "639234411252055064", "Label": "tenantid", "SecurityGroups": [ { "ErrorCode": 0, "ErrorMessage": "", "LeftID": "639234411252055064", "RightID": "12", "RelationshipType": "tag_grp", "RelationType": "tag_grp", "Option1": "TENANT-A", "Option2": "", "Option3": "", "Option4": "", "Option5": "", "Option6": "", "Option7": "", "Option8": "", "Option9": "", "Option10": "", "PermissionTypeEnum": 20 } ], "Contacts": [], "DataTypeEnum": 1, "isGroup": true, "isUser": false, "isActive": true, "DefaultValue": "NONE", "TagGroup": "Tenancy", "Index": 0, "ErrorCode": 0, "ErrorMessage": "", "ModifiedDate": "2026-08-27T15:25:25", "CreatedDate": "2026-08-27T15:25:25" } ] ``` ### Delete a data tag POST /api/DataTag/DeleteDataTag Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#delete-data-tag Remove a data tag. Takes the whole tag object under datatag, so fetch it first with List data tags. Returns a {Code, Message} result. Common use: Remove a security dimension you no longer use. Check that no active policy still references the tag before deleting it. Body parameters: - sessionToken (string, required): A valid session token. - datatag (object, required): The complete data tag object to delete. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "datatag": { "ID": "639234411252055064", "Label": "tenantid" } } ``` Example response: ```json { "Code": 0, "Message": "Data Tag Successfully Deleted" } ``` ### New policy template POST /api/AppShield/NewPolicy Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#new-policy Return an empty AppShield policy with a generated name and date, ready to fill in and pass to Save a policy. Common use: Always start a policy here. Save a policy expects the collections this template initialises. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json { "ErrorCode": null, "ErrorMessage": null, "id": null, "Name": "New AppShield Policy", "Description": "AppShield Policy Created 08/27/2026 14:58:50", "CreatedDate": "2026-08-27T14:58:50.949385+00:00", "ModifiedDate": "08/27/2026 14:58:50", "CreatedBy": null, "ModifiedBy": null, "Constraints": [], "Groups": null, "Users": null, "isActive": false } ``` ### List policies POST /api/AppShield/GetAllAppshieldPolicies Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-all-appshield-policies Return every AppShield policy on the instance with its constraints, assigned groups and assigned users. Common use: Use it to audit which policies are active and which groups they cover, and to fetch the object Delete a policy requires. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json [ { "ErrorCode": "0", "ErrorMessage": "", "id": "639234411233338341", "Name": "Tenant row-level security", "Description": "Constrains every report to the caller's tenant id", "CreatedDate": "2026-08-27T15:25:23.3338367+00:00", "ModifiedDate": "08/27/2026 15:25:23", "CreatedBy": { "ID": "639234363032231617", "LoginName": "apitest", "FullName": "API Test" }, "Constraints": [], "Groups": [ { "GroupId": "12" } ], "Users": [], "isActive": false } ] ``` ### Create or update a policy POST /api/AppShield/SaveAppShieldPolicy Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#save-appshield-policy Create or update an AppShield policy and assign it to groups and users in the same call. Build the policy from New policy template; Constraints, Groups and Users must be arrays rather than null. The groups and users parameters are arrays of IDs and are what the assignment is built from. The response echoes the saved policy and is large, because it embeds the full user records of everyone the policy touches. When updating a policy, build the request from the compact object returned by List policies rather than resending a previous save response, which can exceed the request size limit. Common use: Assign the policy to All Users so every account is constrained, then let the data tag decide what each tenant sees. Set isActive true when you are ready to enforce it. Body parameters: - sessionToken (string, required): A valid session token. - policy (object, required): The policy object, built from the template. - isDeepSave (boolean, required): Save the policy together with its constraints. - groups (array, required): Group IDs the policy applies to. Send an empty array for none. - users (array, required): User IDs the policy applies to. Send an empty array for none. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "policy": { "id": null, "Name": "Tenant row-level security", "Description": "Constrains every report to the caller's tenant id", "Constraints": [], "Groups": [], "Users": [], "isActive": false }, "isDeepSave": true, "groups": [ "12" ], "users": [] } ``` Example response: ```json { "ErrorCode": "0", "ErrorMessage": "", "id": "639234411233338341", "Name": "Tenant row-level security", "Description": "Constrains every report to the caller's tenant id", "CreatedDate": "2026-08-27T15:25:23.3338367+00:00", "ModifiedDate": "08/27/2026 15:25:23", "CreatedBy": { "ID": "639234363032231617", "LoginName": "apitest", "FullName": "API Test" }, "Constraints": [], "Groups": [ { "GroupId": "12" } ], "Users": [], "isActive": false } ``` ### Delete a policy POST /api/AppShield/DeletePolicy Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#delete-policy Remove an AppShield policy. Takes the whole policy object under policy, so fetch it first with List policies. Returns a plain status string. Common use: Tenant offboarding, or replacing a policy with a revised constraint set. Body parameters: - sessionToken (string, required): A valid session token. - policy (object, required): The complete policy object to delete. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "policy": { "id": "639234411233338341", "Name": "Tenant row-level security" } } ``` Example response: ```json "App Shield Policy Deleted" ``` ### Add group to policy POST /api/AppShield/AddGroup Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#appshield-add-group Attach a security group to an existing policy. Returns the plain-text string Success. An unknown policy id returns Policy not found. Other inputs, including an unknown group id, also return Success, so confirm the assignment by reading the policy back with List policies. Common use: Use it to bring a newly created tenant group under an existing policy without rewriting the policy object. Body parameters: - sessionToken (string, required): A valid session token. - policyid (string, required): The policy's ID. - groupid (string, required): The security group's ID. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "policyid": "639234411233338341", "groupid": "12" } ``` Example response: ```json "Success" ``` ### Remove group from policy POST /api/AppShield/RemoveGroup Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#appshield-remove-group Detach a security group from a policy. Returns the plain-text string Success. An unknown policy id returns Policy not found. Other inputs, including an unknown group id, also return Success, so confirm the assignment by reading the policy back with List policies. Common use: Use it when a tenant no longer needs a policy's constraint, or while testing a policy against a single group. Body parameters: - sessionToken (string, required): A valid session token. - policyid (string, required): The policy's ID. - groupid (string, required): The security group's ID. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "policyid": "639234411233338341", "groupid": "12" } ``` Example response: ```json "Success" ``` --------------------------------------------------------------- ## Apps & Servers --------------------------------------------------------------- ### List applications POST /api/App/GetApplicationList Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-app-list Return every application on the instance with its licence position, the users assigned to it, and its registered database servers. Responses are large: each entry embeds a full module profile including user records. Common use: Use it to discover application IDs, to check how many Agent, Builder and Architect seats a module has consumed, and to confirm an integration user has been granted the role it needs. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json [ { "ReportModule": { "ID": "1003", "Name": "Test Load", "ModuleType": "anydb1003", "ProductCode": "ANYDB", "isAnyDbApp": true }, "ModuleProfile": { "isLicensed": true, "LicensedQuanity": 999, "ConsumedQuanity": 1, "NextExpiration": "12/31/2035", "IsExpired": false, "ArchitectConsumptionCount": 3, "BuilderConsumptionCount": 1, "AgentConsumptionCount": 1, "Membership": [] }, "Status": 0, "RegisteredServers": [ { "ErrorCode": 0, "ErrorMessage": "", "ID": "17769733521", "ReportModule": { "ID": "1003", "Name": "Test Load", "ModuleType": "anydb1003", "ProductCode": "ANYDB", "isAnyDbApp": true, "isPremiumApp": false, "isAPIApp": false }, "ModuleType": "ANYDB", "TimeZone": 0, "DaylightSavings": false, "DatabaseOwner": "", "DatabaseServer": "db.internal.example.com", "DatabaseLogin": "reporting", "DatabaseName": "sales", "DatabasePassword": "", "DatabaseDriver": "POSTGRESQL", "DatabasePlatform": "postgresql", "CommandTimeout": 30, "ConnectionTimeout": 10, "Permissions": [], "MappedAnyDB": "", "DisplayName": "Test Load", "allowstoredproc": 0, "allowdirectsql": 0, "datasources": [], "additionalparams": "" } ] } ] ``` ### List registered servers POST /api/RegServers/GetAdminRegisteredServers Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-registered-servers Return every registered database server with its connection settings. DatabasePassword is always returned empty. Common use: Use it to find the ID (the RegServerID) that App Builder calls require, and to audit which databases an instance connects to. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json [ { "ErrorCode": 0, "ErrorMessage": "", "ID": "17769733521", "ReportModule": { "ID": "1003", "Name": "Test Load", "ModuleType": "anydb1003", "ProductCode": "ANYDB", "isAnyDbApp": true, "isPremiumApp": false, "isAPIApp": false }, "ModuleType": "ANYDB", "TimeZone": 0, "DaylightSavings": false, "DatabaseOwner": "", "DatabaseServer": "db.internal.example.com", "DatabaseLogin": "reporting", "DatabaseName": "sales", "DatabasePassword": "", "DatabaseDriver": "POSTGRESQL", "DatabasePlatform": "postgresql", "CommandTimeout": 30, "ConnectionTimeout": 10, "Permissions": [], "MappedAnyDB": "", "DisplayName": "Test Load", "allowstoredproc": 0, "allowdirectsql": 0, "datasources": [], "additionalparams": "" } ] ``` ### List time zones POST /api/RegServers/GetTimeZones Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-timezones Return the time zone list Yurbi uses for users and registered servers. Common use: Populate a time zone picker when provisioning users, so the timezone and timezonename you send to Save user are values Yurbi recognises. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json [ { "Name": "Eastern Time", "Code": "GMT -0500", "Offset": -5 }, { "Name": "Central Time", "Code": "GMT -0600", "Offset": -6 } ] ``` ### Register an AnyDB app POST /api/RegServers/InsertAnyDbModule Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#insert-anydb-module Create a new AnyDB application shell. The returned module carries the ID used by every App Builder call. Common use: The first step when provisioning a tenant that needs its own data source. After creating the app, grant your integration user the Architect role on it, or subsequent App Builder calls will not see it. Body parameters: - sessionToken (string, required): A valid session token. - appname (string, required): Name for the new application. - description (string, required): Description for the new application. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "appname": "Tenant A Data", "description": "Provisioned via the API" } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": null, "ID": "1010", "Name": "Tenant A Data", "ModuleType": "anydb1010", "ProductCode": "ANYDB", "isAnyDbApp": true } ``` ### Save a registered server POST /api/RegServers/SaveRegSrv Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#save-regsrv Create or update the database connection behind an application. Test the settings with Test connection before saving. Common use: Point a newly registered AnyDB app at its database, or rotate credentials on an existing connection. Body parameters: - sessionToken (string, required): A valid session token. - regserver (object, required): The registered server object. - bsaveasanydb (boolean, optional): Save as an AnyDB application. - badvrpt (boolean, optional): Enable advanced report support. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "bsaveasanydb": true, "badvrpt": false, "regserver": { "ID": "17769733521", "DisplayName": "Tenant A Data", "DatabaseDriver": "POSTGRESQL", "DatabasePlatform": "postgresql", "DatabaseServer": "db.internal.example.com", "DatabaseLogin": "reporting", "DatabasePassword": "YOUR_DB_PASSWORD", "DatabaseName": "sales", "DatabaseOwner": "", "ConnectionTimeout": 10, "CommandTimeout": 30 } } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": "", "ID": "17769733521", "ReportModule": { "ID": "1003", "Name": "Test Load", "ModuleType": "anydb1003", "ProductCode": "ANYDB", "isAnyDbApp": true, "isPremiumApp": false, "isAPIApp": false }, "ModuleType": "ANYDB", "TimeZone": 0, "DaylightSavings": false, "DatabaseOwner": "", "DatabaseServer": "db.internal.example.com", "DatabaseLogin": "reporting", "DatabaseName": "sales", "DatabasePassword": "", "DatabaseDriver": "POSTGRESQL", "DatabasePlatform": "postgresql", "CommandTimeout": 30, "ConnectionTimeout": 10, "Permissions": [], "MappedAnyDB": "", "DisplayName": "Test Load", "allowstoredproc": 0, "allowdirectsql": 0, "datasources": [], "additionalparams": "" } ``` ### Test connection POST /api/RegServers/TestConnection Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#test-connection Test a database connection without saving it. Returns a plain string: "Passed" on success, otherwise a message describing the failure, for example "Test Failed - Name or service not known". Common use: Validate credentials during provisioning before writing them with Save a registered server. Body parameters: - sessionToken (string, required): A valid session token. - regserver (object, required): The connection settings to test. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "regserver": { "DisplayName": "Tenant A Data", "DatabaseDriver": "POSTGRESQL", "DatabasePlatform": "postgresql", "DatabaseServer": "db.internal.example.com", "DatabaseLogin": "reporting", "DatabasePassword": "YOUR_DB_PASSWORD", "DatabaseName": "sales", "DatabaseOwner": "", "ConnectionTimeout": 10, "CommandTimeout": 30 } } ``` Example response: ```json "Passed" ``` --------------------------------------------------------------- ## Library --------------------------------------------------------------- ### List a folder's contents POST /api/library/GetListByFolderID Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-list-by-folder Return the reports and dashboards in a folder. itemtype identifies the kind of item — 0 is a dashboard and other values are report output types. item_flags is a JSON string rather than an object. Common use: Use it to browse a tenant's folder, and filter on itemtype before passing IDs to report endpoints: dashboards are returned here too and are not valid report IDs. Body parameters: - sessionToken (string, required): A valid session token. - LibraryID (string, required): The folder ID. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "LibraryID": "2" } ``` Example response: ```json [ { "id": 1776974455, "ReportName": "Count of Records", "ReportType": "Sales_Orders", "AppDisplayName": "Test Load", "ModType": "anydb1003", "folderid": 2, "folderpath": "", "Published": "", "Description": "Count of Records", "PluginId": 0, "error_code": 0, "error_message": null, "CreatedDate": "2026-04-23T20:00:55Z", "CreatedBy": "Ferguson, David", "ModifiedBy": "Ferguson, David", "LastModified": "2026-04-23T20:00:51Z", "Permissions": [], "Application": "Test Load", "isUserAdmin": true, "isUserView": true, "isUserModify": true, "isUserDelete": true, "itemtype": 1, "itemsubtype": "", "isFav": false, "index": 0, "isUserArchitect": true, "isUserBuilder": true, "isUserAgent": true, "isPublicView": false, "isEmbedable": false, "isPrivate": false, "item_flags": "{\"isLagacyMode\":0,\"visualizationOnly\":0,\"DisplayFullRecords\":0}" } ] ``` ### Get the library tree POST /api/library/GetAllLibraryTree Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-all-library-tree Return the folder tree the calling user can see. Each entry wraps its tree under a rootnode key: the Public Library (libtype 1), the caller's personal library (libtype 2), and Favorites when includefav is true. isUserAdmin, isUserModify and isUserDelete describe what the caller may do in each folder. Common use: Use it to find a writable folder before saving a report. Folders scoped to a security group appear only for members of that group, so the tree differs per user. Body parameters: - sessionToken (string, required): A valid session token. - includefav (boolean, optional): Include the Favorites tree. - includePersonal (boolean, optional): Include personal folders. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "includefav": false } ``` Example response: ```json [ { "rootnode": { "id": 0, "text": "Public Library", "level": "###", "libtype": 1, "children": [ { "id": 2, "text": "Tenant A", "children": [], "level": "0", "isUserAdmin": true, "isUserModify": true, "isUserDelete": true, "isUserView": false, "isPublicView": false, "libtype": 1 } ] } }, { "rootnode": { "id": 0, "text": "My Library", "children": [], "level": "###", "libtype": 2 } } ] ``` ### New folder template POST /api/library/NewLibraryFolder Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#new-library-folder Return an empty folder object ready to fill in and pass to Save a folder. The folder's name is the fname field. Common use: Start here when creating a tenant's folder so every field the save expects is present. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json { "error_code": 0, "error_message": "", "ParentLibrary": null, "id": 0, "folderpath": null, "fname": "New Folder", "flevel": null, "fmodtype": null, "isParent": false, "isHidden": false, "InheritPermissions": false, "Permissions": [], "isUserAdmin": false, "isUserView": false, "isUserModify": false, "isPublicView": false, "isUserDelete": false, "isPersonalFolder": false, "isRestricted": false } ``` ### Create or update a folder POST /api/library/SaveLibraryFolder Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#save-library-folder Create or update a library folder. Set the name in fname. Scope the folder to security groups through the Permissions array: one entry per group, with RelationshipType and RelationType set to fld_grp, RightID set to the group ID, and PermissionTypeEnum 2. A folder with no group permissions is visible to All Users. Common use: Give each tenant a folder scoped to that tenant's group and nothing else. Members can then save and share content inside it, while the folder stays invisible to every other tenant. Body parameters: - sessionToken (string, required): A valid session token. - libraryfolder (object, required): The folder object. Start from New folder template. - isShared (boolean, optional): True for a shared folder in the Public Library. - currentUserId (string, optional): Owner for a personal folder. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "isShared": true, "currentUserId": "", "libraryfolder": { "id": 0, "fname": "Tenant A", "isParent": false, "isHidden": false, "InheritPermissions": false, "Permissions": [ { "LeftID": "", "RightID": "12", "RelationshipType": "fld_grp", "RelationType": "fld_grp", "PermissionTypeEnum": 2 } ] } } ``` Example response: ```json { "error_code": 0, "error_message": "", "ParentLibrary": null, "id": 4, "folderpath": "", "fname": "Tenant A", "flevel": ":4", "fmodtype": "AHD", "isParent": false, "isHidden": false, "InheritPermissions": false, "Permissions": [ { "ErrorCode": 0, "ErrorMessage": "", "LeftID": "4", "RightID": "12", "RelationshipType": "fld_grp", "RelationType": "fld_grp", "PermissionTypeEnum": 2 } ], "Application": null, "isUserAdmin": true, "isUserView": true, "isUserModify": true, "isPublicView": false, "isUserDelete": true, "isPersonalFolder": false, "isRestricted": false } ``` ### Get a folder POST /api/library/GetFolderById Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-folder-by-id Return a single folder with its permission assignments. Common use: Confirm a folder is scoped to the group you expect after provisioning a tenant. Body parameters: - sessionToken (string, required): A valid session token. - folderid (string, required): The folder ID. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "folderid": "4" } ``` Example response: ```json { "error_code": 0, "error_message": "", "ParentLibrary": null, "id": 4, "folderpath": "", "fname": "Tenant A", "flevel": ":4", "fmodtype": "AHD", "isParent": false, "isHidden": false, "InheritPermissions": false, "Permissions": [ { "ErrorCode": 0, "ErrorMessage": "", "LeftID": "4", "RightID": "12", "RelationshipType": "fld_grp", "RelationType": "fld_grp", "PermissionTypeEnum": 2 } ], "Application": null, "isUserAdmin": true, "isUserView": true, "isUserModify": true, "isPublicView": false, "isUserDelete": true, "isPersonalFolder": false, "isRestricted": false } ``` ### Delete a folder POST /api/library/DelFolder Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#del-folder Delete a library folder and its contents. Returns a {returncode, message} result reporting how many items were affected. Common use: Tenant offboarding. Remove the folder before the group it is scoped to. Body parameters: - sessionToken (string, required): A valid session token. - folderid (string, required): The folder ID. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "folderid": "4" } ``` Example response: ```json { "returncode": 0, "message": "Delete Action Complete: 1 affected" } ``` ### Delete a report POST /api/library/DelReport Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#del-report Delete a report by ID. Returns 0 on success and 9000 on failure — the opposite of the numeric conventions used elsewhere. Common use: Roll back a report created by an automated build, or remove content during offboarding. Body parameters: - sessionToken (string, required): A valid session token. - ReportId (string, required): The report's ID. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "ReportId": "1776974455" } ``` Example response: ```json 0 ``` ### Search reports POST /api/library/SearchReports Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#search-reports Search library items by name. Returns an array of matches, or an empty array when nothing matches. Common use: The quickest way to resolve a report name to an ID. Results respect the caller's permissions, so a tenant user only ever sees their own content. Body parameters: - sessionToken (string, required): A valid session token. - searchstring (string, required): Text to match against item names. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "searchstring": "Revenue" } ``` Example response: ```json [ { "id": 1776974455, "ReportName": "Count of Records", "ReportType": "Sales_Orders", "AppDisplayName": "Test Load", "ModType": "anydb1003", "folderid": 2, "folderpath": "", "Published": "", "Description": "Count of Records", "PluginId": 0, "error_code": 0, "error_message": null, "CreatedDate": "2026-04-23T20:00:55Z", "CreatedBy": "Ferguson, David", "ModifiedBy": "Ferguson, David", "LastModified": "2026-04-23T20:00:51Z", "Permissions": [], "Application": "Test Load", "isUserAdmin": true, "isUserView": true, "isUserModify": true, "isUserDelete": true, "itemtype": 1, "itemsubtype": null, "isFav": false, "index": 0, "isUserArchitect": true, "isUserBuilder": true, "isUserAgent": true, "isPublicView": false, "isEmbedable": false, "isPrivate": false, "item_flags": null } ] ``` ### Search dashboards POST /api/Dashboard/SearchDashboardList Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#search-dashboard-list Search dashboards by name. Returns a compact list — note the field names differ from report search results. Common use: Resolve a dashboard name to the ID used in embed URLs and favourite calls. Body parameters: - sessionToken (string, required): A valid session token. - search (string, optional): Text to match. Send an empty string to list all. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "search": "Sales" } ``` Example response: ```json [ { "id": 1, "name": "Sales Overview", "descr": "Tenant A sales", "weight": 0, "isFav": 1, "isPersonal": 0 } ] ``` ### Favourite a dashboard POST /api/library/FavDash Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#fav-dashboard Add a dashboard to the calling user's favourites. Takes DashboardId; the favourite is recorded against the session's user. Returns a number rather than an envelope. Confirm the change through isFav in Search dashboards. Common use: Confirm the change through isFav in Search dashboards, where it is returned as 1 or 0. Body parameters: - sessionToken (string, required): A valid session token. - DashboardId (string, required): The dashboard's ID. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "DashboardId": "1" } ``` Example response: ```json 0 ``` ### Un-favourite a dashboard POST /api/library/UnFavDash Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#unfav-dashboard Remove a dashboard from the calling user's favourites. Returns a number rather than an envelope. Confirm the change through isFav in Search dashboards. Common use: The counterpart to Favourite a dashboard. Body parameters: - sessionToken (string, required): A valid session token. - DashboardId (string, required): The dashboard's ID. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "DashboardId": "1" } ``` Example response: ```json 1 ``` ### Favourite a report POST /api/library/FavReport Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#fav-report Add a report to the calling user's favourites. The favourite is recorded against the session's user, so no contact ID is needed. Returns a number rather than an envelope. Treat any 2xx response as accepted and confirm the change through isFav in Search reports. Common use: Back a star control in your own interface. Confirm the change through isFav in Search reports. Body parameters: - sessionToken (string, required): A valid session token. - ReportId (string, required): The report's ID. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "ReportId": "1776974455" } ``` Example response: ```json 1 ``` ### Un-favourite a report POST /api/library/UnFavReport Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#unfav-report Remove a report from the calling user's favourites. Returns a number rather than an envelope. Treat any 2xx response as accepted and confirm the change through isFav in Search reports. Common use: The counterpart to Favourite a report. Body parameters: - sessionToken (string, required): A valid session token. - ReportId (string, required): The report's ID. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "ReportId": "1776974455" } ``` Example response: ```json 1 ``` --------------------------------------------------------------- ## App Builder --------------------------------------------------------------- ### List AnyDB apps POST /api/AppBuilder/GetAnyDbModulesList Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-anydb-modules-list Return every AnyDB application with its registered server. ID is the RegServerID and ReportModule.ID is the ModuleID — App Builder calls need both. Common use: The starting point for any App Builder work: resolve the app you are about to read or modify. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json [ { "ErrorCode": 0, "ErrorMessage": "", "ID": "17769733521", "ReportModule": { "ID": "1003", "Name": "Test Load", "ModuleType": "anydb1003", "ProductCode": "ANYDB", "isAnyDbApp": true, "isPremiumApp": false, "isAPIApp": false }, "ModuleType": "ANYDB", "TimeZone": 0, "DaylightSavings": false, "DatabaseOwner": "", "DatabaseServer": "db.internal.example.com", "DatabaseLogin": "reporting", "DatabaseName": "sales", "DatabasePassword": "", "DatabaseDriver": "POSTGRESQL", "DatabasePlatform": "postgresql", "CommandTimeout": 30, "ConnectionTimeout": 10, "Permissions": [], "MappedAnyDB": "", "DisplayName": "Test Load", "allowstoredproc": 0, "allowdirectsql": 0, "datasources": [], "additionalparams": "" } ] ``` ### Get an AnyDB app POST /api/AppBuilder/GetAnyDbModule Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-anydb-module Return an application's report types, including their SQL tables, joins and field trees. Responses are large — an app with a few hundred tables runs to several megabytes. Common use: Read this before writing with Save an AnyDB app: it gives you the next free RepTypeID and a snapshot to roll back to. Body parameters: - sessionToken (string, required): A valid session token. - moduleid (string, required): The application's module ID. - regserverid (string, required): The registered server ID. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "moduleid": "1003", "regserverid": "17769733521" } ``` Example response: ```json { "ReportTypes": [ { "ErrorCode": 0, "Moduleid": 1003, "RepTypeID": 0, "RepTypeName": "Sales_Orders", "SQLTables": [ { "tablename": "sales_orders", "tableowner": "", "tablealias": "Sales_Orders" } ], "FieldTree": [ { "id": 0, "fname": "Data", "flevel": "0", "nodetype": "G", "idx_order": 1 }, { "id": 2, "fname": "order_id", "flevel": "0:2", "nodetype": "F", "tablealias": "Sales_Orders", "sqlfieldname": "order_id", "datatype": "cha", "idx_order": 3 } ] } ], "DBSQLTableList": { "AllDbtables": [] }, "isExcelCSV": false } ``` ### Save an AnyDB app POST /api/AppBuilder/SaveAnyDbModule Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#save-anydb-module Write report types to an application. Each report type in the payload is replaced in full; report types you leave out are untouched. Returns 1 on success and 0 otherwise, so confirm the result by reading the module back. Common use: Send only the report types you are creating or changing rather than posting a whole module back. See Building apps & reports for the join and field tree rules. Body parameters: - sessionToken (string, required): A valid session token. - anydbmodule (object, required): The module payload containing the report types to write. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "anydbmodule": { "ReportTypes": [], "DBSQLTableList": { "AllDbtables": [] }, "isExcelCSV": false, "ApiEndpointList": null } } ``` Example response: ```json 1 ``` ### Get a table definition POST /api/AppBuilder/GetTableDef Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-table-def Return the columns of a database table as the driver reports them. datatype is the native database type, not a Yurbi field code. Common use: Use it when building a report type to see what columns exist and whether they accept nulls, before mapping them into a field tree. Body parameters: - sessionToken (string, required): A valid session token. - tablename (string, required): The table to describe. - tableowner (string, optional): Schema or owner. Send an empty string when the app registers tables without one. - regserverid (string, required): The registered server ID. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "tablename": "sales_orders", "tableowner": "", "regserverid": "17769733521" } ``` Example response: ```json [ { "columnname": "order_id", "datatype": "text", "tablealias": null, "MaxLength": 1, "isNullValueAllowed": true }, { "columnname": "order_date", "datatype": "timestamp without time zone", "tablealias": null, "MaxLength": 1, "isNullValueAllowed": true }, { "columnname": "revenue", "datatype": "real", "tablealias": null, "MaxLength": 24, "isNullValueAllowed": true } ] ``` ### List field type codes POST /api/AppBuilder/GetDataTypes Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-data-types Return the Yurbi field type codes and what each one does. These codes appear throughout report metadata as Fieldtype and yurbitype. Common use: Use it when mapping database columns into a field tree, and when deciding how a value should be formatted or converted for display. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json [ { "name": "cha", "description": "Character type field", "id": 1 }, { "name": "num", "description": "Integer and other numeric field types", "id": 2 }, { "name": "dat", "description": "SQL datetime field", "id": 4 }, { "name": "doz", "description": "sql date only field with no timezone conversions.", "id": 28 } ] ``` ### List report types POST /api/RegServers/GetReportTypes Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-report-types List the report types available in an app. A report type is the semantic layer a report is built on — it defines which tables are in play and how they join. Every report belongs to exactly one, and a report references its report type by name, so names must stay unique within an app. Common use: Populate a report-type picker, or check whether a report type already exists before creating one. Body parameters: - sessionToken (string, required): A valid session token. - ModuleType (string, required): The module type, e.g. ANYDB. - RegServerID (string, required): The app's RegServerID. - ReportModuleID (string, required): The app's ModuleID. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "ModuleType": "ANYDB", "RegServerID": "177340979543", "ReportModuleID": "1001" } ``` Example response: ```json [ { "reporttypeid": 0, "name": "Sales Pipeline Dataset", "moduleid": 1001 }, { "reporttypeid": 1, "name": "Manufacturing Dataset", "moduleid": 1001 } ] ``` ### Get a report type's field tree POST /api/RegServers/GetReportTree Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-report-tree Return the browsable field tree for one report type: folders (type: "Folder") containing fields (type: "Field"). Each field node carries everything NewField needs — dbfieldname, dbtablealias, dbparenttablealias, fieldtype and Tag. Pass a node straight through to NewField to add it to a report. Common use: Render a field picker, or drive report authoring from a script: read the tree, pick nodes, hand them to NewField. Body parameters: - sessionToken (string, required): A valid session token. - RegServerID (string, required): The app's RegServerID. - ReportType (string, required): The report type's name. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "RegServerID": "177340979543", "ReportType": "Sales Pipeline Dataset" } ``` Example response: ```json { "rootnode": { "id": 0, "text": "Sales Pipeline Dataset", "type": "Folder", "Tag": "RN", "children": [ { "id": 1, "text": "Service Data", "type": "Folder", "Tag": "900000", "children": [ { "id": 2, "text": "Ticket ID", "type": "Field", "Tag": "900001", "dbfieldname": "Report_ID", "dbtablealias": "Service Data", "dbparenttablealias": "Service Data", "fieldtype": "cha", "ReportFieldName": "Ticket ID", "children": [] } ] } ] } } ``` --------------------------------------------------------------- ## Reports --------------------------------------------------------------- ### New report template POST /api/Report/NewReport Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#new-report Return an empty report object with every collection initialised, ready to fill in and pass to Save a report. Common use: Always start here. Save a report expects collections such as linkreports to be present, and this template supplies them. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": "", "ReportID": null, "Reportname": "New Report", "ModType": null, "ReportType": null, "ServerName": null, "Description": "", "FieldList": [], "Permissions": [], "AdHocFields": [], "linkreports": [], "FormLayout": [], "OutputType": 1, "OutputTypeClass": null, "Distinct": 0, "TopN": null, "folderid": 0 } ``` ### New report field POST /api/Report/NewField Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#new-field Turn a node from Get the report tree into a report field, filling in derived values such as RenamedField, the alias used in the generated SQL. Common use: Use this rather than hand-building field objects: the naming and aliasing rules are applied for you. Set fieldindex yourself, starting at 1, and give Criteria an empty array before saving. Body parameters: - sessionToken (string, required): A valid session token. - field (object, required): A Field node from the report tree. - bAdvRpt (boolean, optional): True when building an advanced report. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "bAdvRpt": false, "field": { "id": 2, "text": "order_id", "type": "Field", "Tag": "900001", "dbfieldname": "order_id", "dbtablealias": "Sales_Orders", "dbparenttablealias": "Sales_Orders", "fieldtype": "cha", "ReportFieldName": "order_id", "RenamedField": null, "children": [] } } ``` Example response: ```json { "fieldindex": 0, "DbParentTableAlias": "Sales_Orders", "DbTableAlias": "Sales_Orders", "DbFieldName": "order_id", "DisplayFieldName": "Order", "ReportFieldName": "Order", "RenamedField": "Order", "Fieldtype": "cha", "SearchCriteria": "", "strGroup": null, "Formula": "", "tbl5": "Y", "grouped": 0, "Criteria": null, "ERROR_CODE": 0, "ERROR_MESSAGE": "" } ``` ### New criteria template POST /api/Report/NewCriteria Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#new-criteria Return an empty criteria object for a report field. Common use: Start here when adding a filter by hand, then set Field to the field's display name, choose an Op, and set bprompt true if the value should be prompted at run time. Body parameters: - sessionToken (string, required): A valid session token. - field (object, optional): The field the criteria belongs to. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json { "Index": 0, "Field": null, "Op": null, "Value1": null, "Value2": null, "Logical": null, "Nested": false, "cond": null, "bskip": false, "bprompt": false, "sortorder": null, "vrpt": null, "vrpt_displaycol": null, "vrpt_valuecol": null, "vdefaulttop": 0, "bgetvalues": false, "flags": null } ``` ### New totals template POST /api/Report/NewTotals Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#new-totals Return an empty totals object for a report field. Common use: Use it when adding totals or subtotals to a report field before saving. Body parameters: - sessionToken (string, required): A valid session token. - type (string, optional): Totals type to pre-set on the returned object. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json { "type": null, "func": null, "field1": null, "field2": null, "Value2": null, "percent": null, "addgtotal": false } ``` ### Create or update a report POST /api/Report/SaveReport Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#save-report Create a report or update an existing one. report.ReportID decides which: an empty string creates and the server returns the new ID; an existing ID updates. Build the object from New report template so its collections are populated, and set folderid to a folder the user can modify. Common use: The end of the report build sequence: template, fields, then save. Preview the SQL first with Get SQL to check the statement before writing anything. Body parameters: - sessionToken (string, required): A valid session token. - report (object, required): The report object, built from the template. - processlinks (boolean, optional): Process linked reports on save. Defaults to true. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "report": { "ReportID": "", "Reportname": "Orders by Customer", "Description": "Created via the API", "ModType": "anydb1003", "ReportType": "Sales_Orders", "ServerName": "db.internal.example.com", "ModuleName": "Test Load", "folderid": 2, "OutputType": 1, "OutputTypeClass": "datagrid", "Distinct": 0, "TopN": "0", "FieldList": [ { "fieldindex": 1, "DbParentTableAlias": "Sales_Orders", "DbTableAlias": "Sales_Orders", "DbFieldName": "order_id", "DisplayFieldName": "Order", "ReportFieldName": "Order", "RenamedField": "Order", "Fieldtype": "cha", "SearchCriteria": "", "strGroup": null, "Formula": "", "tbl5": "Y", "grouped": 0, "Criteria": [] } ], "linkreports": [], "AdHocFields": [], "FormLayout": [], "Permissions": [ { "RelationshipType": "rpt_grp", "RelationType": "rpt_grp", "LeftID": "1", "RightID": "0", "Option10": "1", "PermissionTypeEnum": 1 } ], "flags": "{\"isLagacyMode\":0,\"visualizationOnly\":0,\"DisplayFullRecords\":0}" } } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": "", "ReportID": "1787843241", "Reportname": "Orders by Customer", "ModuleName": "Test Load", "ModType": "anydb1003", "ReportType": "Sales_Orders", "folderid": 2, "OutputType": 1, "FieldList": [ { "fieldindex": 1, "DbParentTableAlias": "Sales_Orders", "DbTableAlias": "Sales_Orders", "DbFieldName": "order_id", "DisplayFieldName": "Order", "ReportFieldName": "Order", "RenamedField": "Order", "Fieldtype": "cha", "SearchCriteria": "", "strGroup": null, "Formula": "", "tbl5": "Y", "grouped": 0, "Criteria": [] } ] } ``` ### Update a report POST /api/Report/UpdateReport Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#update-report Update an existing report from a report object carrying its ReportID. The response echoes the fields supplied in the request, so send the complete object — most usefully the Report node from Get report metadata — rather than a partial one. Common use: Use it when you already hold a report object — from Get report metadata, for example — and want to change it without going through the create-or-update branch of Save. Body parameters: - sessionToken (string, required): A valid session token. - report (object, required): The report object to update, including its ReportID. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "report": { "ReportID": "1787843241", "Reportname": "Orders by Customer", "Description": "Updated via the API", "ModType": "anydb1003", "ReportType": "Sales_Orders", "folderid": 2, "FieldList": [ { "fieldindex": 1, "DbParentTableAlias": "Sales_Orders", "DbTableAlias": "Sales_Orders", "DbFieldName": "order_id", "DisplayFieldName": "Order", "ReportFieldName": "Order", "RenamedField": "Order", "Fieldtype": "cha", "SearchCriteria": "", "strGroup": "/Sales_Orders/Order", "Formula": "", "tbl5": "Y", "grouped": 0, "Criteria": [] } ], "linkreports": [], "Permissions": [] } } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": "", "ReportID": "1787843241", "Reportname": "Orders by Customer", "Description": "Updated via the API" } ``` ### Get a report definition POST /api/Report/GetReport Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-report Return a report's stored definition — fields, criteria, output settings, permissions and audit information. Connection fields such as DbLogin and DbPass are returned empty, and CreatedBy and LastModifiedBy are null on reports created before audit information was recorded. Common use: Use it to inspect or clone a report definition. To run a report, use Get report metadata instead, which returns the object Run a report requires. Body parameters: - sessionToken (string, required): A valid session token. - ReportId (string, required): The report's ID. - isbuilder (boolean, optional): True when loading the report for editing. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "ReportId": "1787843241", "isbuilder": false } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": "", "ReportID": "1787843241", "Reportname": "Orders by Customer", "ModuleName": "Test Load", "ModType": "anydb1003", "ReportType": "Sales_Orders", "ServerName": "db.internal.example.com", "DbLogin": "", "DbPass": "", "DbName": "", "DbDriver": "", "folderid": 2, "OutputType": 1, "OutputTypeClass": "datagrid", "FieldList": [ { "fieldindex": 1, "DbParentTableAlias": "Sales_Orders", "DbTableAlias": "Sales_Orders", "DbFieldName": "order_id", "DisplayFieldName": "Order", "ReportFieldName": "Order", "RenamedField": "Order", "Fieldtype": "cha", "SearchCriteria": "", "strGroup": "/Sales_Orders/Order", "Formula": "", "tbl5": "Y", "grouped": 0, "Criteria": [] } ], "Permissions": [], "CreatedBy": { "LoginName": "jsmith", "FullName": "Jane Smith" }, "LastModifiedBy": { "LoginName": "jsmith", "FullName": "Jane Smith" }, "CreatedDate": "2026-04-23T20:00:55Z", "LastModifiedDate": "2026-04-23T20:00:51Z" } ``` ### Get generated SQL POST /api/Report/GetSQL Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-sql Return the SQL a report object would generate, as a plain string. Prompt placeholders appear unresolved until prompts have been applied. Common use: Preview a report before saving or running it. Pair it with Compile criteria to see the statement with criteria compiled in. Body parameters: - sessionToken (string, required): A valid session token. - Reportobj (object, required): A report object — the Report node of a metadata response, or one you have assembled. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "Reportobj": { "ReportID": "1738259678", "Reportname": "Tickets by Customer", "ModuleName": "Ticket Data", "ErrorCode": 0, "ErrorMessage": "", "ModType": "anydb1009", "ReportType": "Service Data", "folderid": 2, "OutputType": 1, "FieldList": [ { "fieldindex": 1, "DbParentTableAlias": "Sales_Orders", "DbTableAlias": "Sales_Orders", "DbFieldName": "order_id", "DisplayFieldName": "Order", "ReportFieldName": "Order", "RenamedField": "Order", "Fieldtype": "cha", "SearchCriteria": "", "strGroup": "/Sales_Orders/Order", "Formula": "", "tbl5": "Y", "grouped": 0, "Criteria": [] } ], "Permissions": [], "linkreports": [], "AdHocFields": [] } } ``` Example response: ```json "Select \"Sales_Orders\".\"order_id\" AS \"Order\" From \"sales_orders\" \"Sales_Orders\" Where 1=1 And ((\"Sales_Orders\".\"customer_id\" = 1115))" ``` ### Compile criteria POST /api/Report/ReportProcUI Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#report-proc-ui Compile a report's structured criteria into the SQL fragments the engine uses, and return the report object with those fragments filled in. Common use: Run this before Get generated SQL when you have built criteria by hand, so the preview includes the WHERE clause. Body parameters: - sessionToken (string, required): A valid session token. - db_platform (string, required): Target platform, for example postgresql, oracle or mssql. - report (object, required): The report object whose criteria should be compiled. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "db_platform": "postgresql", "report": { "ReportID": "", "Reportname": "Preview", "ModType": "anydb1003", "ReportType": "Sales_Orders", "FieldList": [ { "fieldindex": 1, "DbParentTableAlias": "Sales_Orders", "DbTableAlias": "Sales_Orders", "DbFieldName": "order_id", "DisplayFieldName": "Order", "ReportFieldName": "Order", "RenamedField": "Order", "Fieldtype": "cha", "SearchCriteria": "", "strGroup": "/Sales_Orders/Order", "Formula": "", "tbl5": "Y", "grouped": 0, "Criteria": [ { "Index": 0, "Field": "Order", "Op": "inlist", "Value1": "D,O", "Value2": "", "Logical": "And", "cond": "is", "Nested": false } ] } ] } } ``` Example response: ```json { "ErrorCode": 0, "FieldList": [ { "fieldindex": 1, "DisplayFieldName": "Order", "SearchCriteria": "? In ('D','O')", "tbl10": "? In ('D','O')", "tbl11": "And" } ] } ``` ### List SQL functions POST /api/Report/GetSQLFunctions Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-sql-functions Return the SQL functions available for formula fields on a database platform. expression is the template, where ? stands for the field the formula is attached to. Common use: Populate a formula picker, and confirm which aggregate and conversion functions a platform supports before writing a formula into a field. Body parameters: - sessionToken (string, required): A valid session token. - db_plat (string, required): Database platform, for example postgresql, oracle or mssql. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "db_plat": "postgresql" } ``` Example response: ```json [ { "id": "4", "name": "SUM", "description": "Sum of numeric values in a group; NULLs ignored.", "expression": "SUM(?)", "type": "Aggregate", "dbplat": "4", "rdatatype": "num", "systemdefault": false, "error_message": null }, { "id": "36", "name": "UPPER", "description": "Convert character data to uppercase.", "expression": "UPPER(?)", "type": "String", "dbplat": "4", "rdatatype": "cha", "systemdefault": false, "error_message": null } ] ``` ### Get report metadata POST /api/Report/GetReportMetadataById Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-report-metadata Return the runtime metadata for a report: Report holds the definition and Prompts holds any prompts it defines. Prompts is null when the report has none. An unknown ID returns ErrorCode 586 with "Report does not exist." inside Report. Dashboards are not reports and return the same error. Common use: The first call in the run sequence. Pass the whole response to Run a report, or set prompt values first when Prompts is not empty. Body parameters: - sessionToken (string, required): A valid session token. - ReportID (string, required): The report's ID. - isTarget (boolean, optional): True when loading a drill-down target. - PreviousMetadata (object, optional): Prior metadata to carry forward. Send null. - Criteria (string, optional): Additional criteria to apply. Send null. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "ReportID": "1738259678", "isTarget": false, "PreviousMetadata": null, "Criteria": null } ``` Example response: ```json { "Report": { "ReportID": "1738259678", "Reportname": "Tickets by Customer", "ModuleName": "Ticket Data", "ErrorCode": 0, "ErrorMessage": "", "ModType": "anydb1009", "ReportType": "Service Data", "folderid": 2, "OutputType": 1, "FieldList": [ { "fieldindex": 1, "DbParentTableAlias": "Sales_Orders", "DbTableAlias": "Sales_Orders", "DbFieldName": "order_id", "DisplayFieldName": "Order", "ReportFieldName": "Order", "RenamedField": "Order", "Fieldtype": "cha", "SearchCriteria": "", "strGroup": "/Sales_Orders/Order", "Formula": "", "tbl5": "Y", "grouped": 0, "Criteria": [] } ], "Permissions": [], "linkreports": [], "AdHocFields": [] }, "Prompts": [ { "HasError": false, "ErrorCode": 0, "ErrorMessage": null, "PromptField": { "fieldindex": 3, "DbParentTableAlias": "Service Data", "DbTableAlias": "Service Data", "DbFieldName": "customer_id", "DisplayFieldName": "Customer ID", "ReportFieldName": "Customer ID", "Fieldtype": "num", "SearchCriteria": "? = Prompt for:Customer ID#:#num#:##:#", "strGroup": "/Service Data/Customer ID", "RenamedField": "Customer_ID", "Criteria": [ { "Index": 0, "Field": "Customer ID", "Op": "=", "Value1": "1115", "Value2": "", "Logical": "And", "cond": "is", "bskip": false, "bprompt": true, "bgetvalues": true, "sortorder": "None" } ] }, "isSkipable": false, "isBetween": false, "isInList": false, "isLike": false, "isGreaterThan": false, "isLessThan": false, "isSkipped": false, "LowValue": null, "HighValue": null } ] } ``` ### Get prompt values POST /api/Report/GetFieldValues Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-field-values Return the selectable values for a prompt as {key, val} pairs. For a date prompt the list contains relative expressions such as [Today] and [Last Month], which are intended for interface pickers; send an explicit date when setting the value through the API. Common use: Populate a dropdown in your own interface so users choose from real values. Pass the prompt object exactly as it came from Get report metadata. Body parameters: - sessionToken (string, required): A valid session token. - Reportobj (object, required): The metadata object the prompt belongs to. - Prompt (object, required): The prompt to list values for. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "Reportobj": { "Report": { "ReportID": "1738259678", "Reportname": "Tickets by Customer", "ModuleName": "Ticket Data", "ErrorCode": 0, "ErrorMessage": "", "ModType": "anydb1009", "ReportType": "Service Data", "folderid": 2, "OutputType": 1, "FieldList": [ { "fieldindex": 1, "DbParentTableAlias": "Sales_Orders", "DbTableAlias": "Sales_Orders", "DbFieldName": "order_id", "DisplayFieldName": "Order", "ReportFieldName": "Order", "RenamedField": "Order", "Fieldtype": "cha", "SearchCriteria": "", "strGroup": "/Sales_Orders/Order", "Formula": "", "tbl5": "Y", "grouped": 0, "Criteria": [] } ], "Permissions": [], "linkreports": [], "AdHocFields": [] }, "Prompts": [ { "HasError": false, "ErrorCode": 0, "ErrorMessage": null, "PromptField": { "fieldindex": 3, "DbParentTableAlias": "Service Data", "DbTableAlias": "Service Data", "DbFieldName": "customer_id", "DisplayFieldName": "Customer ID", "ReportFieldName": "Customer ID", "Fieldtype": "num", "SearchCriteria": "? = Prompt for:Customer ID#:#num#:##:#", "strGroup": "/Service Data/Customer ID", "RenamedField": "Customer_ID", "Criteria": [ { "Index": 0, "Field": "Customer ID", "Op": "=", "Value1": "1115", "Value2": "", "Logical": "And", "cond": "is", "bskip": false, "bprompt": true, "bgetvalues": true, "sortorder": "None" } ] }, "isSkipable": false, "isBetween": false, "isInList": false, "isLike": false, "isGreaterThan": false, "isLessThan": false, "isSkipped": false, "LowValue": null, "HighValue": null } ] }, "Prompt": { "HasError": false, "ErrorCode": 0, "ErrorMessage": null, "PromptField": { "fieldindex": 3, "DbParentTableAlias": "Service Data", "DbTableAlias": "Service Data", "DbFieldName": "customer_id", "DisplayFieldName": "Customer ID", "ReportFieldName": "Customer ID", "Fieldtype": "num", "SearchCriteria": "? = Prompt for:Customer ID#:#num#:##:#", "strGroup": "/Service Data/Customer ID", "RenamedField": "Customer_ID", "Criteria": [ { "Index": 0, "Field": "Customer ID", "Op": "=", "Value1": "1115", "Value2": "", "Logical": "And", "cond": "is", "bskip": false, "bprompt": true, "bgetvalues": true, "sortorder": "None" } ] }, "isSkipable": false, "isBetween": false, "isInList": false, "isLike": false, "isGreaterThan": false, "isLessThan": false, "isSkipped": false, "LowValue": null, "HighValue": null } } ``` Example response: ```json [ { "key": "1115", "val": "1115" }, { "key": "1006", "val": "1006" }, { "key": "1043", "val": "1043" } ] ``` ### Apply one prompt POST /api/Report/ReplacePrompt Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#replace-prompt Apply a value for a single prompt and return the updated metadata. Only the prompt you pass is compiled into the report's criteria, so for a report with several prompts call this once per prompt, passing the previous response back in as Reportobj each time. Set the value on LowValue, and HighValue as well when isBetween is true. The applied value appears in the returned Report, compiled into that field's criteria; the Prompts array is echoed back as it was supplied in Reportobj. Return the prompt object otherwise unchanged: it is matched to its field by table alias, field name, display name and field index. Common use: Use it when your interface applies prompts one at a time. To apply them all at once, use Apply all prompts instead. Body parameters: - sessionToken (string, required): A valid session token. - Reportobj (object, required): The metadata object, or the response from the previous call in the chain. - Prompt (object, required): One prompt with its value set. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "Reportobj": { "Report": { "ReportID": "1738259678", "Reportname": "Tickets by Customer", "ModuleName": "Ticket Data", "ErrorCode": 0, "ErrorMessage": "", "ModType": "anydb1009", "ReportType": "Service Data", "folderid": 2, "OutputType": 1, "FieldList": [ { "fieldindex": 1, "DbParentTableAlias": "Sales_Orders", "DbTableAlias": "Sales_Orders", "DbFieldName": "order_id", "DisplayFieldName": "Order", "ReportFieldName": "Order", "RenamedField": "Order", "Fieldtype": "cha", "SearchCriteria": "", "strGroup": "/Sales_Orders/Order", "Formula": "", "tbl5": "Y", "grouped": 0, "Criteria": [] } ], "Permissions": [], "linkreports": [], "AdHocFields": [] }, "Prompts": [ { "HasError": false, "ErrorCode": 0, "ErrorMessage": null, "PromptField": { "fieldindex": 3, "DbParentTableAlias": "Service Data", "DbTableAlias": "Service Data", "DbFieldName": "customer_id", "DisplayFieldName": "Customer ID", "ReportFieldName": "Customer ID", "Fieldtype": "num", "SearchCriteria": "? = Prompt for:Customer ID#:#num#:##:#", "strGroup": "/Service Data/Customer ID", "RenamedField": "Customer_ID", "Criteria": [ { "Index": 0, "Field": "Customer ID", "Op": "=", "Value1": "1115", "Value2": "", "Logical": "And", "cond": "is", "bskip": false, "bprompt": true, "bgetvalues": true, "sortorder": "None" } ] }, "isSkipable": false, "isBetween": false, "isInList": false, "isLike": false, "isGreaterThan": false, "isLessThan": false, "isSkipped": false, "LowValue": null, "HighValue": null } ] }, "Prompt": { "HasError": false, "ErrorCode": 0, "ErrorMessage": null, "PromptField": { "fieldindex": 3, "DbParentTableAlias": "Service Data", "DbTableAlias": "Service Data", "DbFieldName": "customer_id", "DisplayFieldName": "Customer ID", "ReportFieldName": "Customer ID", "Fieldtype": "num", "SearchCriteria": "? = Prompt for:Customer ID#:#num#:##:#", "strGroup": "/Service Data/Customer ID", "RenamedField": "Customer_ID", "Criteria": [ { "Index": 0, "Field": "Customer ID", "Op": "=", "Value1": "1115", "Value2": "", "Logical": "And", "cond": "is", "bskip": false, "bprompt": true, "bgetvalues": true, "sortorder": "None" } ] }, "isSkipable": false, "isBetween": false, "isInList": false, "isLike": false, "isGreaterThan": false, "isLessThan": false, "isSkipped": false, "LowValue": null, "HighValue": null } } ``` Example response: ```json { "Report": { "ReportID": "1738259678", "Reportname": "Tickets by Customer", "ModuleName": "Ticket Data", "ErrorCode": 0, "ErrorMessage": "", "ModType": "anydb1009", "ReportType": "Service Data", "folderid": 2, "OutputType": 1, "FieldList": [ { "fieldindex": 1, "DbParentTableAlias": "Sales_Orders", "DbTableAlias": "Sales_Orders", "DbFieldName": "order_id", "DisplayFieldName": "Order", "ReportFieldName": "Order", "RenamedField": "Order", "Fieldtype": "cha", "SearchCriteria": "", "strGroup": "/Sales_Orders/Order", "Formula": "", "tbl5": "Y", "grouped": 0, "Criteria": [] } ], "Permissions": [], "linkreports": [], "AdHocFields": [] }, "Prompts": [ { "HasError": false, "ErrorCode": 0, "ErrorMessage": null, "PromptField": { "fieldindex": 3, "DbParentTableAlias": "Service Data", "DbTableAlias": "Service Data", "DbFieldName": "customer_id", "DisplayFieldName": "Customer ID", "ReportFieldName": "Customer ID", "Fieldtype": "num", "SearchCriteria": "? = Prompt for:Customer ID#:#num#:##:#", "strGroup": "/Service Data/Customer ID", "RenamedField": "Customer_ID", "Criteria": [ { "Index": 0, "Field": "Customer ID", "Op": "=", "Value1": "1115", "Value2": "", "Logical": "And", "cond": "is", "bskip": false, "bprompt": true, "bgetvalues": true, "sortorder": "None" } ] }, "isSkipable": false, "isBetween": false, "isInList": false, "isLike": false, "isGreaterThan": false, "isLessThan": false, "isSkipped": false, "LowValue": "1115", "HighValue": "" } ] } ``` ### Apply all prompts POST /api/Report/ReplacePromptCollection Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#replace-prompt-collection Apply values for every prompt on a report in one call and return the metadata with those values compiled into the report's criteria. Set each value on the prompt's LowValue, and HighValue as well when isBetween is true. Send the Prompts array in the same order and length as the metadata returned it: values are matched to prompts by position. Common use: The recommended way to run a prompted report. Take the metadata, set LowValue and HighValue on each prompt, call this once, then pass the result to Run a report. Body parameters: - Reportobj (object, required): The metadata object from Get report metadata. - Prompts (array, required): The prompts with values set, in the order metadata returned them. Example request body: ```json { "Reportobj": { "Report": { "ReportID": "1738259678", "Reportname": "Tickets by Customer", "ModuleName": "Ticket Data", "ErrorCode": 0, "ErrorMessage": "", "ModType": "anydb1009", "ReportType": "Service Data", "folderid": 2, "OutputType": 1, "FieldList": [ { "fieldindex": 1, "DbParentTableAlias": "Sales_Orders", "DbTableAlias": "Sales_Orders", "DbFieldName": "order_id", "DisplayFieldName": "Order", "ReportFieldName": "Order", "RenamedField": "Order", "Fieldtype": "cha", "SearchCriteria": "", "strGroup": "/Sales_Orders/Order", "Formula": "", "tbl5": "Y", "grouped": 0, "Criteria": [] } ], "Permissions": [], "linkreports": [], "AdHocFields": [] }, "Prompts": [ { "HasError": false, "ErrorCode": 0, "ErrorMessage": null, "PromptField": { "fieldindex": 3, "DbParentTableAlias": "Service Data", "DbTableAlias": "Service Data", "DbFieldName": "customer_id", "DisplayFieldName": "Customer ID", "ReportFieldName": "Customer ID", "Fieldtype": "num", "SearchCriteria": "? = Prompt for:Customer ID#:#num#:##:#", "strGroup": "/Service Data/Customer ID", "RenamedField": "Customer_ID", "Criteria": [ { "Index": 0, "Field": "Customer ID", "Op": "=", "Value1": "1115", "Value2": "", "Logical": "And", "cond": "is", "bskip": false, "bprompt": true, "bgetvalues": true, "sortorder": "None" } ] }, "isSkipable": false, "isBetween": false, "isInList": false, "isLike": false, "isGreaterThan": false, "isLessThan": false, "isSkipped": false, "LowValue": null, "HighValue": null } ] }, "Prompts": [ { "HasError": false, "ErrorCode": 0, "ErrorMessage": null, "PromptField": { "fieldindex": 3, "DbParentTableAlias": "Service Data", "DbTableAlias": "Service Data", "DbFieldName": "customer_id", "DisplayFieldName": "Customer ID", "ReportFieldName": "Customer ID", "Fieldtype": "num", "SearchCriteria": "? = Prompt for:Customer ID#:#num#:##:#", "strGroup": "/Service Data/Customer ID", "RenamedField": "Customer_ID", "Criteria": [ { "Index": 0, "Field": "Customer ID", "Op": "=", "Value1": "1115", "Value2": "", "Logical": "And", "cond": "is", "bskip": false, "bprompt": true, "bgetvalues": true, "sortorder": "None" } ] }, "isSkipable": false, "isBetween": false, "isInList": false, "isLike": false, "isGreaterThan": false, "isLessThan": false, "isSkipped": false, "LowValue": "1115", "HighValue": "" } ] } ``` Example response: ```json { "Report": { "ReportID": "1738259678", "Reportname": "Tickets by Customer", "ModuleName": "Ticket Data", "ErrorCode": 0, "ErrorMessage": "", "ModType": "anydb1009", "ReportType": "Service Data", "folderid": 2, "OutputType": 1, "FieldList": [ { "fieldindex": 1, "DbParentTableAlias": "Sales_Orders", "DbTableAlias": "Sales_Orders", "DbFieldName": "order_id", "DisplayFieldName": "Order", "ReportFieldName": "Order", "RenamedField": "Order", "Fieldtype": "cha", "SearchCriteria": "", "strGroup": "/Sales_Orders/Order", "Formula": "", "tbl5": "Y", "grouped": 0, "Criteria": [] } ], "Permissions": [], "linkreports": [], "AdHocFields": [] }, "Prompts": [ { "HasError": false, "ErrorCode": 0, "ErrorMessage": null, "PromptField": { "fieldindex": 3, "DbParentTableAlias": "Service Data", "DbTableAlias": "Service Data", "DbFieldName": "customer_id", "DisplayFieldName": "Customer ID", "ReportFieldName": "Customer ID", "Fieldtype": "num", "SearchCriteria": "? = Prompt for:Customer ID#:#num#:##:#", "strGroup": "/Service Data/Customer ID", "RenamedField": "Customer_ID", "Criteria": [ { "Index": 0, "Field": "Customer ID", "Op": "=", "Value1": "1115", "Value2": "", "Logical": "And", "cond": "is", "bskip": false, "bprompt": true, "bgetvalues": true, "sortorder": "None" } ] }, "isSkipable": false, "isBetween": false, "isInList": false, "isLike": false, "isGreaterThan": false, "isLessThan": false, "isSkipped": false, "LowValue": "1115", "HighValue": "" } ] } ``` ### Run a report POST /api/Report/GetReportData Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-report-data Execute a report and return its rows. Reportobj must be the complete metadata object from Get report metadata, with prompts applied when the report has any. Rows are in Data, one object per row keyed by column, and Columns describes each column. Check HasError rather than ErrorCode on this endpoint: a failed execution returns HasError: true with the message in ErrorMessage while ErrorCode stays 0. The response also carries interface bindings such as jqxColumns, and etime, the execution time in milliseconds. Common use: The final step of the report workflow. Detail reports can return very large payloads — there is no paging, so use a report with a TopN limit or an aggregate when you only need a summary. Set supressprompts true to run a prompted report without supplying values. Body parameters: - sessionToken (string, required): A valid session token. - Reportobj (object, required): The prepared metadata object. - IsDrillDown (boolean, optional): Whether this is a drill-down run. Defaults to false. - DrillDownCriteria (object, optional): Criteria for a drill-down; null otherwise. - TargetReportobj (object, optional): Target report for a drill-down; null otherwise. - supressprompts (boolean, optional): Run without applying prompts, returning the unfiltered result. - cacheok (boolean, optional): Allow a cached result to be returned. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "IsDrillDown": false, "DrillDownCriteria": null, "Reportobj": { "Report": { "ReportID": "1738259678", "Reportname": "Tickets by Customer", "ModuleName": "Ticket Data", "ErrorCode": 0, "ErrorMessage": "", "ModType": "anydb1009", "ReportType": "Service Data", "folderid": 2, "OutputType": 1, "FieldList": [ { "fieldindex": 1, "DbParentTableAlias": "Sales_Orders", "DbTableAlias": "Sales_Orders", "DbFieldName": "order_id", "DisplayFieldName": "Order", "ReportFieldName": "Order", "RenamedField": "Order", "Fieldtype": "cha", "SearchCriteria": "", "strGroup": "/Sales_Orders/Order", "Formula": "", "tbl5": "Y", "grouped": 0, "Criteria": [] } ], "Permissions": [], "linkreports": [], "AdHocFields": [] }, "Prompts": [ { "HasError": false, "ErrorCode": 0, "ErrorMessage": null, "PromptField": { "fieldindex": 3, "DbParentTableAlias": "Service Data", "DbTableAlias": "Service Data", "DbFieldName": "customer_id", "DisplayFieldName": "Customer ID", "ReportFieldName": "Customer ID", "Fieldtype": "num", "SearchCriteria": "? = Prompt for:Customer ID#:#num#:##:#", "strGroup": "/Service Data/Customer ID", "RenamedField": "Customer_ID", "Criteria": [ { "Index": 0, "Field": "Customer ID", "Op": "=", "Value1": "1115", "Value2": "", "Logical": "And", "cond": "is", "bskip": false, "bprompt": true, "bgetvalues": true, "sortorder": "None" } ] }, "isSkipable": false, "isBetween": false, "isInList": false, "isLike": false, "isGreaterThan": false, "isLessThan": false, "isSkipped": false, "LowValue": null, "HighValue": null } ] }, "TargetReportobj": null } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": "", "HasError": false, "ReportID": "1738259678", "OutputType": 1, "Columns": [ { "headerText": "Customer", "key": "Customer_ID", "dataType": "number", "width": 0, "dataFormatString": null, "yurbitype": "num", "columngroup": "" }, { "headerText": "Tickets", "key": "Ticket_ID", "dataType": "number", "width": 0, "dataFormatString": null, "yurbitype": "num", "columngroup": "" } ], "Data": [ { "Customer_ID": 1115, "Ticket_ID": 10 } ], "GroupMetadata": [], "groups": [], "IsFromCache": false, "IsTopLevel": true, "ContainsDrilldown": false, "etime": "79", "dbtime": null } ``` ### List output types POST /api/Report/GetOutputTypes Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-output-types Return the output types a report can use. id is the value carried by a report's OutputType and by itemtype in library listings; uiclass is the matching interface class. Common use: Use it to label report types in your own interface, and to choose an OutputType when creating a report. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json [ { "id": 1, "name": "DataGrid", "uiclass": "datagrid" }, { "id": 2, "name": "Chart", "uiclass": "chart" }, { "id": 3, "name": "KPI Text", "uiclass": "kpi_metric" }, { "id": 4, "name": "KPI Gauge", "uiclass": "kpi_gauge" }, { "id": 6, "name": "Pie Chart", "uiclass": "pie-chart" }, { "id": 7, "name": "Combo Chart", "uiclass": "combochart" }, { "id": 8, "name": "Pivot Grid", "uiclass": "pivotgrid" }, { "id": 9, "name": "Tree Map", "uiclass": "treemap" }, { "id": 10, "name": "Vector Map", "uiclass": "vectormap" }, { "id": 11, "name": "Skyline", "uiclass": "skyline" }, { "id": 12, "name": "Aggregate Grid", "uiclass": "datagrid2" }, { "id": 13, "name": "Adv Pivot Grid", "uiclass": "pivotgrid2" }, { "id": 14, "name": "Chartv2", "uiclass": "chart2" } ] ``` --------------------------------------------------------------- ## Email (SMTP) --------------------------------------------------------------- ### Get SMTP configuration POST /api/SMTP/GetSMTP Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-smtp Return the instance's outgoing mail configuration. SMTPPassword is always returned empty. The settings are nested inside a realm; SMTPRealm.SMTPSetting is null on the master realm. Common use: Confirm mail is configured before relying on scheduled delivery, and fetch the object required by Save SMTP configuration. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": null, "SMTPId": "177341830687", "SMTPHost": "smtp.example.com", "SMTPPort": "587", "SMTPFromAddress": "reports@example.com", "SMTPRequiredSecurity": "True", "SMTPUserName": "reports@example.com", "SMTPPassword": "", "SMTPCreated": "03/13/2026 16:11:46", "SMTPModified": "03/13/2026 16:11:46", "SMTPEnableSSL": "True", "SMTPRealm": { "ErrorCode": 0, "ErrorMessage": "", "RealmId": "1", "RealmName": "MASTER", "RealmDescription": "This is a default realm. Cannot be edited.", "RealmCreated": "2009-06-29T00:00:00", "RealmModified": "2009-06-29T00:00:00", "ProviderList": [], "SMTPSetting": null } } ``` ### Save SMTP configuration POST /api/SMTP/SaveSMTP Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#save-smtp Create or update the outgoing mail configuration. Read the current settings with Get SMTP configuration, change what you need, and send the whole object back. Supply SMTPPassword whenever SMTPRequiredSecurity is true, since it is never returned by a read. Common use: Point a new instance at your mail relay as part of an automated deployment. Body parameters: - sessionToken (string, required): A valid session token. - smtp (object, required): The SMTP configuration object. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "smtp": { "SMTPId": "177341830687", "SMTPHost": "smtp.example.com", "SMTPPort": "587", "SMTPFromAddress": "reports@example.com", "SMTPRequiredSecurity": "True", "SMTPUserName": "reports@example.com", "SMTPPassword": "YOUR_SMTP_PASSWORD", "SMTPEnableSSL": "True" } } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": null, "SMTPId": "177341830687", "SMTPHost": "smtp.example.com", "SMTPPort": "587", "SMTPFromAddress": "reports@example.com", "SMTPRequiredSecurity": "True", "SMTPUserName": "reports@example.com", "SMTPPassword": "", "SMTPCreated": "03/13/2026 16:11:46", "SMTPModified": "03/13/2026 16:11:46", "SMTPEnableSSL": "True", "SMTPRealm": { "ErrorCode": 0, "ErrorMessage": "", "RealmId": "1", "RealmName": "MASTER", "RealmDescription": "This is a default realm. Cannot be edited.", "RealmCreated": "2009-06-29T00:00:00", "RealmModified": "2009-06-29T00:00:00", "ProviderList": [], "SMTPSetting": null } } ``` ### Delete SMTP configuration POST /api/SMTP/DeleteSMTP Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#delete-smtp Remove the outgoing mail configuration. Takes the whole configuration object under smtp, so read it first with Get SMTP configuration. Common use: Clear mail settings when decommissioning an instance. Scheduled delivery stops working once the configuration is removed. Body parameters: - sessionToken (string, required): A valid session token. - smtp (object, required): The SMTP configuration object to remove. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "smtp": { "SMTPId": "177341830687" } } ``` Example response: ```json { "ErrorCode": 0, "ErrorMessage": null, "SMTPId": null, "SMTPHost": null, "SMTPPort": null, "SMTPFromAddress": null, "SMTPRequiredSecurity": null, "SMTPUserName": null, "SMTPPassword": null, "SMTPRealm": null, "SMTPEnableSSL": null } ``` --------------------------------------------------------------- ## Instance Settings --------------------------------------------------------------- ### Get instance settings POST /api/AppSettings/GetAppSettings Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-app-settings Return the instance's configuration: session timeout, record limits, tenant mode, single sign-on, two-factor settings and scheduler concurrency. Boolean values are returned as the strings "True" and "False". Common use: Read SESSION_TIMEOUT to size your token cache, MaxRecords to understand result limits, and TENANT_MODE_ENABLED, SSOEnabled and SSOHeader to verify a deployment without opening the interface. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json { "DebugLevel": 0, "SESSION_TIMEOUT": 20, "PROMPT_VALUES_LIMIT": 10000, "SSOEnabled": "True", "SSOHeader": "ssoheadertoken", "IIS_PASSTHROUGH_ENABLED": "False", "TENANT_MODE_ENABLED": "False", "USERTZ_MODE_ENABLED": "False", "GUEST_FASTCACHE": "False", "FastCacheMin": 30, "duo_clientid": "", "duo_clientsecret": "", "duo_apihost": "", "duo_redirect": "", "duo_enabled": "False", "bulkemail_enabled": "False", "sqlnolocks": "False", "SchedulerMode": 8, "MaxRecords": 500000, "Productname": "Yurbi", "enableallusersgrp": "False", "enforcestrongpassword": "False" } ``` ### Save instance settings POST /api/AppSettings/SaveAppSettings Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#save-app-settings Update instance configuration. Read the current settings first, change what you need, and send the whole object back — omitted values are not preserved. Common use: Apply a standard configuration when provisioning a new instance, for example enabling tenant mode and setting the session timeout. Body parameters: - sessionToken (string, required): A valid session token. - appsettings (object, required): The complete settings object. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "appsettings": { "DebugLevel": 0, "SESSION_TIMEOUT": 20, "PROMPT_VALUES_LIMIT": 10000, "SSOEnabled": "True", "SSOHeader": "ssoheadertoken", "IIS_PASSTHROUGH_ENABLED": "False", "TENANT_MODE_ENABLED": "False", "USERTZ_MODE_ENABLED": "False", "GUEST_FASTCACHE": "False", "FastCacheMin": 30, "duo_clientid": "", "duo_clientsecret": "", "duo_apihost": "", "duo_redirect": "", "duo_enabled": "False", "bulkemail_enabled": "False", "sqlnolocks": "False", "SchedulerMode": 8, "MaxRecords": 500000, "Productname": "Yurbi", "enableallusersgrp": "False", "enforcestrongpassword": "False" } } ``` Example response: ```json { "DebugLevel": 0, "SESSION_TIMEOUT": 20, "PROMPT_VALUES_LIMIT": 10000, "SSOEnabled": "True", "SSOHeader": "ssoheadertoken", "IIS_PASSTHROUGH_ENABLED": "False", "TENANT_MODE_ENABLED": "False", "USERTZ_MODE_ENABLED": "False", "GUEST_FASTCACHE": "False", "FastCacheMin": 30, "duo_clientid": "", "duo_clientsecret": "", "duo_apihost": "", "duo_redirect": "", "duo_enabled": "False", "bulkemail_enabled": "False", "sqlnolocks": "False", "SchedulerMode": 8, "MaxRecords": 500000, "Productname": "Yurbi", "enableallusersgrp": "False", "enforcestrongpassword": "False" } ``` ### Get audit settings POST /api/Audit/GetAuditTypes Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#get-audit-types Return every auditable event with whether it is recorded and how long it is retained. recorded is -1 when the event is captured and 0 when it is not; retention is in days. Common use: Confirm which events an instance captures before relying on the audit trail for compliance reporting. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json [ { "ID": 1, "type": 0, "symbol": "Login Success", "recorded": -1, "retention": 365, "options": "" }, { "ID": 2, "type": 1, "symbol": "Login Failure", "recorded": -1, "retention": 365, "options": "" }, { "ID": 7, "type": 6, "symbol": "Report Execution", "recorded": -1, "retention": 365, "options": "" }, { "ID": 16, "type": 15, "symbol": "Report Execution SQL", "recorded": 0, "retention": 365, "options": "" } ] ``` ### Save audit settings POST /api/Audit/SaveAuditTypes Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#save-audit-types Update which events are audited and how long each is retained. Send the full list as returned by Get audit settings, with recorded and retention adjusted. Common use: Apply a standard audit policy across instances, or enable SQL capture temporarily while diagnosing a report. Body parameters: - sessionToken (string, required): A valid session token. - AuditTypeList (array, required): The complete list of audit types with their settings. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN", "AuditTypeList": [ { "ID": 1, "type": 0, "symbol": "Login Success", "recorded": -1, "retention": 365, "options": "" }, { "ID": 2, "type": 1, "symbol": "Login Failure", "recorded": -1, "retention": 365, "options": "" }, { "ID": 7, "type": 6, "symbol": "Report Execution", "recorded": -1, "retention": 365, "options": "" }, { "ID": 16, "type": 15, "symbol": "Report Execution SQL", "recorded": 0, "retention": 365, "options": "" } ] } ``` Example response: ```json [ { "ID": 1, "type": 0, "symbol": "Login Success", "recorded": -1, "retention": 365, "options": "" }, { "ID": 2, "type": 1, "symbol": "Login Failure", "recorded": -1, "retention": 365, "options": "" }, { "ID": 7, "type": 6, "symbol": "Report Execution", "recorded": -1, "retention": 365, "options": "" }, { "ID": 16, "type": 15, "symbol": "Report Execution SQL", "recorded": 0, "retention": 365, "options": "" } ] ``` --------------------------------------------------------------- ## Licensing --------------------------------------------------------------- ### Refresh licences POST /api/LicenseManager/RefreshInstalledLicenses Auth: session token required in the request body Reference: https://developers.yurbi.com/reference/#refresh-licenses Re-read installed licence keys from the licence service and update the instance's entitlements. Common use: Call it after purchasing additional seats or renewing, so the instance picks up the change without a restart. Confirm the result with List applications, which reports licensed and consumed quantities per module. Body parameters: - sessionToken (string, required): A valid session token. Example request body: ```json { "sessionToken": "YOUR_SESSION_TOKEN" } ``` Example response: ```json { "returncode": 0, "message": "" } ``` ### Get installation ID POST /api/LicenseManager/GetInstallationID Auth: none (this call issues the token) Reference: https://developers.yurbi.com/reference/#get-installation-id Return the instance's installation identifier as a plain string, formatted as six groups of four digits. This endpoint does not require a session token — it is used during activation, before anyone can sign in. Common use: Identify an instance during licence activation, and record it alongside your own deployment inventory. Body parameters: Example request body: ```json {} ``` Example response: ```json "4446-4836-3034-3631-4452-3666" ```