Zurück zur App

DealFilter einbinden

Verbinde DealFilter mit Claude, Codex oder einem eigenen Skript - per MCP-Server, REST API oder CLI.

DealFilter API, MCP-Server und CLI

Verbinde DealFilter mit Claude, Codex oder einem eigenen Skript. Voraussetzung: Premium- oder Ultra-Plan + API-Key (df_... - generierbar unter Einstellungen > API-Zugang).

PlanAbrufen, Auflisten, KontingentEinreichenPhase ändern
Essential---
Premium--
Ultra (in Planung)

Inhaltsverzeichnis

  1. Authentifizierung und Key-Verwaltung
  2. REST API v1
  3. MCP-Server
  4. OAuth-Connector und Token-Verwaltung
  5. CLI
  6. Fehler-Referenz
  7. Async-Vertrag: Einreichen und Polling

Authentifizierung

DealFilter kennt zwei Arten von Zugangstoken:

TokenPrefixHerkunftVerwendung
Persönlicher API-Keydf_Manuell unter Einstellungen > API-Zugang erstelltREST API, MCP-Server, CLI, eigene Skripte
OAuth-Connector-Tokendfo_Automatisch beim Verbinden eines MCP-Clients (z. B. Claude.ai)MCP-Server über den Connector-Flow

Beide werden ausschließlich gehasht gespeichert und im selben Authorization-Header verwendet.

API-Key generieren

Settings > API-Zugang (ab Premium sichtbar). Der Key wird einmalig im Klartext angezeigt. Format: df_ + 43 Zeichen (Base64url).

Gültigkeitsdauer wählen

Beim Erstellen wählst du die Gültigkeit: 30 Tage, 90 Tage (Standard), 1 Jahr oder unbegrenzt. Nach Ablauf wird der Key abgelehnt (401) - erstelle dann unter Einstellungen > API-Zugang einen neuen. Auf der Seite siehst du Ablaufdatum und einen Hinweis, sobald ein Key abgelaufen ist.

Key erneuern oder widerrufen

  • Erneuern: "Neu erstellen" erzeugt einen frischen Key und macht den alten sofort ungültig.
  • Widerrufen: "Widerrufen" macht den Key sofort ungültig, ohne einen neuen zu erstellen.

Key in Requests mitgeben

Authorization: Bearer df_<key>

Gilt für REST API, MCP-Server und CLI.


REST API v1

Base URL: https://dealfilter.ai Prefix: /api/v1


POST /api/v1/applications Ultra (in Planung) — Anfrage einreichen

Reicht eine neue Anfrage zur KI-Analyse ein. Verbraucht 1 Credit. Die Analyse läuft asynchron - die Response enthält sofort status: "analyzing".

Request

POST /api/v1/applications
Authorization: Bearer df_<key>
Content-Type: application/json

{
  "mailText": "Betreff: Senior Java Developer gesucht\n\nHallo,\n...",
  "channel": "EMAIL",
  "agentId": "cm1abc123",
  "newAgentName": "SOLCOM GmbH"
}
FeldTypPflichtBeschreibung
mailTextstring (min 10)jaVollständiger Text der Anfrage
channelEMAIL|PORTAL|PHONE|SEARCH_AGENTneinStandard: EMAIL
agentIdstringneinID eines bestehenden Recruiters
newAgentNamestringneinName eines neuen Recruiters (alternativ zu agentId)

Response 202

{
  "applicationId": "cmq0go2ib000a1h9kn8dno71t",
  "status": "analyzing"
}

Analyse-Status abrufen: GET /api/v1/applications/{applicationId} nach 30-60 Sekunden.


GET /api/v1/applications Premium Ultra (in Planung) — Anfragen auflisten

GET /api/v1/applications?active=true&limit=20&offset=0
Authorization: Bearer df_<key>

Query-Parameter

ParameterTypDefaultBeschreibung
phasestring-Exakter Phase-Filter (s. u.)
activetrue|false-true = nicht archiviert, false = nur ARCHIVED
limitint (1-100)50Anzahl Ergebnisse
offsetint0Offset für Paginierung

