---
title: "API LinkPilot pour développeurs | Liens courts et secrets"
url: https://uselinkpilot.com/fr/developers
description: "Liens courts et secrets détruits après lecture, depuis votre code : API REST par clé, limites du forfait, routes sans clé pour CLI, spec OpenAPI 3.1."
lang: fr
---

API d’intégration v1

# Liens courts et secrets, depuis votre code.

Une seule clé bearer, du JSON simple et les mêmes règles de forfait que le tableau de bord. Conçue pour les extensions, les CLI, les serveurs MCP et les outils internes.

Créer une clé API: https://uselinkpilot.com/app/api-keys
Spécification OpenAPI: https://uselinkpilot.com/openapi.yaml?v=20261002

**Accès anticipé.** Les routes v1 sont activées espace de travail par espace de travail. Si un appel renvoie `503` avec le code `disabled`, l’API n’est pas encore activée pour vous. Vous pouvez déjà créer des clés: elles fonctionneront dès l’activation.

## Bibliothèques clientes

Les secrets sont chiffrés avant l’envoi, donc chaque client doit s’en charger lui-même. Ces bibliothèques l’implémentent une fois, correctement, et sont testées sur les mêmes vecteurs de test versionnés que l’application web. Toutes les trois sont sous licence MIT, publiées depuis la CI avec la provenance npm, et ne dépendent que de la bibliothèque standard.

### SDK TypeScript

