Skip to content

My Data — data sources

External data the platform can read on the user's behalf: SharePoint / OneDrive files (Microsoft Graph), SQL databases (stored credentials and the SQL chat), reusable data sources for apps and workflows, live camera/JSON feeds for dashboards, and prompt templates.

Endpoints

MethodPathPurpose
GET/ms-graph/graph/auth-url/{domain}/Start connecting SharePoint/OneDrive
POST/ms-graph/graph/token-exchange/Finish connecting SharePoint/OneDrive
POST/ms-graph/graph/refresh-token/Refresh Graph tokens
POST/ms-graph/graph/disconnect/Disconnect SharePoint/OneDrive
POST/ms-graph/graph/list-files/Pull the drive listing from Microsoft
GET/ms-graph/graph/cached-list/Browse the cached drive listing
POST/ms-graph/graph/batch-download-files/Import drive files into My Data
POST/ms-graph/graph/download-file/Get a temporary download URL for a drive item
POST/ms-graph/graph/forget-file/Remove an imported drive file
POST/ms-graph/graph/drive-item-permissions/Permissions of a drive item
POST/ms-graph/graph/organization-credentials/Store an organisation's Microsoft app for Graph
GET/sql-search/credentials/List my SQL connections
POST/sql-search/credentials/Save a SQL connection
GET/sql-search/credentials/{id}/Get a SQL connection
PUT/sql-search/credentials/{id}/Update a SQL connection
DELETE/sql-search/credentials/{id}/Delete a SQL connection
POST/sql-search/overview/Sample rows from every table
POST/sql-search/chat/Ask a question of a SQL database
GET/sql-search/My SQL chat history
POST/sql-search/check-connection/Test a saved SQL connection
POST/sql-search/fetch-files/Scan a SQL table for document records
GET/sql-search/files/File records found in a SQL table
POST/sql-search/download-files/Import file records as documents
GET/sql-search/files/content/{file_id}/Raw content of a file record
DELETE/sql-search/files/{file_id}/Delete an imported file record
GET/data-sources/List data sources
POST/data-sources/Create a data source
GET/data-sources/{id}/Get a data source
PUT/data-sources/{id}/Update a data source
DELETE/data-sources/{id}/Delete a data source
POST/data-sources/{id}/test/Test the connection
GET/data-sources/{id}/tables/Tables exposed by the connection
GET/data-sources/{id}/columns/Columns of a table
POST/data-sources/{id}/preview/Preview rows
GET/live-feeds/sources/List live feeds
POST/live-feeds/sources/Create a live feed
GET/live-feeds/sources/{id}/Get a live feed
PUT/live-feeds/sources/{id}/Update a live feed
DELETE/live-feeds/sources/{id}/Delete a live feed
POST/live-feeds/sources/{id}/test/Test a live feed
GET/live-feeds/sources/{id}/proxy/Fetch JSON through a live feed
POST/live-feeds/sources/{id}/stream-url/Get a signed URL for a camera stream
GET/live-feeds/sources/{id}/stream/Relay a camera stream
GET/templates/List prompt templates
POST/templates/Create a prompt template
GET/templates/{id}/Get a template
PUT/templates/{id}/Update a template
DELETE/templates/{id}/Delete a template

GET /ms-graph/graph/auth-url/{domain}/

Start connecting SharePoint/OneDrive

Builds the Microsoft consent URL for the Graph scopes the importer needs (Files.Read, Sites.ReadWrite.All, mail scopes). Credentials come from the organisation matching domain, or — for users with a personal organisation — from their own metadata. After consent Microsoft redirects to redirect_uri with a code; exchange it with token-exchange/.

Auth: Session token · In the app: My Data → SharePoint → Connect

Path parameters

FieldTypeRequiredDescription
domainstringyes

Query parameters

FieldTypeRequiredDescription
redirect_uristring (uri)yesMust be registered on the Azure application.
force_accountbooleannoForce the account picker.
login_hintstringnoPre-select this Microsoft account.

Response 200 — Consent URL.

FieldTypeDescription
auth_urlstring (uri)

Response 404 — No Microsoft credentials for the domain / account.

json
{
  "detail": "Organization not found or Microsoft credentials not configured.",
  "domain": "acme.com"
}

Example

bash
curl -X GET "https://api.example.com/ms-graph/graph/auth-url/acme.com/?redirect_uri=https%3A%2F%2Fapp.example.com%2Fconnections-callback" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /ms-graph/graph/token-exchange/

Finish connecting SharePoint/OneDrive

Exchanges the code for Graph tokens, stores them on the user (encrypted) and returns them so the browser can call the drive endpoints. Switching to a different Microsoft account clears the cached drive listing.

Auth: Session token · In the app: /connections-callback page

Request body (application/json)

FieldTypeRequiredDescription
codestringyes
domainstringyes
redirect_uristring (uri)yesThe same value used in auth-url.

Response 200 — Tokens.

FieldTypeDescription
access_tokenstring
refresh_tokenstring
expires_ininteger
scopestring
microsoft_emailstring, nullable

Response 400 — Missing code/domain, or Microsoft rejected the exchange.

json
{
  "detail": "Authentication credentials were not provided."
}

Response 404 — No Microsoft credentials for the domain.

json
{
  "detail": "Authentication credentials were not provided."
}

Example

bash
curl -X POST "https://api.example.com/ms-graph/graph/token-exchange/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /ms-graph/graph/refresh-token/

Refresh Graph tokens

Auth: Session token · In the app: Automatic when the Graph token expires

Request body (application/json)

FieldTypeRequiredDescription
refresh_tokenstringyes
domainstringyes

Response 200 — New tokens.

FieldTypeDescription
access_tokenstring
refresh_tokenstring
expires_ininteger