phase und active schliessen sich aus - phase hat Vorrang.

Phasen-Werte: INCOMING, APPLIED, PROFILE_AT_CLIENT, WON, CONTRACT_SIGNED, ARCHIVED

Response 200

{
  "items": [
    {
      "id": "cmq0go2ib000a1h9kn8dno71t",
      "status": "INCOMING",
      "channel": "PORTAL",
      "projectTitle": "Senior Software Engineer - Microservices",
      "agentName": "SOLCOM",
      "analysisStatus": "done",
      "scoreLabel": "GREEN",
      "scorePercent": 88,
      "createdAt": "2026-06-05T05:05:47.699Z",
      "lastContactAt": "2026-06-05T05:07:49.699Z"
    }
  ],
  "total": 32,
  "limit": 20,
  "offset": 0
}

GET /api/v1/applications/ Premium Ultra (in Planung) — Einzelne Anfrage abrufen

GET /api/v1/applications/cmq0go2ib000a1h9kn8dno71t
Authorization: Bearer df_<key>

Response 200

{
  "id": "cmq0go2ib000a1h9kn8dno71t",
  "status": "INCOMING",
  "channel": "PORTAL",
  "analysisStatus": "done",
  "scoreLabel": "GREEN",
  "scorePercent": 88,
  "matchScore": {
    "techFit": 90,
    "rateFit": 85,
    "locationFit": 80
  },
  "redFlags": ["Keine Remote-Option erwähnt"],
  "hints": ["Java 17+", "Microservices", "Kubernetes"],
  "aiSummary": "Solides Java-Projekt bei einem Endkunden im Finanzbereich...",
  "createdAt": "2026-06-05T05:05:47.699Z",
  "lastContactAt": "2026-06-05T05:07:49.699Z",
  "originalMail": "Betreff: Senior Software Engineer...",
  "project": {
    "title": "Senior Software Engineer - Microservices",
    "description": "...",
    "location": "Frankfurt",
    "remotePercentMin": 60,
    "remotePercentMax": 80,
    "durationMonthsMin": 6,
    "durationMonthsMax": 12,
    "startDate": "2026-07-01T00:00:00.000Z"
  },
  "agentName": "SOLCOM",
  "communicationLog": [
    {
      "id": "cm2xyz456",
      "date": "2026-06-06T10:00:00.000Z",
      "type": "PHONE",
      "direction": "INBOUND",
      "contactSuccessful": true,
      "note": "Telefonat mit Recruiter - Rate verhandelt"
    }
  ]
}

analysisStatus-Werte:

WertBedeutung
analyzingAnalyse läuft noch - später erneut abfragen
doneScore, redFlags, hints und aiSummary verfügbar
failedAnalyse endgültig fehlgeschlagen (max. Retries)

PATCH /api/v1/applications/ Ultra (in Planung) — Phase ändern

Kein Credit-Verbrauch.

PATCH /api/v1/applications/cmq0go2ib000a1h9kn8dno71t
Authorization: Bearer df_<key>
Content-Type: application/json

{
  "status": "APPLIED"
}

Response 200

{
  "id": "cmq0go2ib000a1h9kn8dno71t",
  "status": "APPLIED"
}

GET /api/v1/quota Premium Ultra (in Planung) — Kontingent abfragen

GET /api/v1/quota
Authorization: Bearer df_<key>

Response 200

{
  "used": 44,
  "limit": 500,
  "remaining": 456,
  "resetAt": "2026-07-01T00:00:00.000Z"
}

MCP-Server

Endpoint: POST https://dealfilter.ai/api/mcp Transport: StreamableHTTP (stateless, kein Session-Management) Protokoll: MCP 2024-11-05

Konfiguration in Claude Code

Einstellungen - MCP-Server - Server hinzufügen:

{
  "name": "dealfilter",
  "url": "https://dealfilter.ai/api/mcp",
  "headers": {
    "Authorization": "Bearer df_<key>"
  }
}

