apis.php
Zentrale Definition aller externen APIs.
Alle externen HTTP-Dienste, gegen die deine Tools Requests schicken, werden hier einmal definiert. Tools referenzieren sie per Key. Das hält Auth und Base-URLs an einer Stelle.
Aufbau
<?php
return [
'apis' => [
'<key>' => [
'base_url' => '...',
'headers' => [ ... ],
// optional:
'_auth' => '...',
'timeout' => 30,
],
// weitere Keys ...
],
];
Felder
| Feld | Pflicht | Bedeutung |
|---|---|---|
base_url |
ja | Basis-URL, wird mit path aus Tools kombiniert |
headers |
empfohlen | Statische Header (Accept, Authorization, Custom) |
_auth |
optional | Query-String, der an jede URL angehängt wird |
timeout |
optional | Timeout in Sekunden (default 30) |
Auth wird in dieser Datei immer als Header oder _auth-Query gesetzt. Für OAuth-basierte APIs trägst du kein separates auth-Feld ein — die Access-Tokens werden über die unter OAuth-Verbindungen verwalteten Benutzer-Verbindungen vom Tool-Handler zur Laufzeit gezogen.
Beispiele
Bearer-Token (statisch)
'shop_api' => [
'base_url' => 'https://shop.example.com/api/v2/',
'headers' => [
'Authorization' => 'Bearer sk_live_abc123…',
'Accept' => 'application/json',
],
],
OAuth-basierte API
OAuth-Tokens kommen nicht direkt aus apis.php. Registriere in apis.php nur die Basis-URL (und ggf. statische Header), und lass den Access-Token im Tool-Handler einsetzen:
// apis.php
'google_drive' => [
'base_url' => 'https://www.googleapis.com/drive/v3/',
'headers' => [
'Accept' => 'application/json',
],
],
Im Handler ziehst du den Token der OAuth-Verbindung und setzt ihn als Bearer-Header beim HTTP-Call. Details: OAuth-Verbindungen.
Query-String-Auth
'weather' => [
'base_url' => 'https://api.openweathermap.org/data/2.5/',
'_auth' => 'appid=abc123…',
],
_auth wird an jede URL angehängt — praktisch für APIs, die Keys als Query-Parameter erwarten.
Basic Auth
'legacy' => [
'base_url' => 'https://legacy.example.com/api/',
'headers' => [
'Authorization' => 'Basic ' . base64_encode('user:passwort'),
],
],
Mehrere Base-URLs desselben Dienstes
Manche Services (z. B. Dropbox) haben separate Endpunkte für API und Content-Upload:
'dropbox' => [
'base_url' => 'https://api.dropboxapi.com/2/',
],
'dropbox_content' => [
'base_url' => 'https://content.dropboxapi.com/2/',
],
Zwei API-Keys, dieselbe OAuth-Verbindung. Den Bearer-Token setzt der Tool-Handler.
Credentials
API-Keys gehören NICHT als Klartext in apis.php. Stattdessen nutzt du den {{secret:KEY}}-Marker. Der ToolRunner expandiert ihn unmittelbar vor jedem HTTP-Call:
// apis.php — sicher, kann ins Git
'apis' => [
'shop_api' => [
'base_url' => 'https://shop.example.com/api/v2/',
'headers' => [
'Authorization' => 'Bearer {{secret:SHOP_API_TOKEN}}',
'Accept' => 'application/json',
],
],
],
# .env — untracked, niemals einchecken
SHOP_API_TOKEN=sk_live_abc123
Der String bleibt in der Config-Datei lesbar mit Marker, in Logs/Knowledge-Index/LLM-Kontext steht ebenfalls nur der Marker. Erst beim echten Request wird er ersetzt.
Wo liegt die .env
- Bei dir lokal: nach
tm pulllegt die CLI eine Skeleton-Datei an. Pfad wird angezeigt, üblicherweise im selben Verzeichnis wie dein Tenant-Config. - Auf dem Server: liegt unter
shared/tenants_untracked/<dein-code>/.envund überlebt Deploys. - Die echten Werte syncen wir nicht über die API — du pflegst sie lokal in der
.envund der Server hat seine eigene Kopie.
Welche Keys es gibt
config/tenants/_template/.env.example im Repo (wird beim tm pull automatisch mitgeliefert) listet die Standard-Keys mit Kommentaren — Shopify, JTL, SendGrid, Anthropic, SMTP/IMAP, Trello, FinAPI, Dropbox.
Isolation
Der Marker {{secret:X}} wird nur mit Werten deines eigenen Tenants aufgelöst. Andere Tenants haben ihre eigene .env, du kommst nicht ran. Werte landen auch nicht in $_ENV — kein Risiko, dass ein anderes Skript sie sieht.
Wenn Key fehlt
{{secret:FEHLT_NICHT}} wird zu einem leeren String. Tools die einen leeren Token sehen, scheitern mit HTTP 401 — das ist der Hinweis, dass deine .env unvollständig ist.
secret()-Helper für komplexere Handler
Für Handler-Code, der einen Secret-Wert programmatisch braucht (z.B. JWT-Signierung, Custom-Header-Berechnung), gibt es zusätzlich den secret()-Helper:
'handler' => function ($r, $args, $ctx) {
$token = generateJwt($args['user'], secret('JWT_SIGNING_KEY'));
return $ctx['tool']('callApi', ['token' => $token]);
},
Sicherheits-Hinweis.
.envNIE ins Git pushen. Sie steht in.gitignore— wenn du sie trotzdem siehst (git statuszeigt sie als untracked), lass sie da.- Bei Key-Rotation: Wert in
.enversetzen — keintm syncnötig, der ToolRunner liest live.- Wenn du
apis.phppertm pullaktualisierst, bleibt deine.envunangetastet.
Migration alter Configs
Wenn du noch 'Authorization' => 'Bearer sk_live_xyz' als Klartext in apis.php hast:
// Vorher
'headers' => ['Authorization' => 'Bearer sk_live_xyz'],
// Nachher
'headers' => ['Authorization' => 'Bearer {{secret:SHOP_API_TOKEN}}'],
Wert in .env legen (SHOP_API_TOKEN=sk_live_xyz), apis.php committen — fertig.
Wie Tools API-Keys referenzieren
Im Tool:
'tools' => [
'getRecentOrders' => [
'api' => 'shop_api', // ← Key aus apis.php
'method' => 'GET',
'path' => 'orders?limit=5',
],
],
Der Runner holt sich shop_api aus apis.php, setzt Header und Base-URL, und feuert den Request ab.
Debug
Wenn ein Tool plötzlich 401 gibt und du den API-Key gerade geändert hast: vielleicht ist die Env-Variable auf dem Server nicht aktualisiert. Beim Betreiber nachfragen.
Wenn du nicht sicher bist, ob die API überhaupt erreichbar ist:
tm test-tool getRecentOrders since=today
tm logs # zeigt URL + Status