Response 400 — Refresh failed.

json
{
  "error": "path is required"
}

Example

bash
curl -X POST "https://api.example.com/ms-graph/graph/refresh-token/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /ms-graph/graph/disconnect/

Disconnect SharePoint/OneDrive

Forgets the stored Graph tokens and the cached drive listing. Imported documents are kept.

Auth: Session token · In the app: My Data → SharePoint → Disconnect

Response 200 — Disconnected.

FieldTypeDescription
detailstringHuman-readable explanation.
codestringMachine-readable error code (present on some responses).
json
{
  "detail": "Microsoft cloud disconnected."
}

Example

bash
curl -X POST "https://api.example.com/ms-graph/graph/disconnect/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /ms-graph/graph/list-files/

Pull the drive listing from Microsoft

Walks the whole OneDrive recursively, caches every item, and returns the tree. Slow on large drives; the app calls it once per connect/refresh and browses the cache afterwards.

Auth: Session token · In the app: My Data → SharePoint → Refresh

Request body (application/json)

FieldTypeRequiredDescription
access_tokenstringyesGraph access token.

Response 200 — Tree of items (children on folders) and the total size.

FieldTypeDescription
drive_contentsobject[]
total_size_mbnumber

Response 400access_token missing.

json
{
  "detail": "Authentication credentials were not provided."
}

Response 500 — Graph error (body carries the Graph response).

json
{
  "error": "path is required"
}

Example

bash
curl -X POST "https://api.example.com/ms-graph/graph/list-files/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

GET /ms-graph/graph/cached-list/

Browse the cached drive listing

Auth: Session token · In the app: My Data → SharePoint tab

Response 200 — Flat list of cached items with import state.

FieldTypeDescription
drive_contentsobject[]
drive_contents[].idstringGraph drive-item id.
drive_contents[].namestring
drive_contents[].typestring ("file", "folder")
drive_contents[].file_extensionstring, nullableMIME type (Graph's file.mimeType); null for folders.
drive_contents[].parent_referencestringGraph parent path.
drive_contents[].size_bytesinteger
drive_contents[].size_mbnumber
drive_contents[].downloadedboolean
drive_contents[].embeddedboolean
drive_contents[].document_uidstring, nullableThe semantic-search document created from this item, if imported.
drive_contents[].created_atstring (date-time)
drive_contents[].last_modified_atstring (date-time)

Example

bash
curl -X GET "https://api.example.com/ms-graph/graph/cached-list/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /ms-graph/graph/batch-download-files/

Import drive files into My Data

Downloads the selected items and indexes them as semantic-search documents in the background. Items already imported are reported in saved_files; items another user is still processing in in_progress.

Auth: Session token · In the app: My Data → SharePoint → Import selected

Request body (application/json)

FieldTypeRequiredDescription
access_tokenstringyes
file_idsstring[]yes

Response 200 — Nothing new to import.

Response 202 — Import queued.

FieldTypeDescription
saved_filesstring[]Media paths already imported.
in_progressstring[]
batch_idstring, nullablePoll with semantic-search/upload/batch/{batch_id}/status/.
queuedinteger

Response 400 — Missing fields.

json
{
  "detail": "Authentication credentials were not provided."
}

Example

bash
curl -X POST "https://api.example.com/ms-graph/graph/batch-download-files/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /ms-graph/graph/download-file/

Get a temporary download URL for a drive item

Auth: Session token

Request body (application/json)

FieldTypeRequiredDescription
access_tokenstringyes
file_idstringyes

Response 200 — Pre-authenticated Microsoft download URL (short-lived).

FieldTypeDescription
download_urlstring (uri)

Response 400 — Missing fields, or Graph returned no download URL.

json
{
  "detail": "Authentication credentials were not provided."
}

Example

bash
curl -X POST "https://api.example.com/ms-graph/graph/download-file/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /ms-graph/graph/forget-file/

Remove an imported drive file

If you own the imported document its index, file and row are removed; if it was shared with you, you are detached from it. The cached item is marked not imported.

Auth: Session token · In the app: My Data → SharePoint → Remove from My Data

Request body (application/json)

FieldTypeRequiredDescription
file_idstringyes

Response 200 — Forgotten.

FieldTypeDescription
detailstring
file_idstring

Example

bash
curl -X POST "https://api.example.com/ms-graph/graph/forget-file/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /ms-graph/graph/drive-item-permissions/

Permissions of a drive item

Proxies Graph's permissions collection for one item.

Auth: Session token

Request body (application/json)

FieldTypeRequiredDescription
access_tokenstringyes
drive_item_idstringyes

Response 200 — Graph permissions response.

Example

bash
curl -X POST "https://api.example.com/ms-graph/graph/drive-item-permissions/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /ms-graph/graph/organization-credentials/

Store an organisation's Microsoft app for Graph

Creates or updates the organisation's Azure application id and secret used for SharePoint access (and Microsoft SSO).

Auth: Session token · In the app: My Data → SharePoint → configure organisation (admins)

Request body (application/json)

FieldTypeRequiredDescription
domainstringyes
application_idstringyes
secret_keystringyes
organization_namestringno

Response 200 — Updated.

FieldTypeDescription
detailstring
organizationobject
organization.idinteger
organization.namestring
organization.domainstring

Response 201 — Created.

Response 400 — Missing fields.

json
{
  "detail": "Authentication credentials were not provided."
}

Example

bash
curl -X POST "https://api.example.com/ms-graph/graph/organization-credentials/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

GET /sql-search/credentials/

List my SQL connections

Auth: Session token · In the app: Database search page → connections

Response 200 — Connections.

Array of:

FieldTypeDescription
idinteger
connectionstring ("mysql", "mariadb", "mssql")Database engine.
serverstringHost (and port) of the database server.
usernamestring
passwordstringStored and echoed back — treat this endpoint as sensitive.
databasestring
created_atstring (date-time)

Example

bash
curl -X GET "https://api.example.com/sql-search/credentials/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /sql-search/credentials/

Save a SQL connection

Auth: Session token

Request body (application/json)

FieldTypeRequiredDescription
connectionstring ("mysql", "mariadb", "mssql")yes
serverstringyes
usernamestringyes
passwordstringyes
databasestringyes
json
{
  "connection": "mysql",
  "server": "db.internal:3306",
  "username": "reporting",
  "password": "s3cret",
  "database": "erp"
}

Response 200 — Stored ("stored").

Response 400 — Validation errors.

json
{
  "username": [
    "A user with that username already exists."
  ]
}

Example

bash
curl -X POST "https://api.example.com/sql-search/credentials/" \
  -H "Authorization: Token $FINBLADE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"connection":"mysql","server":"db.internal:3306","username":"reporting","password":"s3cret","database":"erp"}'

GET /sql-search/credentials/{id}/

Get a SQL connection

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Response 200 — The connection.

FieldTypeDescription
idinteger
connectionstring ("mysql", "mariadb", "mssql")Database engine.
serverstringHost (and port) of the database server.
usernamestring
passwordstringStored and echoed back — treat this endpoint as sensitive.
databasestring
created_atstring (date-time)
json
{
  "id": 3,
  "connection": "mysql",
  "server": "db.internal:3306",
  "username": "reporting",
  "password": "********",
  "database": "erp",
  "created_at": "2026-05-11T08:00:00Z"
}

Response 404 — Not yours.

Example

bash
curl -X GET "https://api.example.com/sql-search/credentials/<id>/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

PUT /sql-search/credentials/{id}/

Update a SQL connection

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Request body (application/json)

FieldTypeRequiredDescription
idintegerno
connectionstring ("mysql", "mariadb", "mssql")noDatabase engine.
serverstringnoHost (and port) of the database server.
usernamestringno
passwordstringnoStored and echoed back — treat this endpoint as sensitive.
databasestringno
created_atstring (date-time)no
json
{
  "id": 3,
  "connection": "mysql",
  "server": "db.internal:3306",
  "username": "reporting",
  "password": "********",
  "database": "erp",
  "created_at": "2026-05-11T08:00:00Z"
}

Response 200 — Updated.

FieldTypeDescription
idinteger
connectionstring ("mysql", "mariadb", "mssql")Database engine.
serverstringHost (and port) of the database server.
usernamestring
passwordstringStored and echoed back — treat this endpoint as sensitive.
databasestring
created_atstring (date-time)
json
{
  "id": 3,
  "connection": "mysql",
  "server": "db.internal:3306",
  "username": "reporting",
  "password": "********",
  "database": "erp",
  "created_at": "2026-05-11T08:00:00Z"
}

Response 400 — Validation errors.

json
{
  "username": [
    "A user with that username already exists."
  ]
}

Example

bash
curl -X PUT "https://api.example.com/sql-search/credentials/<id>/" \
  -H "Authorization: Token $FINBLADE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id":3,"connection":"mysql","server":"db.internal:3306","username":"reporting","password":"********","database":"erp","created_at":"2026-05-11T08:00:00Z"}'

