Kurzlinks und Geheimnisse, direkt aus Ihrem Code.
Ein Bearer-Schlüssel, einfaches JSON und dieselben Tarifregeln wie im Dashboard. Gebaut für Browser-Erweiterungen, CLIs, MCP-Server und interne Tools.
Früher Zugang. Wir schalten die v1-Endpunkte Workspace für Workspace frei. Gibt ein Aufruf 503 mit dem Code disabled zurück, ist die API für Sie noch nicht freigeschaltet. Schlüssel können Sie schon heute erstellen. Sie funktionieren, sobald die API für Ihren Workspace freigeschaltet ist.
Client-Bibliotheken
Geheimnisse werden verschlüsselt, bevor sie gesendet werden. Jeder Client muss diesen Teil also selbst erledigen. Diese Bibliotheken tun es einmal und richtig, geprüft gegen dieselben im Repository hinterlegten Testvektoren wie die Web-App. Alle drei stehen unter der MIT-Lizenz, werden aus der CI mit npm-Provenance veröffentlicht und hängen nur von der Standardbibliothek ab.
TypeScript-SDK
npmTypisierter Client für jede Route. Ohne Abhängigkeiten, nur WebCrypto, daher läuft er unverändert unter Node 20+, Deno, Bun, in Browsern und in Edge-Runtimes.
npm i @uselinkpilot/sdkKommandozeile
npmLeiten Sie ein Geheimnis per Pipe ein, statt es als Argument zu übergeben: Ein Argument landet in Ihrer Shell-History und ist in der Prozessliste sichtbar.
npm i -g linkpilot
echo 'db password: hunter2' | linkpilot secret --ttl 1hMCP-Server
npmDamit kann ein KI-Assistent jemandem Zugangsdaten übergeben, ohne dass sie in einem Chatverlauf stehen. Fügen Sie dies in Claude Desktop, Claude Code, Cursor oder einem anderen MCP-Client hinzu:
{
"mcpServers": {
"linkpilot": {
"command": "npx",
"args": ["-y", "@uselinkpilot/mcp"],
"env": { "LINKPILOT_API_KEY": "lp_live_..." }
}
}
}Das sollten Sie vor der Installation wissen: Der Klartext läuft durch den Kontext des Assistenten, denn das Modell muss ein Geheimnis sehen, um einen Link dafür zu erstellen. Der Server schützt es bei der Übertragung, im Ruhezustand und dadurch, dass es sich nur einmal öffnen lässt. Vor dem Modell selbst kann er es nicht verbergen.
Quellcode: linkpilot-cli (SDK und CLI) und linkpilot-mcp.
1. Authentifizierung
Erstellen Sie einen Schlüssel unter /app/api-keys (Workspace-Inhaber und Admins). Der vollständige Schlüssel wird einmal angezeigt; LinkPilot speichert nur seinen SHA-256-Hash. Senden Sie ihn bei jeder Anfrage mit:
Authorization: Bearer lp_live_...Schlüssel gehören zu einem Workspace, deshalb gibt es nirgends einen Mandanten-Parameter. Widerrufene, abgelaufene, unbekannte und fehlerhafte Schlüssel liefern alle dasselbe 401 unauthorized. Schlüssel landen nie in Logs.
Basis-URL: https://khiydxamyihofmtmgvjz.supabase.co/functions/v1/api-v1
2. Routen
| Methode | Pfad | Funktion |
|---|---|---|
| GET | /me | Workspace, Tarif, Limits, Nutzung und das Anfragebudget Ihres Schlüssels |
| POST | /links | Kurzlink erstellen (url, optional slug, domain, title, tags) |
| GET | /links | Links auflisten, neueste zuerst, mit Cursor-Paginierung |
| GET | /links/{id} | Einen Link abrufen |
| DELETE | /links/{id} | Einen Link löschen |
| POST | /secrets | Secret-Link erstellen (ciphertext, enc_version, ttl_seconds, burn_after_read, passphrase_hash ab Pro) |
| GET | /secrets | Metadaten der Geheimnisse auflisten (nie die Inhalte) |
| DELETE | /secrets/{id} | Ein Geheimnis widerrufen und seinen Inhalt vernichten |
| POST | /public/links | Anonymen Link mit einer client_id erstellen, ohne Schlüssel |
| POST | /public/secrets | Anonymes Geheimnis mit Löschen nach dem Lesen erstellen, ohne Schlüssel |
Listen liefern { data, next_cursor }. Geben Sie next_cursor als cursor zurück, um weiterzublättern. limit liegt zwischen 1 und 100.
3. Beispiele
Einen Link mit curl erstellen
curl -X POST "https://khiydxamyihofmtmgvjz.supabase.co/functions/v1/api-v1/links" \
-H "Authorization: Bearer $LINKPILOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/launch","slug":"launch","tags":["campaign"]}'Ein Geheimnis mit JavaScript erstellen
const b64u = (b) => btoa(String.fromCharCode(...new Uint8Array(b)))
.replace(/+/g, "-").replace(///g, "_").replace(/=+$/, "");
// 1. Encrypt locally. This key is generated here and never sent anywhere.
const key = crypto.getRandomValues(new Uint8Array(32));
const iv = crypto.getRandomValues(new Uint8Array(12));
const k = await crypto.subtle.importKey("raw", key, "AES-GCM", false, ["encrypt"]);
const ct = await crypto.subtle.encrypt(
{ name: "AES-GCM", iv, tagLength: 128 },
k,
new TextEncoder().encode("staging db password"),
);
const ciphertext = `v1.${b64u(iv)}.${b64u(ct)}`;
// 2. Store the blob. LinkPilot cannot read it.
const res = await fetch("https://khiydxamyihofmtmgvjz.supabase.co/functions/v1/api-v1/secrets", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.LINKPILOT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ ciphertext, enc_version: 1, ttl_seconds: 3600 }),
});
if (!res.ok) throw new Error((await res.json()).error.code);
const { secret_url } = await res.json();
// 3. Attach the key. Without this the link can never be opened, by anyone.
const shareUrl = `${secret_url}#k=${b64u(key)}`;Links mit Python auflisten
import os, requests
r = requests.get(
"https://khiydxamyihofmtmgvjz.supabase.co/functions/v1/api-v1/links",
params={"limit": 20},
headers={"Authorization": f"Bearer {os.environ['LINKPILOT_API_KEY']}"},
)
r.raise_for_status()
for link in r.json()["data"]:
print(link["short_url"], "->", link["url"])
print("remaining this hour:", r.headers["X-RateLimit-Remaining"])Einen anonymen Link ohne Schlüssel erstellen
curl -X POST "https://khiydxamyihofmtmgvjz.supabase.co/functions/v1/api-v1/public/links" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com","client_id":"my-cli-0123456789abcdef"}'Der formale Vertrag wird hier veröffentlicht, nicht in einem Repository: OpenAPI-3.1-Dokument, Postman-Collection und die schriftliche Referenz. Richten Sie Ihren Codegenerator direkt auf die OpenAPI-URL.
4. Wie Geheimnisse gespeichert werden
Hier wollen wir genau sein, denn ein API-Client hat an dieser Stelle echte Arbeit zu leisten: Die API nimmt ein payload im Klartext überhaupt nicht an.
- Sie verschlüsseln, wir speichern einen Blob. Senden Sie
ciphertext(AES-GCM-256,v1.<iv>.<ct>) mitenc_version: 1. Ein gesendetespayloadwird abgelehnt, nicht stillschweigend angenommen. - Den Schlüssel hängen Sie selbst an. Die
secret_url, die wir zurückgeben, enthält keinen Schlüssel und kann keinen enthalten: Wir haben ihn nie gesehen. Hängen Sie#k=<base64url key>an. Browser übertragen den Teil des Links nach dem#nie, deshalb entschlüsselt der Empfänger lokal. - Es gibt keine Wiederherstellung. Ist der Schlüssel verloren, ist das Geheimnis weg, für Sie und für uns. Genau so funktioniert die Garantie.
- Vernichtet beim Löschen nach dem Lesen, bei Ablauf oder Widerruf. Der gespeicherte Geheimtext wird auf dem Server überschrieben.
- Die API gibt ihn nie zurück. Keine Route liefert einen Inhalt oder Geheimtext aus. Lesen kann ihn nur die Anzeigeseite des Empfängers, und sie protokolliert den Aufruf.
- Passphrasen (ab Pro) sind ein echter zweiter Faktor: Sie werden mit PBKDF2-SHA256 gestreckt und per HKDF in den Schlüssel eingerechnet, sodass weder der Link allein noch die Passphrase allein entschlüsselt. Senden Sie nur
passphrase_hash, den SHA-256-Hex-Wert der NFKC-normalisierten Passphrase, niemals die Passphrase selbst, denn sie ist die Hälfte des Schlüssels. Leiten Sie den Schlüssel aus derselben NFKC-Form ab, damit eine auf einer anderen Tastatur eingegebene Passphrase das Geheimnis trotzdem öffnet. - Was das nicht abdeckt. Wer den vollständigen Link hat, hat den Schlüssel. Kurze Ablaufzeiten und Löschen nach dem Lesen bleiben deshalb wichtig. Dateianhänge werden genauso verschlüsselt, mit einem Schlüssel, der aus demselben Link abgeleitet ist.
Das Übertragungsformat ist in der API-Referenz spezifiziert, und @uselinkpilot/sdk erledigt den gesamten Austausch mit einem Aufruf, wenn Sie ihn nicht selbst implementieren wollen. Dasselbe Modell beschreibt die Seite zur Sicherheitsarchitektur.
5. Tarif-Limits und Rate-Limits
| Limit | Free | Pro | Agency |
|---|---|---|---|
| Links | 50 | Unbegrenzt | Unbegrenzt |
| Aktive Geheimnisse | 5 | 100 | 100 |
| Geheimnisse mit Passphrase | Nein | Ja | Ja |
| Eigene Domains für Links | Bereits verifizierte Domains | Bis zu 5 | Unbegrenzt |
| Anfragen pro Schlüssel und Stunde | 60 | 1.000 | 5.000 |
Die API wendet dieselben Tarifregeln an wie das Dashboard und liest sie aus derselben Quelle. Eine Agentur-Bündelung gilt also auch hier. GET /me liefert die aktuellen Werte für Ihren Workspace. Jede authentifizierte Antwort enthält X-RateLimit-Limit, X-RateLimit-Remaining und X-RateLimit-Reset.
6. Öffentliche Routen ohne Schlüssel
POST /public/links und POST /public/secrets gibt es für Clients, die keine Browser-Prüfung anzeigen können: CLIs, MCP-Server, den Launcher. Sie erwarten eine opake client_id (16 bis 64 Zeichen, einmal pro Installation erzeugt) und legen Einträge im selben anonymen Pool an wie die kostenlosen Web-Tools.
- 20 Erstellungen pro Client und Tag und 60 pro Netzwerk und Stunde, dazu die eigenen Netzwerk-Limits des Pools.
- Dieselbe Prüfung gegen Bedrohungs-Feeds, dieselbe Google-Abfrage zu gefährlichen URLs und dieselben geplanten Nachprüfungen wie bei jedem anderen Weg, Links zu erstellen.
- Keine eigene Domain, kein eigenes Kürzel, keine Passphrase. Öffentliche Geheimnisse werden immer nach einmaligem Lesen gelöscht und laufen innerhalb von 24 Stunden ab.
- Die Antwort enthält ein
claim_token, mit dem ein angemeldeter Nutzer den Eintrag später in einen Workspace übernehmen kann. Behandeln Sie es wie Zugangsdaten.
7. Fehler
Jeder Fehler hat die Form { "error": { "code", "message", "upgrade_url"? } }. Meldungen nennen das Feld, nie Ihre Daten. Ressourcen in anderen Workspaces ergeben 404, nicht 403.
| Code | HTTP | Wann |
|---|---|---|
| unauthorized | 401 | Schlüssel fehlt, ist fehlerhaft, unbekannt, widerrufen oder abgelaufen |
| disabled | 503 | Die API ist für diese Instanz noch nicht freigeschaltet |
| invalid_request | 400 | Validierungsfehler, gesperrtes Ziel, vergebenes Kürzel, unbekannte Domain |
| not_found | 404 | Route existiert nicht, oder die Ressource gehört nicht zu Ihrem Workspace |
| plan_limit | 402 | Kontingent für Links oder aktive Geheimnisse erreicht (mit upgrade_url) |
| pro_required | 402 | Passphrase in einem Tarif, der sie nicht enthält (mit upgrade_url) |
| rate_limited | 429 | Stundenbudget des Schlüssels oder öffentliches Kontingent aufgebraucht (mit Retry-After) |
Häufige Fragen von Entwicklern
- Welche Tarife enthalten die API?
- API-Schlüssel erstellen Sie im Dashboard unter /app/api-keys. Jeder Schlüssel nutzt die Tarif-Limits seines Workspace: Free bietet 50 Links und 5 aktive Geheimnisse bei 60 Anfragen pro Stunde. Pro hat unbegrenzte Links, 100 aktive Geheimnisse, Geheimnisse mit Passphrase-Schutz und 1.000 Anfragen pro Stunde. Agency-Tarife erhalten 5.000 Anfragen pro Stunde.
- Sind die Inhalte von Geheimnissen Ende-zu-Ende-verschlüsselt?
- Ja, und die API nimmt Klartext überhaupt nicht an. Sie verschlüsseln mit AES-GCM-256 und senden den Geheimtext. LinkPilot speichert einen Blob, für den es keinen Schlüssel hat und den es nicht entschlüsseln kann. Weil wir Ihren Schlüssel nie sehen, enthält die secret_url, die wir zurückgeben, keinen Schlüssel. Sie hängen ihn selbst als Fragment #k= an, und Browser übertragen diesen Teil nie. Ist der Schlüssel verloren, kann niemand das Geheimnis wiederherstellen, auch wir nicht. Dateianhänge werden genauso verschlüsselt, mit einem Schlüssel, der aus demselben Link abgeleitet ist.
- Kann ich Links ohne API-Schlüssel erstellen?
- Ja. POST /public/links und POST /public/secrets erwarten statt eines Schlüssels eine opake client_id und legen Einträge im selben anonymen Pool an wie die kostenlosen Web-Tools: 20 Erstellungen pro Client und Tag, 60 pro Netzwerk und Stunde, keine eigene Domain, keine Passphrase, und Geheimnisse laufen innerhalb von 24 Stunden ab.
- Was passiert, wenn ich ein Limit erreiche?
- Tarif-Limits liefern HTTP 402 mit dem Code plan_limit oder pro_required und einer upgrade_url. Rate-Limits liefern 429 mit einem Retry-After-Header. Jede authentifizierte Antwort enthält X-RateLimit-Limit, X-RateLimit-Remaining und X-RateLimit-Reset, damit Clients rechtzeitig drosseln können.
- Ist die API stabil?
- Die v1-Routen ändern sich nicht inkompatibel. Inkompatible Änderungen erscheinen als neue Version. Während des frühen Zugangs schalten wir die Endpunkte Workspace für Workspace frei. Eine 503-Antwort mit dem Code disabled bedeutet, dass die API für Ihren Workspace noch nicht freigeschaltet ist.
Bereit zum Entwickeln?
Erstellen Sie einen Schlüssel in Ihrem Workspace, oder starten Sie mit dem Free-Tarif.