REST API
Die HTTP-Schnittstelle, die ObjectOS bereitstellt — aus deinen Metadaten generiert, durch Berechtigungen eingegrenzt, per OpenAPI beschrieben.
REST API
Jedes Objekt, das du deklarierst, erhält automatisch einen vollständigen
Satz von REST-Endpunkten. Jede Action wird zu einem POST. Jeder Flow
wird zu einem POST auf /flows/.... Es gibt keine separate API-Schicht,
die du schreiben oder bereitstellen musst.
Basis-URL: https://<your-host>/api/v1.
Die OpenAPI-Spezifikation ist live unter /api/v1/openapi.json verfügbar.
Authentication
ObjectOS verwendet Better Auth. Alle Routen
unter /api/v1 erfordern eine authentifizierte Sitzung, sofern sie nicht
ausdrücklich als public markiert sind (siehe Public forms).
Die Authentifizierungsmethoden werden in apps/<app>/auth.config.ts
konfiguriert — typischerweise ein Session-Cookie oder ein Bearer-Token von
/api/v1/auth/sign-in.
Berechtigungen werden pro Route, pro Datensatz geprüft. Routen, die unten
mit einem Berechtigungsschlüssel (z. B. ai:chat) annotiert sind, rufen
requirePermission(...) auf; der Zugriff auf Datensatzebene wird durch RBAC +
Row-Level Security + Field-Level Security innerhalb der Daten-Engine
durchgesetzt.
Discovery
| Pfad | Methode | Zweck |
|---|---|---|
/api/v1 | GET | Service Discovery — listet alle registrierten Routen, die Version und den Scoping-Modus auf |
/api/v1/discovery | GET | Expliziter Alias für das obige Discovery-Dokument |
/api/v1/openapi.json | GET | OpenAPI-3.0-Spezifikation für jeden Endpunkt im laufenden Runtime |
/api/v1/search | GET | Volltextsuche über durchsuchbare Felder aller Objekte |
API-Oberfläche einschränken
Die automatisch generierten Endpunkte werden pro Objekt gesteuert, sodass du ein Objekt von der API nehmen oder schreibgeschützt machen kannst, ohne Routen-Code zu schreiben:
apiEnabled(boolean, Standardtrue) — auffalsesetzen, um das Objekt vollständig von der REST-Oberfläche auszuschließen. Anfragen an seine Routen liefern 404.apiMethods(optionale Whitelist) — wenn gesetzt, sind nur die aufgeführten Operationen erreichbar; jede andere Operation wird auf der REST-Ebene abgelehnt. Erlaubte Werte:get,list,create,update,delete,upsert,bulk,aggregate,history,search,restore,purge,import,export.
// Ein schreibgeschütztes Referenzobjekt, niemals über die API beschreibbar:
defineObject({
name: 'exchange_rate',
apiMethods: ['get', 'list'],
// ...fields
})
// Ein internes Objekt, das die API niemals offenlegt:
defineObject({
name: 'sync_cursor',
apiEnabled: false,
// ...fields
})Beide werden jetzt auf der REST-Ebene durchgesetzt (ADR-0049) — frühere Versionen parsten diese Eigenschaften, wendeten sie aber nicht an.
Data — /api/v1/data/*
CRUD + erweiterte Abfragen für jedes Objekt, das du deklarierst. :object ist
der name des Objekts (snake_case).
| Pfad | Methode | Zweck |
|---|---|---|
/data/:object | GET | Auflisten / Abfragen — übergib where, orderBy, limit, offset, cursor, expand, select als Query-Parameter |
/data/:object/query | POST | Erweiterte Abfrage — vollständiger ObjectQL-Body mit groupBy + aggregations (siehe ObjectQL) |
/data/:object/:id | GET | Einen Datensatz abrufen. Unterstützt ?select= und ?expand= |
/data/:object | POST | Erstellen. Gibt 201 mit dem neuen Datensatz zurück |
/data/:object/:id | PATCH | Aktualisieren. Übergib den Header If-Match: <version> (oder expectedVersion im Body) für optimistische Nebenläufigkeit — 409 CONCURRENT_UPDATE bei einem Konflikt |
/data/:object/:id | DELETE | Löschen. Gleiche If-Match-Regel |
/data/:object/import | POST | Massenimport (CSV oder JSON). Body: { format, csv? | rows?, mapping?, dryRun? }. Maximal 5.000 Zeilen pro Anfrage |
/data/:object/export | POST | Datensätze als csv / xlsx / pdf / json exportieren |
/data/:object/:id/shares | GET / POST | Freigabe pro Datensatz — Freigaben auflisten, Zugriff gewähren |
/data/:object/:id/shares/:shareId | DELETE | Eine Freigabe widerrufen |
/data/lead/:id/convert | POST | Lead-Konvertierung im Salesforce-Stil (CRM-Vorlage). Body: { accountId?, contactId?, createOpportunity? } |
Kurzes Beispiel
GET /api/v1/data/support_ticket?where={"status":{"$eq":"open"}}&orderBy=-created_at&limit=20
Authorization: Bearer <token>{
"items": [ { "id": "...", "subject": "...", "status": "open" } ],
"total": 137,
"nextCursor": "eyJpZCI6IjAxSDA..."
}AI — /api/v1/ai/*
Die Endpunkte, auf denen der AI Builder und deine Agenten aufsetzen.
| Pfad | Methode | Berechtigung | Zweck |
|---|---|---|---|
/ai/models | GET | ai:chat | Verfügbare Modelle der konfigurierten Anbieter auflisten |
/ai/chat | POST | ai:chat | Einmalige Chat-Completion (synchron) |
/ai/chat/stream | POST | ai:chat | Streaming-Chat (SSE) |
/ai/complete | POST | ai:chat | Roher Completion-Endpunkt |
/ai/conversations | GET / POST | ai:chat | Persistente Konversationen auflisten / erstellen |
/ai/conversations/:id | GET / DELETE | ai:chat | Eine Konversation lesen / löschen |
/ai/conversations/:id/messages | POST | ai:chat | Eine Benutzernachricht anhängen und den Agenten ausführen |
/ai/pending-actions | GET | ai:read | Die HITL-Freigabewarteschlange — von der KI vorgeschlagene Mutationen |
/ai/pending-actions/:id | GET | ai:read | Eine eingereihte Mutation inspizieren |
/ai/pending-actions/:id/approve | POST | ai:approve | Die Mutation anwenden |
/ai/pending-actions/:id/reject | POST | ai:approve | Sie verwerfen |
Die Trennung zwischen ai:read und ai:approve ist das
Sicherheitsprimitiv, das den AI Builder für Endbenutzer sicher macht.
Actions — /api/v1/actions/*
Jede *.action.ts, die du deklarierst, wird zu einem Endpunkt.
| Pfad | Methode | Zweck |
|---|---|---|
/actions/:action | POST | Die Action aufrufen. Der Body ist das Input-Schema der Action. Berechtigungen und Eingabevalidierung stammen aus der Action-Deklaration |
Jede Action wird der KI außerdem als action_<name>-Tool bereitgestellt — siehe
Actions.
Flows — /api/v1/flows/*
| Pfad | Methode | Zweck |
|---|---|---|
/flows/:flow/start | POST | Einen Flow starten. Der Body ist die Flow-Eingabe |
/flows/:flow/runs/:runId | GET | Status + Schritt-Ausgabe eines laufenden / abgeschlossenen Flows |
/flows/:flow/runs/:runId/cancel | POST | Einen laufenden Durchlauf abbrechen |
Metadata — /api/v1/meta/*
Schreibgeschützte Introspektion der Metadaten des laufenden Runtime. Nützlich für Tooling und die Console.
| Pfad | Methode | Zweck |
|---|---|---|
/meta | GET | Alle Metadatentypen (object, view, action, flow, agent, …) |
/meta/:type | GET | Elemente eines Typs auflisten. Filtern mit ?package=<id> |
/meta/:type/:name | GET | Ein Element abrufen. ?layers=true liefert die 3-Zustands-Diff-Ansicht (base / package / overlay) |
/meta/:type/:name/references | GET | Jedes Metadatenelement finden, das auf dieses verweist |
/meta/:type/:name/history | GET | Audit-Verlauf für dieses Element |
/meta/:type/:section/:name | GET / POST | Ein in Abschnitte gegliedertes Metadatenelement lesen / upserten |
/meta/:type/:section/:name | DELETE | Ein in Abschnitte gegliedertes Element löschen |
Sharing & Freigaben
| Pfad | Methode | Zweck |
|---|---|---|
/sharing/rules | GET / POST / DELETE | Freigaberegeln verwalten |
/sharing/rules/:idOrName/evaluate | POST | Eine Regel testweise gegen einen Kontext ausführen |
/approvals/processes | GET / POST | Definitionen von Genehmigungsprozessen |
/approvals/requests | GET / POST | Genehmigungsanfragen einreichen / auflisten |
/approvals/requests/:id/approve | POST | Entscheidung: genehmigen |
/approvals/requests/:id/reject | POST | Entscheidung: ablehnen |
Reports & Suche
| Pfad | Methode | Zweck |
|---|---|---|
/reports | GET / POST / PATCH | Report-CRUD |
/reports/:id/run | POST | Einen Report ausführen — gibt aggregierte Zeilen zurück |
/reports/:id/schedule | POST | Wiederkehrende Auslieferung planen |
Public forms
Die einzigen Routen, die unauthentifiziert sind, per Opt-in über
FormView.sharing.allowAnonymous.
| Pfad | Methode | Auth |
|---|---|---|
/forms/:slug | GET | public — gibt das Formularschema zurück |
/forms/:slug/submit | POST | public — übermittelt eine Antwort |
Utilities
| Pfad | Methode | Berechtigung | Zweck |
|---|---|---|---|
/email/send | POST | email:send | Eine E-Mail über den konfigurierten Anbieter senden |
Fehler-Envelope
Jede Antwort, die nicht 2xx ist, folgt derselben Struktur:
{
"error": {
"code": "PERMISSION_DENIED",
"message": "Missing ai:approve on conversation 01H…",
"details": { "permission": "ai:approve", "subject": "01H…" }
}
}Häufige Codes: UNAUTHENTICATED, PERMISSION_DENIED,
VALIDATION_ERROR, NOT_FOUND, CONCURRENT_UPDATE,
RATE_LIMITED, INTERNAL.
Versionierung
/api/v1 ist die stabile API. Breaking Changes gehen nach /api/v2, und
beide werden für ein Minor-Release parallel bereitgestellt. Die aktuelle
Version und der Deprecation-Horizont stehen in GET /api/v1.
Siehe auch
- ObjectQL — die von
/data/*verwendete Abfragesprache - Field types — welche Formen Daten annehmen können
- Build → Actions — eigene Endpunkte deklarieren
- Security — was jede Route prüft, bevor sie ausgeführt wird