DELETE /sql-search/credentials/{id}/

Delete a SQL connection

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Response 204 — Deleted.

Response 404 — Not yours.

Example

bash
curl -X DELETE "https://api.example.com/sql-search/credentials/<id>/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /sql-search/overview/

Sample rows from every table

Connects with the supplied credentials and returns up to limit rows from each table — used to preview a database before chatting with it.

Auth: Session token · In the app: Database search page → Overview

Request body (application/json)

FieldTypeRequiredDescription
connectionstring ("mysql", "mssql")yes
serverstringyes
usernamestringyes
passwordstringyes
databasestringyes
limitintegeryesRows per table.

Response 200 — Rows keyed by table name.

FieldTypeDescription
resultobject

Response 400 — Invalid limit.

json
{
  "error": "path is required"
}

Example

bash
curl -X POST "https://api.example.com/sql-search/overview/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /sql-search/chat/

Ask a question of a SQL database

Text-to-SQL over the supplied connection. The connection is cached per user for the conversation; both question and answer are stored in the SQL chat history.

Auth: Session token · In the app: Database search page → SQL chat

Request body (application/json)

FieldTypeRequiredDescription
connectionstring ("mysql", "mssql")yes
serverstringyes
usernamestringyes
passwordstringyes
databasestringyes
questionstringyes

Response 200 — Answer.

FieldTypeDescription
answerstring

Example

bash
curl -X POST "https://api.example.com/sql-search/chat/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

GET /sql-search/

My SQL chat history

Auth: Session token

Response 200 — Messages.

Array of:

FieldTypeDescription
idinteger
userinteger
messagestring
from_serverboolean
created_atstring (date-time)

Example

bash
curl -X GET "https://api.example.com/sql-search/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /sql-search/check-connection/

Test a saved SQL connection

Auth: Session token

Request body (application/json)

FieldTypeRequiredDescription
credential_idintegeryes

Response 200 — Connected.

FieldTypeDescription
successstring

Response 404 — Credential not found.

json
{
  "error": "path is required"
}

Response 500 — Connection failed (body carries the driver error).

json
{
  "error": "path is required"
}

Example

bash
curl -X POST "https://api.example.com/sql-search/check-connection/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /sql-search/fetch-files/

Scan a SQL table for document records

For document-management databases: reads rows from the credential's configured table (using its id_column, created_at_column, … mapping set by an administrator) and registers each as a file record that can later be downloaded and indexed.