npm (https://www.npmjs.com/package/@uselinkpilot/sdk)

Un client typé pour chaque route. Aucune dépendance, uniquement WebCrypto: il fonctionne tel quel sous Node 20+, Deno et Bun, dans les navigateurs et sur les runtimes de périphérie.

```
npm i @uselinkpilot/sdk
```

### Ligne de commande

npm (https://www.npmjs.com/package/linkpilot)

Transmettez le secret par un pipe plutôt qu’en argument: un argument finit dans l’historique du shell et reste visible dans la liste des processus.

```
npm i -g linkpilot
echo 'db password: hunter2' | linkpilot secret --ttl 1h
```

### Serveur MCP

npm (https://www.npmjs.com/package/@uselinkpilot/mcp)

Permet à un assistant IA de transmettre des identifiants à quelqu’un sans les laisser dans un historique de conversation. Ajoutez ceci à Claude Desktop, Claude Code, Cursor ou tout autre client MCP:

```
{
  "mcpServers": {
    "linkpilot": {
      "command": "npx",
      "args": ["-y", "@uselinkpilot/mcp"],
      "env": { "LINKPILOT_API_KEY": "lp_live_..." }
    }
  }
}
```

À savoir avant de l’installer: le texte en clair passe par le contexte de l’assistant, car le modèle doit voir un secret pour pouvoir le créer. Le serveur le protège pendant le transfert, au repos et en limitant son ouverture à une seule fois. Il ne peut pas le cacher au modèle lui-même.

Code source: linkpilot-cli (https://github.com/TetraCoreHQ/linkpilot-cli) (SDK et CLI) et linkpilot-mcp (https://github.com/TetraCoreHQ/linkpilot-mcp).

## 1. Authentification

Créez une clé sur /app/api-keys (https://uselinkpilot.com/app/api-keys) (propriétaires et administrateurs de l’espace de travail). La clé brute n’est affichée qu’une fois; LinkPilot n’en conserve que le hash SHA-256. Envoyez-la à chaque requête:

```
Authorization: Bearer lp_live_...
```

Chaque clé est liée à un espace de travail, il n’existe donc aucun paramètre de locataire. Les clés révoquées, expirées, inconnues ou mal formées renvoient toutes la même erreur `401 unauthorized`. Les clés ne sont jamais écrites dans les journaux.

URL de base: `https://khiydxamyihofmtmgvjz.supabase.co/functions/v1/api-v1`

## 2. Routes

| Méthode | Chemin | Rôle |
| --- | --- | --- |
| GET | /me | Espace de travail, forfait, limites, consommation et quota de requêtes de votre clé |
| POST | /links | Créer un lien court (url, slug facultatif, domaine, titre, tags) |
| GET | /links | Lister les liens, du plus récent au plus ancien, avec pagination par curseur |
| GET | /links/{id} | Récupérer un lien |
| DELETE | /links/{id} | Supprimer un lien |
| POST | /secrets | Créer un lien secret (ciphertext, enc_version, ttl_seconds, burn_after_read, passphrase_hash avec Pro) |
| GET | /secrets | Lister les métadonnées des secrets (jamais leur contenu) |
| DELETE | /secrets/{id} | Révoquer un secret et détruire son contenu |
| POST | /public/links | Créer un lien anonyme avec un client_id, sans clé |
| POST | /public/secrets | Créer un secret anonyme détruit après lecture, sans clé |

Les listes renvoient `{ data, next_cursor }`; renvoyez `next_cursor` dans `cursor` pour continuer. `limit` va de 1 à 100.

## 3. Exemples

Créer un lien avec curl

```
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"]}'
```

Créer un secret en JavaScript

```
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)}`;
```

Lister les liens en Python

```
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"])
```

Créer un lien anonyme sans clé

```
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"}'
```

Le contrat formel est publié ici, pas dans un dépôt: document OpenAPI 3.1 (https://uselinkpilot.com/openapi.yaml?v=20261002), collection Postman (https://uselinkpilot.com/linkpilot-api-v1.postman_collection.json) et documentation de référence (https://uselinkpilot.com/docs/api-v1.md?v=20261002). Pointez directement votre générateur de code vers l’URL OpenAPI.

## 4. Comment les secrets sont stockés

Nous tenons à être précis, car un client API a ici un vrai travail à faire: l’API refuse purement et simplement un `payload` en clair.

- **Vous chiffrez, nous stockons un blob.** Envoyez `ciphertext` (AES-GCM-256, `v1.<iv>.<ct>`) avec `enc_version: 1`. Un envoi de `payload` est refusé, et non accepté en silence.
- **Vous devez ajouter la clé vous-même.** Le `secret_url` que nous renvoyons ne contient pas de clé, et ne peut pas en contenir, car nous n’en avons jamais vu aucune. Ajoutez `#k=<base64url key>`. Les navigateurs ne transmettent jamais la partie du lien située après le `#`, donc le destinataire déchiffre en local.
- **Aucune récupération possible.** Si la clé est perdue, le secret l’est aussi, pour vous comme pour nous. C’est la preuve que la garantie fonctionne.
- **Détruit après lecture, à l’expiration ou à la révocation.** Le texte chiffré stocké est écrasé côté serveur.
- **Jamais renvoyé par l’API.** Aucune route ne renvoie un contenu ou un texte chiffré. Seule la page d’affichage du destinataire le lit, et elle enregistre l’ouverture.
- **Les phrases de passe** (Pro et au-delà) sont un vrai second facteur: renforcées avec PBKDF2-SHA256 puis intégrées à la clé avec HKDF, si bien que ni le lien seul ni la phrase de passe seule ne permettent de déchiffrer. N’envoyez que `passphrase_hash`, le hash SHA-256 en hexadécimal de la phrase de passe normalisée en NFKC, jamais la phrase de passe brute, qui constitue la moitié de la clé. Dérivez la clé à partir de la même forme NFKC, pour qu’une phrase de passe saisie sur un autre clavier ouvre toujours le secret.
- **Ce que cela ne couvre pas.** Quiconque détient le lien complet détient la clé, donc une expiration courte et la destruction après lecture restent importantes. Les pièces jointes sont chiffrées de la même manière, avec une clé dérivée du même lien.

Le format d’échange est spécifié dans la référence de l’API, et `@uselinkpilot/sdk` effectue tout l’échange en un seul appel si vous préférez ne pas l’implémenter vous-même. Le même modèle est décrit sur la page architecture de sécurité (https://uselinkpilot.com/fr/security-architecture).

## 5. Limites des forfaits et limites de débit

| Limite | Free | Pro | Agency |
| --- | --- | --- | --- |
| Liens | 50 | Illimités | Illimités |
| Secrets actifs | 5 | 100 | 100 |
| Secrets protégés par phrase de passe | Non | Oui | Oui |
| Domaines personnalisés pour les liens | Domaines déjà vérifiés | Jusqu’à 5 | Illimités |
| Requêtes par clé et par heure | 60 | 1 000 | 5 000 |

L’API applique les mêmes règles de forfait que le tableau de bord, lues au même endroit, donc le regroupement des forfaits d’agence s’applique ici aussi. `GET /me` renvoie les valeurs en temps réel pour votre espace de travail. Chaque réponse authentifiée contient les en-têtes `X-RateLimit-Limit`, `X-RateLimit-Remaining` et `X-RateLimit-Reset`.

Comparer les forfaits: https://uselinkpilot.com/fr/pricing

## 6. Routes publiques sans clé

`POST /public/links` et `POST /public/secrets` existent pour les clients qui ne peuvent pas afficher de vérification dans un navigateur: les CLI, les serveurs MCP, le lanceur. Elles prennent un `client_id` opaque (de 16 à 64 caractères, généré une fois par installation) et créent des enregistrements dans le même pool anonyme que les outils web gratuits.

- 20 créations par client et par jour et 60 par réseau et par heure, en plus des plafonds propres au pool pour chaque réseau.
- Le même filtrage par flux de menaces, la même vérification des URL auprès de Google et les mêmes revérifications planifiées que pour toutes les autres voies de création.
- Pas de domaine personnalisé, pas de slug personnalisé, pas de phrase de passe; les secrets publics sont toujours détruits après une seule lecture et expirent dans les 24 heures.
- La réponse contient un `claim_token` qui permet à une personne connectée de revendiquer plus tard l’enregistrement, c’est-à-dire de le rattacher à un espace de travail. Traitez-le comme un identifiant de connexion.

## 7. Erreurs

Chaque erreur a la forme `{ "error": { "code", "message", "upgrade_url"? } }`. Les messages nomment le champ, jamais vos données. Une ressource d’un autre espace de travail renvoie une 404, pas une 403.

| Code | HTTP | Cas |
| --- | --- | --- |
| unauthorized | 401 | Clé absente, mal formée, inconnue, révoquée ou expirée |
| disabled | 503 | L’API n’est pas encore activée pour ce déploiement |
| invalid_request | 400 | Échec de validation, destination bloquée, slug déjà pris, domaine inconnu |
| not_found | 404 | Route inexistante, ou ressource hors de votre espace de travail |
| plan_limit | 402 | Quota de liens ou de secrets actifs atteint (upgrade_url inclus) |
| pro_required | 402 | Phrase de passe sur un forfait qui ne l’inclut pas (upgrade_url inclus) |
| rate_limited | 429 | Quota horaire de la clé ou allocation publique épuisés (Retry-After inclus) |

## Questions des développeurs

Quels forfaits incluent l’API?

Les clés API se créent depuis le tableau de bord, sur /app/api-keys. Chaque clé suit les limites du forfait de son espace de travail: le forfait Free est limité à 50 liens et 5 secrets actifs, avec 60 requêtes par heure; Pro offre des liens illimités, 100 secrets actifs, des secrets protégés par phrase de passe et 1 000 requêtes par heure; les forfaits Agency ont droit à 5 000 requêtes par heure.

Le contenu des secrets est-il chiffré de bout en bout?

Oui, et l’API refuse purement et simplement le texte en clair. Vous chiffrez avec AES-GCM-256 et envoyez le texte chiffré; LinkPilot stocke un blob dont il n’a pas la clé et qu’il ne peut pas déchiffrer. Comme nous ne voyons jamais votre clé, le secret_url que nous renvoyons n’en contient pas. Vous l’ajoutez vous-même sous la forme d’un fragment #k=, que les navigateurs ne transmettent jamais. Si la clé est perdue, personne ne peut récupérer le secret, pas même nous. Les pièces jointes sont chiffrées de la même manière, avec une clé dérivée du même lien.

Puis-je créer des liens sans clé API?

Oui. POST /public/links et POST /public/secrets prennent un client_id opaque au lieu d’une clé et créent des enregistrements dans le même pool anonyme que les outils web gratuits: 20 créations par client et par jour, 60 par réseau et par heure, pas de domaine personnalisé, pas de phrase de passe, et les secrets expirent dans les 24 heures.

Que se passe-t-il quand j’atteins une limite?

Les limites de forfait renvoient une erreur HTTP 402 avec le code plan_limit ou pro_required et une upgrade_url. Les limites de débit renvoient une erreur 429 avec un en-tête Retry-After. Chaque réponse authentifiée contient X-RateLimit-Limit, X-RateLimit-Remaining et X-RateLimit-Reset, pour que les clients puissent ralentir avant d’en arriver là.

L’API est-elle stable?

Les routes v1 ne changeront pas de manière incompatible. Tout changement incompatible sera publié dans une nouvelle version. Pendant l’accès anticipé, les routes sont activées espace de travail par espace de travail; une réponse 503 avec le code disabled signifie que l’API n’est pas encore activée pour votre espace de travail.

## Envie de commencer à développer?

Créez une clé dans votre espace de travail ou commencez avec le forfait Free.

Accéder aux clés API: https://uselinkpilot.com/app/api-keys
Créer un espace de travail gratuit: https://uselinkpilot.com/signup

## Structured data

```json
[
  {
    "@context": "https://schema.org",
    "@type": "FAQPage",
    "mainEntity": [
      {
        "@type": "Question",
        "name": "Quels forfaits incluent l’API ?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Les clés API se créent depuis le tableau de bord, sur /app/api-keys. Chaque clé suit les limites du forfait de son espace de travail : le forfait Free est limité à 50 liens et 5 secrets actifs, avec 60 requêtes par heure ; Pro offre des liens illimités, 100 secrets actifs, des secrets protégés par phrase de passe et 1 000 requêtes par heure ; les forfaits Agency ont droit à 5 000 requêtes par heure."
        }
      },
      {
        "@type": "Question",
        "name": "Le contenu des secrets est-il chiffré de bout en bout ?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Oui, et l’API refuse purement et simplement le texte en clair. Vous chiffrez avec AES-GCM-256 et envoyez le texte chiffré ; LinkPilot stocke un blob dont il n’a pas la clé et qu’il ne peut pas déchiffrer. Comme nous ne voyons jamais votre clé, le secret_url que nous renvoyons n’en contient pas. Vous l’ajoutez vous-même sous la forme d’un fragment #k=, que les navigateurs ne transmettent jamais. Si la clé est perdue, personne ne peut récupérer le secret, pas même nous. Les pièces jointes sont chiffrées de la même manière, avec une clé dérivée du même lien."
        }
      },
      {
        "@type": "Question",
        "name": "Puis-je créer des liens sans clé API ?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Oui. POST /public/links et POST /public/secrets prennent un client_id opaque au lieu d’une clé et créent des enregistrements dans le même pool anonyme que les outils web gratuits : 20 créations par client et par jour, 60 par réseau et par heure, pas de domaine personnalisé, pas de phrase de passe, et les secrets expirent dans les 24 heures."
        }
      },
      {
        "@type": "Question",
        "name": "Que se passe-t-il quand j’atteins une limite ?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Les limites de forfait renvoient une erreur HTTP 402 avec le code plan_limit ou pro_required et une upgrade_url. Les limites de débit renvoient une erreur 429 avec un en-tête Retry-After. Chaque réponse authentifiée contient X-RateLimit-Limit, X-RateLimit-Remaining et X-RateLimit-Reset, pour que les clients puissent ralentir avant d’en arriver là."
        }
      },
      {
        "@type": "Question",
        "name": "L’API est-elle stable ?",
        "acceptedAnswer": {
          "@type": "Answer",
          "text": "Les routes v1 ne changeront pas de manière incompatible. Tout changement incompatible sera publié dans une nouvelle version. Pendant l’accès anticipé, les routes sont activées espace de travail par espace de travail ; une réponse 503 avec le code disabled signifie que l’API n’est pas encore activée pour votre espace de travail."
        }
      }
    ]
  },
  {
    "@context": "https://schema.org",
    "@type": "BreadcrumbList",
    "itemListElement": [
      {
        "@type": "ListItem",
        "position": 1,
        "name": "Accueil",
        "item": "https://uselinkpilot.com/fr"
      },
      {
        "@type": "ListItem",
        "position": 2,
        "name": "Développeurs",
        "item": "https://uselinkpilot.com/fr/developers"
      }
    ]
  },
  {
    "@context": "https://schema.org",
    "@type": "SoftwareApplication",
    "@id": "https://uselinkpilot.com/#software",
    "name": "LinkPilot",
    "applicationCategory": "BusinessApplication",
    "operatingSystem": "Web",
    "description": "LinkPilot is a secure link management platform for creating branded short links, tracking engagement, and sharing secrets with expiring, protected, self-destructing links.",
    "url": "https://uselinkpilot.com",
    "offers": [
      {
        "@type": "Offer",
        "name": "Free",
        "price": "0",
        "priceCurrency": "USD",
        "url": "https://uselinkpilot.com/pricing"
      },
      {
        "@type": "Offer",
        "name": "Pro",
        "price": "29",
        "priceCurrency": "USD",
        "priceSpecification": {
          "@type": "UnitPriceSpecification",
          "price": "29",
          "priceCurrency": "USD",
          "billingDuration": "P1M"
        },
        "url": "https://uselinkpilot.com/pricing"
      },
      {
        "@type": "Offer",
        "name": "Agency",
        "price": "299",
        "priceCurrency": "USD",
        "priceSpecification": {
          "@type": "UnitPriceSpecification",
          "price": "299",
          "priceCurrency": "USD",
          "billingDuration": "P1M"
        },
        "url": "https://uselinkpilot.com/pricing"
      },
      {
        "@type": "Offer",
        "name": "Agency Plus",
        "price": "799",
        "priceCurrency": "USD",
        "priceSpecification": {
          "@type": "UnitPriceSpecification",
          "price": "799",
          "priceCurrency": "USD",
          "billingDuration": "P1M"
        },
        "url": "https://uselinkpilot.com/pricing"
      },
      {
        "@type": "Offer",
        "name": "Pro (yearly)",
        "price": "288",
        "priceCurrency": "USD",
        "priceSpecification": {
          "@type": "UnitPriceSpecification",
          "price": "288",
          "priceCurrency": "USD",
          "billingDuration": "P1Y"
        },
        "url": "https://uselinkpilot.com/pricing"
      },
      {
        "@type": "Offer",
        "name": "Agency (yearly)",
        "price": "2988",
        "priceCurrency": "USD",
        "priceSpecification": {
          "@type": "UnitPriceSpecification",
          "price": "2988",
          "priceCurrency": "USD",
          "billingDuration": "P1Y"
        },
        "url": "https://uselinkpilot.com/pricing"
      },
      {
        "@type": "Offer",
        "name": "Agency Plus (yearly)",
        "price": "7980",
        "priceCurrency": "USD",
        "priceSpecification": {
          "@type": "UnitPriceSpecification",
          "price": "7980",
          "priceCurrency": "USD",
          "billingDuration": "P1Y"
        },
        "url": "https://uselinkpilot.com/pricing"
      },
      {
        "@type": "Offer",
        "name": "Enterprise",
        "priceSpecification": {
          "@type": "PriceSpecification",
          "priceCurrency": "USD"
        },
        "url": "https://uselinkpilot.com/pricing"
      }
    ]
  },
  {
    "@context": "https://schema.org",
    "@type": "Organization",
    "@id": "https://uselinkpilot.com/#organization",
    "name": "LinkPilot",
    "alternateName": "LinkPilot by TetraCore",
    "url": "https://uselinkpilot.com",
    "contactPoint": {
      "@type": "ContactPoint",
      "contactType": "customer support",
      "email": "support@uselinkpilot.com",
      "url": "https://uselinkpilot.com/support"
    },
    "parentOrganization": {
      "@type": "Organization",
      "@id": "https://tetracorehq.com/#organization",
      "name": "TetraCore",
      "url": "https://tetracorehq.com/"
    },
    "logo": {
      "@type": "ImageObject",
      "url": "https://uselinkpilot.com/logo-512.png",
      "width": 512,
      "height": 512
    },
    "description": "LinkPilot is a secure link management platform for creating branded short links, tracking engagement, and sharing secrets with expiring, protected, self-destructing links.",
    "sameAs": [
      "https://x.com/uselinkpilot",
      "https://www.linkedin.com/company/uselinkpilot",
      "https://facebook.com/uselinkpilot",
      "https://github.com/TetraCoreHQ/linkpilot-cli",
      "https://github.com/TetraCoreHQ/linkpilot-mcp",
      "https://www.npmjs.com/package/linkpilot",
      "https://www.npmjs.com/package/@uselinkpilot/sdk",
      "https://www.npmjs.com/package/@uselinkpilot/mcp",
      "https://chromewebstore.google.com/detail/linkpilot-short-links-and/mnmppadihpcncicldpkmgknhnjkondad",
      "https://addons.mozilla.org/en-US/firefox/addon/uselinkpilot/"
    ]
  },
  {
    "@context": "https://schema.org",
    "@type": "WebSite",
    "name": "LinkPilot",
    "url": "https://uselinkpilot.com",
    "potentialAction": {
      "@type": "SearchAction",
      "target": "https://uselinkpilot.com/blog?q={search_term_string}",
      "query-input": "required name=search_term_string"
    }
  }
]
```