Fuga exposes a standardized integration model so any external AI solution — an AI scribe / dictation tool (Vetnio, CoVet, IzyScribe, Squako, Tandem Health, …) or an AI assistant (Claude, ChatGPT) — can connect to a practice's Fuga data in a uniform way. There is no bespoke project per vendor: a new partner is onboarded by registering them as an OAuth client. This article describes the OAuth 2.0 model, the REST endpoints, and the MCP connector currently offered. Endpoints marked (roadmap) are planned, not yet live.
All paths below use the production context path /backend. The base URL is the fuga-backend host, e.g. https://<fuga-backend-host>/backend.
1. OAuth 2.0 — Fuga is the identity provider
Fuga-backend is itself the OAuth 2.0 authorization server (built on Spring Authorization Server — not Auth0). The vet authorizes the external solution with their own Fuga credentials; the solution never sees or stores a password.
- Grant types:
authorization_code+refresh_token - Client authentication:
client_secret_basicfor confidential clients (scribes); public clients use PKCE with no secret (AI assistants). - Token signing: RS256 (RSA 2048-bit), key id
oauth-server-key-1 - Authorization code TTL: 10 minutes · Access token TTL: 1 day · Refresh token TTL: 30 days (reusable)
- Consent screen: not shown
Standard OAuth 2.0 / OIDC endpoints:
Authorization GET /backend/oauth2/authorize Token POST /backend/oauth2/token JWK Set GET /backend/oauth2/jwks OIDC Discovery GET /backend/.well-known/openid-configuration Token Revocation POST /backend/oauth2/revoke Token Introspection POST /backend/oauth2/introspect
The issued JWT carries: sub (the Fuga username, e.g. FU000601), practiceId (extracted from the username), roles, scope (the granted scopes), iat, exp. Every API and MCP call is automatically isolated to the practiceId in the token — a caller can only ever reach its own practice's data.
Send the access token as a standard bearer header:
Authorization: Bearer <access_token>
You must request a JWT from us. Access is granted by Sonetas — there is no self-service signup. To be allowed to call the API you request access from us; we register you as an OAuth client with the scopes your use case needs and you then obtain a JWT through the OAuth flow above. Without a valid Sonetas-issued token every call is rejected.
2. API reference — fuga-backend Swagger / OpenAPI
The complete and authoritative reference for every REST endpoint, parameter and schema is the fuga-backend Swagger / OpenAPI documentation:
Swagger UI https://<fuga-backend-host>/backend/swagger-ui.html OpenAPI JSON https://<fuga-backend-host>/backend/v3/api-docs
The Swagger UI is scope-aware and protected. Use its “Authorize” button with a bearer JWT (the Sonetas-issued token described above) to see and try the calls your scopes allow.
3. Scopes
Authorization is scope-based, in the form method:domain. A registered client is granted only the scopes it needs; the JWT's scope claim is enforced per endpoint.
Consultations (REST) read:api_consultations read a consultation write:api_consultations create / update a consultation Agenda items (REST) query:api_agendaItems list agenda items read:api_agendaItems read a single agenda item write:api_agendaItems create / update an agenda item delete:api_agendaItems delete an agenda item MCP tools query:mcp_agendaItems read the agenda (appointments) query:mcp_personFromPractices list vets / assistants query:mcp_appointmentTypes list bookable appointment types OIDC openid
4. REST API — Consultations
This is the core endpoint for AI scribes: the vet dictates, the solution writes the structured report back into the consultation.
GET /backend/api/consultations list (paginated) query: or read:api_consultations
GET /backend/api/consultations/{id} get one read:api_consultations
POST /backend/api/consultations create write:api_consultations
PUT /backend/api/consultations/{id} full update write:api_consultations
PATCH /backend/api/consultations/{id} partial update write:api_consultations
DELETE /backend/api/consultations/{id} delete delete:api_consultationsRead response (GET) — ApiConsultationDto:
{
"id": "string",
"date": "2026-06-13",
"description": "string",
"intern": "string",
"weight": "string",
"anamnesis": "string",
"clinicalExamination": "string",
"additionalExamination": "string",
"diagnosis": "string",
"diffDiagnosis": "string",
"therapy": "string",
"followup": "string",
"prognosis": "string",
"client": { "id": "string", "name": "string" },
"animal": {
"id": "string",
"name": "string",
"breed": { "id": "string", "name": "string" },
"species": "DOG",
"sex": "MALE",
"dateOfBirth": "2020-01-01"
}
}The write side (POST / PUT / PATCH) accepts only the clinical text fields — description, intern, weight, anamnesis, clinicalExamination, additionalExamination, diagnosis, diffDiagnosis, therapy, followup, prognosis. The id, date, client and animal can be read back but cannot be set or reassigned through the API. On PATCH, an omitted field is left unchanged; an explicit null clears it.
5. REST API — Agenda items, clients & animals (read)
Read access to the practice's agenda, and (roadmap) to its clients and their animals.
GET /backend/api/agendaItems list (paginated) query:api_agendaItems
GET /backend/api/agendaItems/{id} get one read:api_agendaItems
GET /backend/api/clients list clients (roadmap)
GET /backend/api/clients/{id} get one client (roadmap)
GET /backend/api/animals list animals, filter by clientId (roadmap)
GET /backend/api/animals/{id} get one animal (roadmap)The agenda write: / delete:api_agendaItems scopes exist on the same controller but are granted only on request — the typical scribe integration receives read access only. The clients and animals read endpoints (roadmap, SON-3737) are part of the base AI integration package, not a paid extension; they mirror Fuga's internal client/animals endpoints (animals filterable by clientId).
Agenda response — ApiAgendaItemDto:
{
"id": "string",
"date": "2026-06-13",
"beginTime": "09:00",
"endTime": "09:20",
"type": "...",
"status": "string",
"description": "string",
"personFromPractices": [ { "id": "string" } ],
"personFromClient": { "id": "string" },
"animal": { "id": "string" },
"appointmentType": { "id": "string" },
"location": { "id": "string" }
}6. MCP connector
For AI assistants that speak the Model Context Protocol (Claude, ChatGPT), Fuga also exposes a read-only MCP server. This lets the assistant query a practice's agenda in natural language without a custom REST integration.
- Endpoint:
/backend/mcp - Transport: streamable HTTP, stateless (Spring AI MCP server). Server name
fuga, version1.0.0. - Authentication: the same OAuth 2.0 server as above. MCP clients are registered as public clients (PKCE, no secret) and receive a bearer token whose
query:mcp_*scopes gate each tool. Calls are isolated perpracticeIdlike the REST API. - Discovery: OAuth 2.0 Protected Resource Metadata (RFC 9728) is served at
/backend/.well-known/oauth-protected-resourceand/backend/.well-known/oauth-protected-resource/mcp, pointing the client at the authorization server and the supported scopes.
Tools ((roadmap) = planned, part of the base package):
getAgendaItems scope query:mcp_agendaItems
Agenda items (appointments and other calendar entries) for a date range,
optionally filtered by vet. Availability can be derived from the items.
Params: dateFrom (yyyy-MM-dd), dateTo (yyyy-MM-dd),
personFromPracticeId (optional), pageNumber, pageSize
getPersonFromPractices scope query:mcp_personFromPractices
All personFromPractices (vets and assistants); the Type tells which.
Params: none
getAppointmentTypes scope query:mcp_appointmentTypes
The appointment types of the practice: what can be booked and the
expected duration.
Params: none
getClients scope query:mcp_clients (roadmap)
The practice's clients (pet owners).
getAnimals scope query:mcp_animals (roadmap)
The practice's animals, optionally filtered by clientId.7. Consultation start trigger (optional)
Besides the vet launching the solution from the vendor's own app, Fuga can optionally launch the solution from inside an open consultation — a button in the consultation action bar that opens the vendor's web app. Fuga can pass the consultation id and the appointment id (the agenda item) as query parameters, so the solution knows exactly which consultation to write its report back to (via the consultations API) and which appointment it belongs to.
Example shape (target URL and parameter names are agreed per vendor at onboarding):
https://<vendor-app>/...?consultationId={consultationId}&appointmentId={appointmentId}The existing Vetnio button already works this way today, passing the consultation id (as external_id) plus the animal name; the appointment id can be added in the same manner for a new vendor. This trigger is optional — a solution can also run purely from its own UI and rely on the REST API alone.
8. Onboarding a new AI solution
The standardized model means no new development is needed to add a vendor. A new partner is registered as a dedicated OAuth client (its own client_id / secret, or PKCE for a public MCP client) with exactly the scopes its use case needs — typically read: + write:api_consultations for a scribe, plus query:api_agendaItems or the query:mcp_* scopes for agenda read. Currently registered clients: vetnio and covet (scribes), claude and chatgpt (MCP). Onboarding a new vendor is a commercial decision; the technical path already exists.
The capabilities described above (read/write of consultations, read of the agenda, and the roadmap clients/animals read) are the base AI integration package. Additional functionality — for example booking appointments through the API — will be offered as paid extensions within Fuga.
Commercially, API access to the integration is offered on a revenue-share basis; the concrete terms are agreed as part of the partner onboarding.
9. Test / integration environment
You can build and validate the integration without touching production data. Sonetas provides a shared integration practice — used by our other integration partners as well — that you connect to while developing. It is available on a production-test level and on the test4 and test5 environments.
Error responses follow RFC 9457 Problem Details (application/problem+json) — see the separate article on the fuga-backend error format.