Auth: Session token

Request body (application/json)

FieldTypeRequiredDescription
credential_idintegeryes
batch_sizeintegernoDefault: 1000.
max_recordsintegerno0 = no limit. Default: 0.

Response 200 — Scan summary.

FieldTypeDescription
successstring
savedinteger
skippedinteger
total_fetchedinteger
final_offsetinteger

Response 400 — Missing credential id or column mapping.

json
{
  "error": "path is required"
}

Example

bash
curl -X POST "https://api.example.com/sql-search/fetch-files/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

GET /sql-search/files/

File records found in a SQL table

Auth: Session token

Query parameters

FieldTypeRequiredDescription
credential_idintegeryes
downloadedbooleanno
embeddedbooleanno
file_idintegerno

Response 200 — Column mapping and records.

FieldTypeDescription
headersobjectThe credential's column mapping.
filesobject[]
files[].file_idinteger
files[].doc_instring, nullable
files[].doc_outstring, nullable
files[].remarksstring, nullable
files[].created_at_originalstring, nullable
files[].created_at_hijiristring, nullable
files[].downloadedboolean
files[].embeddedboolean
files[].created_atstring (date-time)

Example

bash
curl -X GET "https://api.example.com/sql-search/files/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /sql-search/download-files/

Import file records as documents

Downloads the content of the given records from the database and queues them for indexing in the semantic-search store.

Auth: Session token

Request body (application/json)

FieldTypeRequiredDescription
credential_idintegeryes
file_idsinteger[]yes

Response 202 — Queued.

FieldTypeDescription
batch_idstring
queuedinteger

Example

bash
curl -X POST "https://api.example.com/sql-search/download-files/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

GET /sql-search/files/content/{file_id}/

Raw content of a file record

Auth: Session token

Path parameters

FieldTypeRequiredDescription
file_idintegeryes

Query parameters

FieldTypeRequiredDescription
credential_idintegeryes

Response 200 — Content.

FieldTypeDescription
contentstring

Example

bash
curl -X GET "https://api.example.com/sql-search/files/content/<file_id>/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

DELETE /sql-search/files/{file_id}/

Delete an imported file record

Auth: Session token

Path parameters

FieldTypeRequiredDescription
file_idintegeryes

Response 200 — Deleted.

Response 404 — Not found.

Example

bash
curl -X DELETE "https://api.example.com/sql-search/files/<file_id>/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

GET /data-sources/

List data sources

Connections you own plus those shared with you, newest first.

Auth: Session token · In the app: My Data → Data sources

Response 200 — Data sources.

Array of:

FieldTypeDescription
idinteger
namestring
enginestring ("postgresql", "mysql", "mariadb", "mssql")
hoststringMust pass the deployment's host policy (no private/loopback ranges unless allowed).
portinteger, nullableDefaults to the engine's standard port.
databasestring
usernamestring
passwordstringWrite-only. Omit on update to keep; send "" to clear.
has_passwordboolean
optionsobjectDriver options (e.g. {"sslmode": "require"}).
allowed_tablesstring[]Restrict the connection to these tables (empty = all).
max_rowsintegerRow cap for queries.
sharedinteger[]User ids the connection is shared with.
credential_versionintegerIncrements when credentials change.
last_tested_atstring (date-time), nullable
last_test_okboolean, nullable
last_errorstring
created_atstring (date-time)
updated_atstring (date-time)
userintegerOwner id.

Example

bash
curl -X GET "https://api.example.com/data-sources/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /data-sources/

Create a data source

Auth: Session token · In the app: My Data → Data sources → New connection

Request body (application/json)

FieldTypeRequiredDescription
idintegerno
namestringno
enginestring ("postgresql", "mysql", "mariadb", "mssql")no
hoststringnoMust pass the deployment's host policy (no private/loopback ranges unless allowed).
portinteger, nullablenoDefaults to the engine's standard port.
databasestringno
usernamestringno
passwordstringnoWrite-only. Omit on update to keep; send "" to clear.
has_passwordbooleanno
optionsobjectnoDriver options (e.g. {"sslmode": "require"}).
allowed_tablesstring[]noRestrict the connection to these tables (empty = all).
max_rowsintegernoRow cap for queries.
sharedinteger[]noUser ids the connection is shared with.
credential_versionintegernoIncrements when credentials change.
last_tested_atstring (date-time), nullableno
last_test_okboolean, nullableno
last_errorstringno
created_atstring (date-time)no
updated_atstring (date-time)no
userintegernoOwner id.
json
{
  "name": "Warehouse (read-only)",
  "engine": "postgresql",
  "host": "warehouse.acme.internal",
  "port": 5432,
  "database": "analytics",
  "username": "readonly",
  "password": "s3cret",
  "allowed_tables": [
    "orders",
    "customers"
  ],
  "max_rows": 5000
}

Response 201 — Created.

FieldTypeDescription
idinteger
namestring
enginestring ("postgresql", "mysql", "mariadb", "mssql")
hoststringMust pass the deployment's host policy (no private/loopback ranges unless allowed).
portinteger, nullableDefaults to the engine's standard port.
databasestring
usernamestring
passwordstringWrite-only. Omit on update to keep; send "" to clear.
has_passwordboolean
optionsobjectDriver options (e.g. {"sslmode": "require"}).
allowed_tablesstring[]Restrict the connection to these tables (empty = all).
max_rowsintegerRow cap for queries.
sharedinteger[]User ids the connection is shared with.
credential_versionintegerIncrements when credentials change.
last_tested_atstring (date-time), nullable
last_test_okboolean, nullable
last_errorstring
created_atstring (date-time)
updated_atstring (date-time)
userintegerOwner id.
json
{
  "id": 7,
  "name": "Warehouse (read-only)",
  "engine": "postgresql",
  "host": "warehouse.acme.internal",
  "port": 5432,
  "database": "analytics",
  "username": "readonly",
  "has_password": true,
  "options": {
    "sslmode": "require"
  },
  "allowed_tables": [
    "orders",
    "customers"
  ],
  "max_rows": 5000,
  "shared": [
    57
  ],
  "credential_version": 2,
  "last_tested_at": "2026-09-20T09:00:00Z",
  "last_test_ok": true,
  "last_error": "",
  "created_at": "2026-06-01T09:00:00Z",
  "updated_at": "2026-09-20T09:00:00Z",
  "user": 42
}