Konfiguration in Claude.ai, OpenAI Codex und kompatiblen Clients

Alle MCP-kompatiblen Clients (Claude.ai, OpenAI Codex, Cursor u.a.) verwenden das mcpServers-Format:

{
  "mcpServers": {
    "dealfilter": {
      "url": "https://dealfilter.ai/api/mcp",
      "headers": {
        "Authorization": "Bearer df_<key>"
      }
    }
  }
}

MCP-Protokoll: initialize

POST /api/mcp
Authorization: Bearer df_<key>
Content-Type: application/json
Accept: application/json, text/event-stream

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "capabilities": {},
    "clientInfo": { "name": "claude-code", "version": "1.0" }
  }
}

Response (SSE)

event: message
data: {"result":{"protocolVersion":"2024-11-05","capabilities":{"tools":{"listChanged":true}},"serverInfo":{"name":"dealfilter","version":"1.0.0"}},"jsonrpc":"2.0","id":1}

MCP-Protokoll: tools/list

POST /api/mcp
Authorization: Bearer df_<key>
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list",
  "params": {}
}

Response (Ausschnitt)

{
  "result": {
    "tools": [
      { "name": "submit_inquiry",  "description": "... (async, Polling erforderlich)" },
      { "name": "list_inquiries",  "description": "..." },
      { "name": "get_inquiry",     "description": "..." },
      { "name": "change_phase",    "description": "..." },
      { "name": "get_quota",       "description": "..." }
    ]
  }
}

MCP-Tools im Detail


submit_inquiry Ultra (in Planung)

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "submit_inquiry",
    "arguments": {
      "mailText": "Betreff: Java Entwickler für 6 Monate\n\nHallo...",
      "channel": "EMAIL",
      "newAgentName": "Hays AG"
    }
  }
}

Response

{
  "result": {
    "content": [{ "type": "text", "text": "{\"applicationId\":\"cmq0xyz123\",\"status\":\"analyzing\"}" }],
    "isError": false
  }
}

Warte 30-60 Sekunden, dann get_inquiry mit der applicationId aufrufen.


list_inquiries Premium Ultra (in Planung)

{
  "method": "tools/call",
  "params": {
    "name": "list_inquiries",
    "arguments": { "active": "true", "limit": 10, "offset": 0 }
  }
}

get_inquiry Premium Ultra (in Planung)

{
  "method": "tools/call",
  "params": {
    "name": "get_inquiry",
    "arguments": { "id": "cmq0go2ib000a1h9kn8dno71t" }
  }
}

Wenn analysisStatus = "analyzing": erneut abfragen. Wenn "done": scoreLabel, scorePercent, redFlags, hints, aiSummary auswerten.


change_phase Ultra (in Planung)

{
  "method": "tools/call",
  "params": {
    "name": "change_phase",
    "arguments": { "id": "cmq0go2ib000a1h9kn8dno71t", "status": "APPLIED" }
  }
}

get_quota Premium Ultra (in Planung)

{
  "method": "tools/call",
  "params": {
    "name": "get_quota",
    "arguments": {}
  }
}

OAuth-Connector

MCP-Clients wie Claude.ai verbinden sich nicht über einen manuell eingefügten df_-Key, sondern über einen standardkonformen OAuth-2.0-Flow (RFC 6749 mit PKCE S256). Dabei stellt DealFilter ein dfo_-Token aus, das im Hintergrund verwaltet wird.

Discovery

DealFilter veröffentlicht die Metadaten nach RFC 8414 und RFC 9728:

GET /.well-known/oauth-authorization-server
GET /.well-known/oauth-protected-resource

Die Authorization-Server-Metadaten nennen alle Endpunkte:

{
  "issuer": "https://dealfilter.ai",
  "authorization_endpoint": "https://dealfilter.ai/api/oauth/authorize",
  "token_endpoint": "https://dealfilter.ai/api/oauth/token",
  "registration_endpoint": "https://dealfilter.ai/api/oauth/register",
  "revocation_endpoint": "https://dealfilter.ai/api/oauth/revoke",
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code"],
  "code_challenge_methods_supported": ["S256"],
  "token_endpoint_auth_methods_supported": ["none"]
}

