TaskMonkey Handbuch

Eigene REST-API anbinden

Wie du Dienste einbindest, die kein OAuth brauchen — klassische API-Keys.

Nicht jeder Dienst, an den du andocken willst, hat OAuth. Viele APIs identifizieren sich einfach per API-Key, Bearer-Token oder Basic Auth im Header.

In apis.php eintragen

<?php
return [
    'apis' => [
        'shop_api' => [
            'base_url' => 'https://shop.example.com/api/v2/',
            'headers' => [
                'Authorization' => 'Bearer sk_live_abc123…',
                'Accept' => 'application/json',
            ],
        ],

        'weather' => [
            'base_url' => 'https://api.openweathermap.org/data/2.5/',
            '_auth' => 'appid=abc123…',
        ],
    ],
];

Zwei typische Muster:

  • headers: Auth als HTTP-Header (Bearer-Token, Basic Auth, Custom Header)
  • _auth: Auth als Query-String — wird automatisch an jede URL angehängt

Credentials behandeln

API-Keys stehen direkt in apis.php:

'Authorization' => 'Bearer sk_live_abc123',

apis.php ist sensitiv. Sie enthält Secrets, die deinen Workspace mit echten Diensten verbinden. Halte die Datei aus öffentlichen Repos heraus. Nutze ein privates Git-Repo für deinen Workspace, oder schließe apis.php per .gitignore aus, wenn das Repo öffentlich ist.

Bei Key-Rotation: Wert in apis.php ersetzen, tm sync, fertig.

Tool definieren

'tools' => [
    'getRecentOrders' => [
        'description' => 'Letzte 5 Bestellungen aus dem Shop laden.',
        'parameters' => [
            'type' => 'object',
            'properties' => [
                'since' => [
                    'type' => 'string',
                    'description' => 'Datum YYYY-MM-DD oder "today"',
                ],
            ],
            'required' => ['since'],
        ],
        'api' => 'shop_api',
        'method' => 'GET',
        'path' => 'orders?limit=5&since={since}',
        'mapping' => [
            'orders' => [
                'id' => 'id',
                'customer' => 'customer.name',
                'total' => 'total',
                'status' => 'status',
            ],
        ],
    ],
];

POST-Requests mit Body

'createOrder' => [
    'description' => 'Neue Bestellung anlegen.',
    'parameters' => [
        'type' => 'object',
        'properties' => [
            'customerId' => ['type' => 'integer'],
            'items' => [
                'type' => 'array',
                'items' => [
                    'type' => 'object',
                    'properties' => [
                        'sku' => ['type' => 'string'],
                        'qty' => ['type' => 'integer'],
                    ],
                ],
            ],
        ],
        'required' => ['customerId', 'items'],
    ],
    'api' => 'shop_api',
    'method' => 'POST',
    'path' => 'orders',
    'body' => [
        'customer_id' => '{customerId}',
        'line_items' => '{items}',
    ],
    'mapping' => [
        'id' => 'id',
        'orderNumber' => 'number',
        'url' => 'admin_url',
    ],
];

Basic Auth

'old_api' => [
    'base_url' => 'https://old.example.com/api/',
    'headers' => [
        'Authorization' => 'Basic ' . base64_encode('user:passwort'),
    ],
],

Custom Header

Manche APIs wollen eigene Header — typisch für B2B-Systeme:

'internal_crm' => [
    'base_url' => 'https://crm.firma.intern/api/',
    'headers' => [
        'x-app-id' => 'TaskMonkey',
        'x-app-version' => '1.0',
        'x-api-key' => 'abc123…',
    ],
],

Response-Mapping

APIs geben oft deutlich mehr zurück, als du brauchst. mapping pickt die interessanten Felder raus:

'mapping' => [
    'total' => 'amounts.gross_total',
    'customerName' => 'billing.first_name',
    'line' => 'line_items[0].name',   // erstes Array-Element
    'items' => 'line_items',           // ganzes Array behalten
],

Ohne mapping bekommt das Modell den kompletten Response-JSON. Bei großen Responses frisst das Tokens und bringt selten Mehrwert.

Pre-/Postprocess für Spezialfälle

Wenn du den Request vor dem Absenden anpassen musst (z. B. Signatur berechnen, Datum formatieren):

'preprocess' => function (array $args, array $ctx): array {
    $args['date'] = (new \DateTime($args['date']))->format('Y-m-d');
    return $args;
},

Debug

# Request + Response live ansehen
tm test-tool getRecentOrders since=today

# Logs mit vollem HTTP-Dump
tm logs --lines 200

Wenn ein externer Dienst 500 zurückgibt, liegt es meistens nicht an TaskMonkey, sondern am Dienst. tm logs zeigt die rohe Response — das kannst du in der Regel direkt an den Betreiber dieses Dienstes weiterreichen.

Zuletzt aktualisiert: 2026-04-19