Response 400 — Validation errors (including host policy).

json
{
  "host": [
    "Private network hosts are not allowed."
  ]
}

Example

bash
curl -X POST "https://api.example.com/data-sources/" \
  -H "Authorization: Token $FINBLADE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Warehouse (read-only)","engine":"postgresql","host":"warehouse.acme.internal","port":5432,"database":"analytics","username":"readonly","password":"s3cret","allowed_tables":["orders","customers"],"max_rows":5000}'

GET /data-sources/{id}/

Get a data source

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Response 200 — The data source.

FieldTypeDescription
idinteger
namestring
enginestring ("postgresql", "mysql", "mariadb", "mssql")
hoststringMust pass the deployment's host policy (no private/loopback ranges unless allowed).
portinteger, nullableDefaults to the engine's standard port.
databasestring
usernamestring
passwordstringWrite-only. Omit on update to keep; send "" to clear.
has_passwordboolean
optionsobjectDriver options (e.g. {"sslmode": "require"}).
allowed_tablesstring[]Restrict the connection to these tables (empty = all).
max_rowsintegerRow cap for queries.
sharedinteger[]User ids the connection is shared with.
credential_versionintegerIncrements when credentials change.
last_tested_atstring (date-time), nullable
last_test_okboolean, nullable
last_errorstring
created_atstring (date-time)
updated_atstring (date-time)
userintegerOwner id.
json
{
  "id": 7,
  "name": "Warehouse (read-only)",
  "engine": "postgresql",
  "host": "warehouse.acme.internal",
  "port": 5432,
  "database": "analytics",
  "username": "readonly",
  "has_password": true,
  "options": {
    "sslmode": "require"
  },
  "allowed_tables": [
    "orders",
    "customers"
  ],
  "max_rows": 5000,
  "shared": [
    57
  ],
  "credential_version": 2,
  "last_tested_at": "2026-09-20T09:00:00Z",
  "last_test_ok": true,
  "last_error": "",
  "created_at": "2026-06-01T09:00:00Z",
  "updated_at": "2026-09-20T09:00:00Z",
  "user": 42
}

Response 403 — Not shared with you.

json
{
  "detail": "Authentication credentials were not provided."
}

Example

bash
curl -X GET "https://api.example.com/data-sources/7/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

PUT /data-sources/{id}/

Update a data source

Owner only; partial update. Rotating credentials or narrowing shared revokes outstanding agent grants.

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Request body (application/json)

FieldTypeRequiredDescription
idintegerno
namestringno
enginestring ("postgresql", "mysql", "mariadb", "mssql")no
hoststringnoMust pass the deployment's host policy (no private/loopback ranges unless allowed).
portinteger, nullablenoDefaults to the engine's standard port.
databasestringno
usernamestringno
passwordstringnoWrite-only. Omit on update to keep; send "" to clear.
has_passwordbooleanno
optionsobjectnoDriver options (e.g. {"sslmode": "require"}).
allowed_tablesstring[]noRestrict the connection to these tables (empty = all).
max_rowsintegernoRow cap for queries.
sharedinteger[]noUser ids the connection is shared with.
credential_versionintegernoIncrements when credentials change.
last_tested_atstring (date-time), nullableno
last_test_okboolean, nullableno
last_errorstringno
created_atstring (date-time)no
updated_atstring (date-time)no
userintegernoOwner id.
json
{
  "id": 7,
  "name": "Warehouse (read-only)",
  "engine": "postgresql",
  "host": "warehouse.acme.internal",
  "port": 5432,
  "database": "analytics",
  "username": "readonly",
  "has_password": true,
  "options": {
    "sslmode": "require"
  },
  "allowed_tables": [
    "orders",
    "customers"
  ],
  "max_rows": 5000,
  "shared": [
    57
  ],
  "credential_version": 2,
  "last_tested_at": "2026-09-20T09:00:00Z",
  "last_test_ok": true,
  "last_error": "",
  "created_at": "2026-06-01T09:00:00Z",
  "updated_at": "2026-09-20T09:00:00Z",
  "user": 42
}

Response 200 — Updated.

FieldTypeDescription
idinteger
namestring
enginestring ("postgresql", "mysql", "mariadb", "mssql")
hoststringMust pass the deployment's host policy (no private/loopback ranges unless allowed).
portinteger, nullableDefaults to the engine's standard port.
databasestring
usernamestring
passwordstringWrite-only. Omit on update to keep; send "" to clear.
has_passwordboolean
optionsobjectDriver options (e.g. {"sslmode": "require"}).
allowed_tablesstring[]Restrict the connection to these tables (empty = all).
max_rowsintegerRow cap for queries.
sharedinteger[]User ids the connection is shared with.
credential_versionintegerIncrements when credentials change.
last_tested_atstring (date-time), nullable
last_test_okboolean, nullable
last_errorstring
created_atstring (date-time)
updated_atstring (date-time)
userintegerOwner id.
json
{
  "id": 7,
  "name": "Warehouse (read-only)",
  "engine": "postgresql",
  "host": "warehouse.acme.internal",
  "port": 5432,
  "database": "analytics",
  "username": "readonly",
  "has_password": true,
  "options": {
    "sslmode": "require"
  },
  "allowed_tables": [
    "orders",
    "customers"
  ],
  "max_rows": 5000,
  "shared": [
    57
  ],
  "credential_version": 2,
  "last_tested_at": "2026-09-20T09:00:00Z",
  "last_test_ok": true,
  "last_error": "",
  "created_at": "2026-06-01T09:00:00Z",
  "updated_at": "2026-09-20T09:00:00Z",
  "user": 42
}