Ablauf

  1. Client-Registrierung (POST /api/oauth/register): Der Client registriert sich dynamisch mit redirect_uris (nur HTTPS, außer localhost) und erhält eine client_id.
  2. Autorisierung (GET /api/oauth/authorize): Der User meldet sich an und bestätigt den Zugriff auf einer Zustimmungsseite. PKCE mit code_challenge_method=S256 ist Pflicht.
  3. Token-Tausch (POST /api/oauth/token): Der Client tauscht den code plus code_verifier gegen ein dfo_-Token.
{
  "access_token": "dfo_...",
  "token_type": "Bearer",
  "expires_in": 7776000
}

Token-Ablauf und Erneuerung

dfo_-Tokens laufen nach 90 Tagen ab (expires_in in Sekunden). Refresh-Tokens gibt es bewusst nicht: Läuft das Token ab, startet der MCP-Client beim nächsten 401 automatisch den Connector-Flow erneut und holt sich ein frisches Token - ohne manuelles Zutun.

Verbindung beenden

Zwei Wege:

  • In der App: Einstellungen > API-Zugang > Verbundene Apps > "Beenden". Die App verliert sofort den Zugriff.
  • Per Endpunkt (RFC 7009): Der Client widerruft sein eigenes Token.
POST /api/oauth/revoke
Content-Type: application/json

{ "token": "dfo_<token>" }

Antwort ist immer 200, auch bei unbekanntem Token (gemäß RFC 7009).


CLI

Voraussetzung: Node.js 18+

Installation

# Einmalig global installieren (empfohlen)
npm install -g @dealfilter/cli

# Oder direkt ohne Installation via npx
npx @dealfilter/cli <subkommando>

Konfiguration

Option 1 - Env-Variable (empfohlen für CI/Skripte):

export DEALFILTER_API_KEY=df_<key>
export DEALFILTER_BASE_URL=https://dealfilter.ai  # optional

Option 2 - Config-Datei ~/.dealfilter.json:

{
  "apiKey": "df_<key>",
  "baseUrl": "https://dealfilter.ai"
}