Response 403 — Not the owner.

json
{
  "detail": "Authentication credentials were not provided."
}

Example

bash
curl -X PUT "https://api.example.com/data-sources/<id>/" \
  -H "Authorization: Token $FINBLADE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id":7,"name":"Warehouse (read-only)","engine":"postgresql","host":"warehouse.acme.internal","port":5432,"database":"analytics","username":"readonly","has_password":true,"options":{"sslmode":"require"},"allowed_tables":["orders","customers"],"max_rows":5000,"shared":[57],"credential_version":2,"last_tested_at":"2026-09-20T09:00:00Z","last_test_ok":true,"last_error":"","created_at":"2026-06-01T09:00:00Z","updated_at":"2026-09-20T09:00:00Z","user":42}'

DELETE /data-sources/{id}/

Delete a data source

Owner only. Refused with 409 while dashboard tiles use it, unless force=1.

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Query parameters

FieldTypeRequiredDescription
forcebooleanno

Response 200 — Deleted.

FieldTypeDescription
messagestring
json
{
  "message": "OK"
}

Response 409 — In use by dashboard tiles.

json
{
  "error": "This connection is used by dashboard tiles.",
  "in_use": [
    {
      "id": 91,
      "chart_name": "Orders by month",
      "category_id": 3
    }
  ]
}

Example

bash
curl -X DELETE "https://api.example.com/data-sources/<id>/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /data-sources/{id}/test/

Test the connection

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Response 200 — Always 200; read ok.

FieldTypeDescription
okboolean
latency_msinteger, nullable
errorstring
json
{
  "ok": true,
  "latency_ms": 38,
  "error": ""
}

Example

bash
curl -X POST "https://api.example.com/data-sources/<id>/test/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

GET /data-sources/{id}/tables/

Tables exposed by the connection

Cached for 5 minutes; refresh=1 forces a new read. Honours allowed_tables.

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Query parameters

FieldTypeRequiredDescription
refreshbooleanno

Response 200 — Tables.

FieldTypeDescription
tablesobject[]
tables[].namestring
tables[].schemastring
json
{
  "tables": [
    {
      "name": "orders",
      "schema": "public"
    },
    {
      "name": "customers",
      "schema": "public"
    }
  ]
}

Response 502 — The SQL service could not run the query.

json
{
  "error": "path is required"
}

Example

bash
curl -X GET "https://api.example.com/data-sources/<id>/tables/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

GET /data-sources/{id}/columns/

Columns of a table

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Query parameters

FieldTypeRequiredDescription
tablestringyes

Response 200 — Columns.

FieldTypeDescription
tablestring
columnsobject[]
columns[].namestring
columns[].typestring
json
{
  "table": "orders",
  "columns": [
    {
      "name": "id",
      "type": "integer"
    },
    {
      "name": "total",
      "type": "numeric"
    }
  ]
}

Example

bash
curl -X GET "https://api.example.com/data-sources/<id>/columns/?table=orders" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /data-sources/{id}/preview/

Preview rows

Up to 200 rows from a table, or from a read-only SELECT you supply.

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Request body (application/json)

FieldTypeRequiredDescription
tablestringno
sqlstringnoA SELECT statement (alternative to table).
json
{
  "sql": "SELECT region, SUM(total) AS total FROM orders GROUP BY region"
}

Response 200 — Rows.

FieldTypeDescription
columnsstring[]
rowsobject[]One object per row, keyed by column.
row_countinteger
truncatedbooleanTrue when the row cap cut the result.
elapsed_msinteger
json
{
  "columns": [
    "id",
    "region",
    "total"
  ],
  "rows": [
    {
      "id": 1,
      "region": "East",
      "total": 1200000
    },
    {
      "id": 2,
      "region": "West",
      "total": 900000
    }
  ],
  "row_count": 2,
  "truncated": false,
  "elapsed_ms": 41
}

Response 400 — Neither table nor sql, or a non-SELECT statement.

json
{
  "error": "path is required"
}

Example

bash
curl -X POST "https://api.example.com/data-sources/<id>/preview/" \
  -H "Authorization: Token $FINBLADE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"sql":"SELECT region, SUM(total) AS total FROM orders GROUP BY region"}'

GET /live-feeds/sources/

List live feeds

Auth: Session token · In the app: Dashboard → live tiles

Response 200 — Feeds you own or that are shared with you.

Array of:

FieldTypeDescription
idinteger
namestring
base_urlstringOrigin plus optional base path; requests are restricted to it.
auth_typestring ("none", "bearer", "header", "query")
auth_header_namestringFor header auth (e.g. X-API-Key).
auth_query_paramstringFor query auth (e.g. key).
api_keystringAccepted on create and update; never returned — read has_api_key instead.
has_api_keyboolean
verify_tlsboolean
sharedinteger[]
created_atstring (date-time)
updated_atstring (date-time)
userinteger

Example

bash
curl -X GET "https://api.example.com/live-feeds/sources/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /live-feeds/sources/

Create a live feed

Auth: Session token

Request body (application/json)

FieldTypeRequiredDescription
idintegerno
namestringno
base_urlstringnoOrigin plus optional base path; requests are restricted to it.
auth_typestring ("none", "bearer", "header", "query")no
auth_header_namestringnoFor header auth (e.g. X-API-Key).
auth_query_paramstringnoFor query auth (e.g. key).
api_keystringnoAccepted on create and update; never returned — read has_api_key instead.
has_api_keybooleanno
verify_tlsbooleanno
sharedinteger[]no
created_atstring (date-time)no
updated_atstring (date-time)no
userintegerno
json
{
  "name": "Lobby camera",
  "base_url": "https://cams.acme.internal",
  "auth_type": "header",
  "auth_header_name": "X-API-Key",
  "api_key": "s3cret"
}

Response 201 — Created.

FieldTypeDescription
idinteger
namestring
base_urlstringOrigin plus optional base path; requests are restricted to it.
auth_typestring ("none", "bearer", "header", "query")
auth_header_namestringFor header auth (e.g. X-API-Key).
auth_query_paramstringFor query auth (e.g. key).
api_keystringAccepted on create and update; never returned — read has_api_key instead.
has_api_keyboolean
verify_tlsboolean
sharedinteger[]
created_atstring (date-time)
updated_atstring (date-time)
userinteger
json
{
  "id": 4,
  "name": "Lobby camera",
  "base_url": "https://cams.acme.internal",
  "auth_type": "header",
  "auth_header_name": "X-API-Key",
  "auth_query_param": "",
  "has_api_key": true,
  "verify_tls": true,
  "shared": [],
  "created_at": "2026-07-01T08:00:00Z",
  "updated_at": "2026-07-01T08:00:00Z",
  "user": 42
}

Response 400 — Validation errors.

json
{
  "username": [
    "A user with that username already exists."
  ]
}

Example

bash
curl -X POST "https://api.example.com/live-feeds/sources/" \
  -H "Authorization: Token $FINBLADE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Lobby camera","base_url":"https://cams.acme.internal","auth_type":"header","auth_header_name":"X-API-Key","api_key":"s3cret"}'

GET /live-feeds/sources/{id}/

Get a live feed

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Response 200 — The feed.

FieldTypeDescription
idinteger
namestring
base_urlstringOrigin plus optional base path; requests are restricted to it.
auth_typestring ("none", "bearer", "header", "query")
auth_header_namestringFor header auth (e.g. X-API-Key).
auth_query_paramstringFor query auth (e.g. key).
api_keystringAccepted on create and update; never returned — read has_api_key instead.
has_api_keyboolean
verify_tlsboolean
sharedinteger[]
created_atstring (date-time)
updated_atstring (date-time)
userinteger
json
{
  "id": 4,
  "name": "Lobby camera",
  "base_url": "https://cams.acme.internal",
  "auth_type": "header",
  "auth_header_name": "X-API-Key",
  "auth_query_param": "",
  "has_api_key": true,
  "verify_tls": true,
  "shared": [],
  "created_at": "2026-07-01T08:00:00Z",
  "updated_at": "2026-07-01T08:00:00Z",
  "user": 42
}

Example

bash
curl -X GET "https://api.example.com/live-feeds/sources/<id>/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

PUT /live-feeds/sources/{id}/

Update a live feed

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Request body (application/json)

FieldTypeRequiredDescription
idintegerno
namestringno
base_urlstringnoOrigin plus optional base path; requests are restricted to it.
auth_typestring ("none", "bearer", "header", "query")no
auth_header_namestringnoFor header auth (e.g. X-API-Key).
auth_query_paramstringnoFor query auth (e.g. key).
api_keystringnoAccepted on create and update; never returned — read has_api_key instead.
has_api_keybooleanno
verify_tlsbooleanno
sharedinteger[]no
created_atstring (date-time)no
updated_atstring (date-time)no
userintegerno
json
{
  "id": 4,
  "name": "Lobby camera",
  "base_url": "https://cams.acme.internal",
  "auth_type": "header",
  "auth_header_name": "X-API-Key",
  "auth_query_param": "",
  "has_api_key": true,
  "verify_tls": true,
  "shared": [],
  "created_at": "2026-07-01T08:00:00Z",
  "updated_at": "2026-07-01T08:00:00Z",
  "user": 42
}

Response 200 — Updated.

FieldTypeDescription
idinteger
namestring
base_urlstringOrigin plus optional base path; requests are restricted to it.
auth_typestring ("none", "bearer", "header", "query")
auth_header_namestringFor header auth (e.g. X-API-Key).
auth_query_paramstringFor query auth (e.g. key).
api_keystringAccepted on create and update; never returned — read has_api_key instead.
has_api_keyboolean
verify_tlsboolean
sharedinteger[]
created_atstring (date-time)
updated_atstring (date-time)
userinteger
json
{
  "id": 4,
  "name": "Lobby camera",
  "base_url": "https://cams.acme.internal",
  "auth_type": "header",
  "auth_header_name": "X-API-Key",
  "auth_query_param": "",
  "has_api_key": true,
  "verify_tls": true,
  "shared": [],
  "created_at": "2026-07-01T08:00:00Z",
  "updated_at": "2026-07-01T08:00:00Z",
  "user": 42
}

Example

bash
curl -X PUT "https://api.example.com/live-feeds/sources/<id>/" \
  -H "Authorization: Token $FINBLADE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"id":4,"name":"Lobby camera","base_url":"https://cams.acme.internal","auth_type":"header","auth_header_name":"X-API-Key","auth_query_param":"","has_api_key":true,"verify_tls":true,"shared":[],"created_at":"2026-07-01T08:00:00Z","updated_at":"2026-07-01T08:00:00Z","user":42}'

DELETE /live-feeds/sources/{id}/

Delete a live feed

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Response 200 — Deleted.

FieldTypeDescription
messagestring
json
{
  "message": "OK"
}