Priorität: Env-Variable > Config-Datei. baseUrl ist optional (Standard: https://dealfilter.ai).


submit Ultra (in Planung) — Anfrage einreichen

# Text als Argument
dealfilter submit "Hallo, wir suchen einen Java-Entwickler für 6 Monate..."

# Text aus Datei
dealfilter submit --file=/tmp/anfrage.txt

# Text aus stdin (Pipeline)
cat anfrage.txt | dealfilter submit
pbpaste | dealfilter submit --channel=EMAIL --agent="Hays AG"

Optionen:

FlagWerteBeschreibung
--file=<pfad>DateipfadText aus Datei lesen
--channel=<wert>EMAIL|PORTAL|PHONE|SEARCH_AGENTStandard: EMAIL
--agent=<name>stringNeuer Recruiter-Name
--agentId=<id>stringBestehender Recruiter-ID

Ausgabe:

{ "applicationId": "cmq0xyz123", "status": "analyzing" }

list Premium Ultra (in Planung) — Anfragen auflisten

dealfilter list --active=true       # alle aktiven
dealfilter list --phase=INCOMING    # nur INCOMING
dealfilter list --limit=5 --offset=10
dealfilter list --active=false      # archivierte

Optionen:

FlagWerteBeschreibung
--phase=<wert>Phase-EnumExakter Phase-Filter
--active=true|falsebooleanAktiv/archiviert Filter
--limit=<n>1-100Standard: 50
--offset=<n>intStandard: 0

Ausgabe:

{
  "items": [
    {
      "id": "cmq0go2ib000a1h9kn8dno71t",
      "status": "INCOMING",
      "channel": "PORTAL",
      "projectTitle": "Senior Software Engineer - Microservices",
      "agentName": "SOLCOM",
      "analysisStatus": "done",
      "scoreLabel": "GREEN",
      "scorePercent": 88,
      "createdAt": "2026-06-05T05:05:47.699Z",
      "lastContactAt": "2026-06-05T05:07:49.699Z"
    }
  ],
  "total": 32,
  "limit": 50,
  "offset": 0
}

get Premium Ultra (in Planung) — Einzelne Anfrage abrufen

dealfilter get cmq0go2ib000a1h9kn8dno71t

Ausgabe (analysisStatus = "done"):

{
  "id": "cmq0go2ib000a1h9kn8dno71t",
  "status": "INCOMING",
  "analysisStatus": "done",
  "scoreLabel": "GREEN",
  "scorePercent": 88,
  "redFlags": [],
  "hints": ["Java 17", "Kubernetes", "Remote 80%"],
  "aiSummary": "Solides Java-Projekt...",
  "project": {
    "title": "Senior Software Engineer - Microservices",
    "location": "Frankfurt",
    "remotePercentMin": 60,
    "remotePercentMax": 80,
    "durationMonthsMin": 6,
    "durationMonthsMax": 12
  },
  "agentName": "SOLCOM",
  "communicationLog": []
}

Ausgabe (Analyse noch laufend):

{
  "id": "cmq0xyz123",
  "analysisStatus": "analyzing",
  "scoreLabel": null,
  "scorePercent": null,
  "redFlags": null,
  "hints": null,
  "aiSummary": null
}

phase Ultra (in Planung) — Phase ändern

dealfilter phase cmq0go2ib000a1h9kn8dno71t APPLIED

Gültige Phasen: INCOMING > APPLIED > PROFILE_AT_CLIENT > WON / CONTRACT_SIGNED > ARCHIVED

Ausgabe:

{ "id": "cmq0go2ib000a1h9kn8dno71t", "status": "APPLIED" }

quota Premium Ultra (in Planung) — Kontingent abfragen

dealfilter quota

Ausgabe:

{
  "used": 44,
  "limit": 500,
  "remaining": 456,
  "resetAt": "2026-07-01T00:00:00.000Z"
}

Fehler-Referenz

HTTP-Statuserror-WertBeschreibung
401unauthorizedKein oder ungültiger Bearer-Token
403api.read requires Premium plan or higherAbrufen: kein Premium oder höher
403api.write requires Ultra planEinreichen/Phase ändern: kein Ultra
400invalid_idUngültige applicationId
400validation_errorPflichtfelder fehlen oder falsche Typen
400invalid_jsonRequest-Body kein gültiges JSON
404not_foundAnfrage nicht gefunden (oder gehört anderem User)
429quota_exceededCredit-Limit erreicht
429rate_limit_exceededZu viele Requests in kurzer Zeit

quota_exceeded-Response:

{
  "error": "quota_exceeded",
  "remaining": 0,
  "limit": 500,
  "used": 500
}

Async-Vertrag

submit_inquiry / POST /api/v1/applications folgt einem Fire-and-Poll-Muster:

1. POST /api/v1/applications   →  202 { applicationId, status: "analyzing" }
2. Warte 30-60 Sekunden
3. GET /api/v1/applications/{id}
   → analysisStatus: "analyzing"  →  nochmal warten und wiederholen
   → analysisStatus: "done"       →  Ergebnis verfügbar
   → analysisStatus: "failed"     →  Analyse endgültig fehlgeschlagen

Für AI-Agenten: Einen Tool-Call für submit_inquiry als abgeschlossen werten bedeutet NICHT, dass das Ergebnis vorliegt. Nach dem Submit immer mit get_inquiry pollen bis analysisStatus != "analyzing". Niemals ein leeres scoreLabel als fertiges Ergebnis interpretieren.

Empfohlenes Polling-Intervall: 30 Sekunden, max. 5 Versuche (Analyse dauert typisch 10-30s nach dem Submit).