Example

bash
curl -X DELETE "https://api.example.com/live-feeds/sources/<id>/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /live-feeds/sources/{id}/test/

Test a live feed

Probes base_url + path. Always answers 200; read ok.

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Request body (application/json, optional)

FieldTypeRequiredDescription
pathstringnoDefault: "/".

Response 200 — Probe result.

FieldTypeDescription
okboolean
urlstring
status_codeinteger
latency_msinteger
content_typestring
samplestring, nullableFirst 500 characters for text/JSON responses.
errorstring

Example

bash
curl -X POST "https://api.example.com/live-feeds/sources/<id>/test/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

GET /live-feeds/sources/{id}/proxy/

Fetch JSON through a live feed

Proxies a GET to base_url + path with the feed's credentials attached server-side (max 5 MB). Extra query parameters are forwarded upstream.

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Query parameters

FieldTypeRequiredDescription
pathstringyes

Response 200 — The upstream JSON (upstream status codes are passed through).

Response 502 — Upstream error.

Response 504 — Upstream timed out.

Example

bash
curl -X GET "https://api.example.com/live-feeds/sources/<id>/proxy/?path=%2Fapi%2Fstatus" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /live-feeds/sources/{id}/stream-url/

Get a signed URL for a camera stream

Mirrors media signing — returns a short-lived URL (default 5 minutes) that can be placed in an <img src> to relay an MJPEG stream or snapshot.

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Request body (application/json)

FieldTypeRequiredDescription
pathstringyes
ttlintegerno
json
{
  "path": "/video.mjpg"
}

Response 200 — Signed relative URL.

FieldTypeDescription
pathstring
urlstringRelative URL (live-feeds/sources/{id}/stream/?…).
expires_atinteger
ttlinteger

Example

bash
curl -X POST "https://api.example.com/live-feeds/sources/<id>/stream-url/" \
  -H "Authorization: Token $FINBLADE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"path":"/video.mjpg"}'

GET /live-feeds/sources/{id}/stream/

Relay a camera stream

Streams the upstream response chunk by chunk. Authenticated only by the signature from stream-url/; at most 12 concurrent relays per API process.

Auth: Signed URL (from stream-url/)

Path parameters

FieldTypeRequiredDescription
idintegeryes

Query parameters

FieldTypeRequiredDescription
pathstringyes
expires_atintegeryes
user_idintegeryes
signaturestringyes

Response 200 — The stream (e.g. multipart/x-mixed-replace MJPEG or an image).

Response 403 — Invalid or expired signature.

Response 503 — Relay limit reached.

Example

bash
curl -X GET "https://api.example.com/live-feeds/sources/<id>/stream/"

GET /templates/

List prompt templates

Your templates plus shared (general) ones, optionally filtered by type.

Auth: Session token · In the app: My Data → Templates

Query parameters

FieldTypeRequiredDescription
typestringno

Response 200 — Templates.

Array of:

FieldTypeDescription
idinteger
userinteger, nullable
typestringFree-form grouping key, e.g. semantic_search.
titlestring
contentstringThe prompt text.
generalboolean
created_atstring (date-time)

Example

bash
curl -X GET "https://api.example.com/templates/?type=semantic_search" \
  -H "Authorization: Token $FINBLADE_TOKEN"

POST /templates/

Create a prompt template

Auth: Session token

Request body (application/json)

FieldTypeRequiredDescription
titlestringno
contentstringyes
typestringno
generalbooleannoDefault: false.
json
{
  "title": "Executive summary",
  "content": "Summarise the document for a board audience in five bullets.",
  "type": "semantic_search"
}

Response 201 — Created.

FieldTypeDescription
idinteger
userinteger, nullable
typestringFree-form grouping key, e.g. semantic_search.
titlestring
contentstringThe prompt text.
generalboolean
created_atstring (date-time)
json
{
  "id": 12,
  "user": 42,
  "type": "semantic_search",
  "title": "Executive summary",
  "content": "Summarise the document for a board audience in five bullets.",
  "general": false,
  "created_at": "2026-04-02T10:00:00Z"
}

Response 400 — Validation errors.

json
{
  "username": [
    "A user with that username already exists."
  ]
}

Example

bash
curl -X POST "https://api.example.com/templates/" \
  -H "Authorization: Token $FINBLADE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Executive summary","content":"Summarise the document for a board audience in five bullets.","type":"semantic_search"}'

GET /templates/{id}/

Get a template

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Response 200 — The template.

FieldTypeDescription
idinteger
userinteger, nullable
typestringFree-form grouping key, e.g. semantic_search.
titlestring
contentstringThe prompt text.
generalboolean
created_atstring (date-time)
json
{
  "id": 12,
  "user": 42,
  "type": "semantic_search",
  "title": "Executive summary",
  "content": "Summarise the document for a board audience in five bullets.",
  "general": false,
  "created_at": "2026-04-02T10:00:00Z"
}

Example

bash
curl -X GET "https://api.example.com/templates/<id>/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

PUT /templates/{id}/

Update a template

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Request body (application/json)

FieldTypeRequiredDescription
titlestringno
contentstringno
typestringno
generalbooleanno

Response 200 — The updatable fields after the change.

FieldTypeDescription
templateobject
template.titlestring
template.contentstring
template.typestring
template.generalboolean

Example

bash
curl -X PUT "https://api.example.com/templates/<id>/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

DELETE /templates/{id}/

Delete a template

Auth: Session token

Path parameters

FieldTypeRequiredDescription
idintegeryes

Response 204 — Deleted.

Example

bash
curl -X DELETE "https://api.example.com/templates/<id>/" \
  -H "Authorization: Token $FINBLADE_TOKEN"

Finblade documentation