Inscription programmatique : connexion par portefeuille et création d'API key pour agents et CI

Inscrivez-vous et créez une API key par programmation à l'aide d'une signature de portefeuille Ethereum (EIP-191) sans navigateur pour les agents IA, scripts et flux CI.

Pour les agents IA autonomes, les pipelines CI et les scripts automatisés s'exécutant sans navigateur, BlockVectra fournit un flux de connexion et d'ouverture de compte programmatique basé sur les signatures de portefeuille Ethereum (EIP-4361 / EIP-191).

Sécurité de la clé

Ne collez jamais de clés privées, de jetons de session ou d'API keys dans des conversations avec l'IA et ne les transmettez pas en tant qu'arguments d'outils MCP.

Avant de vous inscrire, vous pouvez d'abord tester le point de terminaison public sans clé https://api.blockvectra.com/v1/robinhood_mainnet/public (méthodes JSON-RPC de portefeuille uniquement, la Data API nécessite une clé ; les méthodes et limites dépendent de /v1/chains) ; créez un compte si le quota est insuffisant.

Aperçu du flux de travail

Le flux d'inscription programmatique et d'attribution de clés se compose de quatre étapes :

  1. Demander un challenge : envoyez une requête à POST /auth/siwe/challenge pour obtenir un message de connexion généré par le serveur.
  2. Signer le message : signez le message exact avec un portefeuille Ethereum EOA en utilisant EIP-191 (personal_sign).
  3. Se connecter / ouvrir un compte : soumettez le message textuel et la signature à POST /auth/siwe/login. Lors de la première connexion pour un portefeuille, un compte est automatiquement créé (account_created: true). Les nouveaux comptes reçoivent 30,000,000 CU à l'inscription — aucune carte bancaire requise.
  4. Créer une API key : utilisez le jeton de session pour appeler POST /keys et créer une API key.

Exemples complets exécutables

Commencez ici : utilisez un signataire Ethereum EOA local, créez une clé et vérifiez-la avec eth_blockNumber. Pour l'exemple Bash, vous avez besoin de curl, jq et Foundry cast. Conservez les identifiants de portefeuille dans votre environnement de signature local.

Modèle de démarrage complet : blockvectra/agent-quickstart

Les scripts suivants lisent les identifiants de portefeuille, effectuent la séquence de challenge et de connexion, approvisionnent une API key, exportent ou affichent export BLOCKVECTRA_API_KEY=... pour la configuration de l'environnement, et envoient une requête de vérification eth_blockNumber :

Les nouvelles clés prennent quelques secondes pour s'activer ; ces exemples réessaient automatiquement.

BASE=https://console-api.blockvectra.com/v1
# $ADDR: Ethereum wallet address (0x...)
# $PK: wallet private key, loaded from a secrets manager (never hardcode in scripts)

# 1. Fetch server-generated SIWE message (omit Origin header)
curl -s "$BASE/auth/siwe/challenge" -H 'Content-Type: application/json' \
  -d "{\"address\":\"$ADDR\",\"purpose\":\"login\"}" > challenge.json
jq -r .message challenge.json > msg.txt

# 2. Sign the exact message with EIP-191 personal_sign
SIG=$(cast wallet sign --private-key "$PK" "$(cat msg.txt)")

# 3. Submit verbatim message and signature (omit Origin header) to log in (ref is optional)
jq -n --rawfile m msg.txt --arg s "$SIG" '{message: ($m | rtrimstr("\n")), signature: $s, ref: "docs-signup"}' |
  curl -s "$BASE/auth/siwe/login" -H 'Content-Type: application/json' -d @- > session.json
TOKEN=$(jq -r .session.token session.json)

# 4. Create an API key (the secret is returned only once)
KEY_RESP=$(curl -s "$BASE/keys" \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"label":"agent-key"}')
export BLOCKVECTRA_API_KEY=$(echo "$KEY_RESP" | jq -r .api_key)

# 5. Call JSON-RPC with the key in the x-api-key request header
RPC_DEADLINE=$((SECONDS + 10))
while true; do
  RPC_TIMEOUT=$((RPC_DEADLINE - SECONDS))
  if ((RPC_TIMEOUT <= 0)); then
    printf '%s' "${RPC_BODY:-}"
    break
  fi
  RPC_RESP=$(curl -s --max-time "$RPC_TIMEOUT" -w '\n%{http_code}' "https://api.blockvectra.com/v1/robinhood_mainnet" \
    -H "x-api-key: $BLOCKVECTRA_API_KEY" \
    -H 'Content-Type: application/json' \
    -d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}') || { rc=$?; echo "request failed (curl exit $rc)" >&2; exit $rc; }
  RPC_STATUS=${RPC_RESP##*$'\n'}
  RPC_BODY=${RPC_RESP%$'\n'*}
  if ((SECONDS + 2 < RPC_DEADLINE)) &&
    printf '%s' "$RPC_BODY" | jq -e --arg status "$RPC_STATUS" '
      ($status == "401" and .error.data.reason == "invalid_api_key") or
      ($status == "503" and .error.code == -32021)
    ' >/dev/null 2>&1; then
    sleep 2
  else
    printf '%s' "$RPC_BODY"
    break
  fi
done

URL de base et mode programmatique

Tous les points de terminaison d'authentification et de gestion des clés utilisent l'URL de base officielle :

https://console-api.blockvectra.com/v1

Omission de l'en-tête Origin

Les requêtes programmatiques fonctionnent en mode programmatique :

  • Les requêtes de challenge (POST /auth/siwe/challenge) et de connexion (POST /auth/siwe/login) ne doivent pas inclure l'en-tête Origin (curl et les clients HTTP standard omettent cet en-tête par défaut ; ne l'ajoutez pas manuellement).
  • Si un en-tête Origin est envoyé sans correspondre à un domaine configuré de la console web (y compris une chaîne vide ou null), la requête de challenge renvoie HTTP 400 invalid_request.
  • Si le mode lors de la connexion ne correspond pas au mode du challenge (par exemple, demander un challenge programmatique sans Origin puis soumettre la connexion avec un en-tête Origin, ou inversement), la requête de connexion renvoie HTTP 400 siwe_invalid avec reason: domain_mismatch.

Intégrité des messages et prérequis de portefeuille

  • Signature et soumission textuelles : les clients doivent signer et soumettre le texte du message exactement tel qu'il a été renvoyé par le point de terminaison de challenge. Ne modifiez ni les espaces, ni le domaine, ni l'ID de chaîne, ni aucun autre champ. Toute modification entraîne une réponse HTTP 400 siwe_invalid avec reason: signature.
  • Portefeuilles pris en charge : comptes de type Externally Owned Accounts (EOA) sur Ethereum mainnet (Chain ID 1). La signature doit être une signature ECDSA de 65 octets (personal_sign). Les portefeuilles de contrats (EIP-1271) et les smart accounts ne sont pas pris en charge.
  • Validité du challenge : chaque nonce de challenge est à usage unique et expire au bout de 5 minutes.

Corps de requête et attribution d'inscription (facultatif)

Le corps de la requête POST /auth/siwe/login accepte des paramètres d'authentification obligatoires et des champs d'attribution d'inscription facultatifs :

  • Champs obligatoires :
    • message : la chaîne complète du message SIWE obtenue à partir du point de terminaison de challenge.
    • signature : la signature hexadécimale de 65 octets (préfixée par 0x) produite en signant message via EIP-191 avec un portefeuille Ethereum.
  • Champs d'attribution facultatifs (enregistrés une seule fois lors de la création d'un nouveau compte ; ignorés lors des connexions ultérieures) :
    • ref : un jeton de canal en minuscules respectant ^[a-z0-9._-]{1,64}$ (lettres ASCII minuscules, chiffres, ., _, -, 1 à 64 caractères). Par exemple, les agents autonomes peuvent renseigner l'identifiant de leur framework ou environnement d'exécution (par exemple my-agent.v1). Les valeurs non conformes (notamment majuscules, chaînes vides, longueur excessive ou caractères non pris en charge) renvoient HTTP 400 invalid_request sans conversion de casse et empêchent la création du compte ; omettez ce champ ou transmettez null s'il n'est pas applicable.
    • referrer : une URL source ou une chaîne d'hôte ; seuls les types autres que chaîne renvoient HTTP 400.

L'envoi de champs non définis tels que signup_method renvoie HTTP 400 invalid_request.

Jetons de session et API keys

Cycle de vie des jetons de session

  • Format : rgs_ suivi de 64 caractères hexadécimaux en minuscules.
  • Validité : durée de vie absolue de 7 jours ; expire automatiquement après 24 heures d'inactivité.
  • Aucun jeton de rafraîchissement : lorsqu'un jeton de session expire, initiez un nouveau flux de challenge et de connexion.
  • En-tête : transmettez le jeton de session dans l'en-tête de requête Authorization: Bearer rgs_....

Création d'API key

  • Appelez POST /keys avec le jeton de session pour créer une API key (rgw_ suivi de 64 caractères hexadécimaux).
  • Par compte, au maximum 20 clés non révoquées et non expirées (active + disabled) ; les clés expirées ne sont pas comptabilisées. Tout dépassement renvoie HTTP 409 key_limit_reached avec reason: active_keys et limit: 20 ; révoquez d'abord une clé. Ce plafond s'applique à l'ensemble des identités, sessions et chaînes du compte. La création et la rotation de clés sont également limitées à 20 par période de 24 heures ; tout dépassement renvoie HTTP 429 rate_limited avec Retry-After: 3600.
  • Plafond et expiration facultatifs : vous pouvez définir cu_cap (plafond de CU sur la durée de vie de la clé, correspondant à un plafond indicatif / soft cap) et une expiration (expires_in_secs ou expires_at, jusqu'au nombre maximal de jours autorisé par la politique des clés) ; une fois la clé expirée ou le plafond atteint, le serveur renvoie 403 (JSON-RPC -32025, motif key_expired ou key_cap_exhausted).
  • Le secret api_key est renvoyé une seule fois lors de la création. Stockez-le immédiatement en lieu sûr dans votre gestionnaire de secrets ou vos variables d'environnement.
  • Une seule API key fonctionne sur toutes les chaînes prises en charge pour JSON-RPC et la Data API.

Session ou API key perdue ?

Sur BlockVectra, l'identité du compte d'un agent est liée à l'adresse de portefeuille Ethereum utilisée lors de l'inscription. Si votre jeton de session expire ou si une API key est perdue ou divulguée, vous pouvez en récupérer le contrôle total en utilisant uniquement ce portefeuille :

  1. Se réauthentifier avec le même portefeuille : demandez un challenge, signez-le avec le même portefeuille et soumettez la requête de connexion (POST /auth/siwe/login). Le serveur vérifie la signature, se connecte au compte existant avec account_created: false et délivre un nouveau jeton de session.
  2. Créer une nouvelle API key : avec le nouveau jeton de session, appelez POST /keys avec {"label": "..."} et l'en-tête Authorization: Bearer <token>. Le point de terminaison renvoie HTTP 201 avec les détails de la clé créée dans key et le secret à usage unique dans api_key. Enregistrez immédiatement cette clé dans vos variables d'environnement ou votre gestionnaire de secrets.
  3. Lister toutes les clés du compte :
    • Point de terminaison : GET /keys
    • En-tête : Authorization: Bearer <token>
    • Paramètre de requête : include_revoked=true facultatif (si true, inclut les clés révoquées ; par défaut, ne liste que les clés actives ou désactivées).
    • Réponse : HTTP 200 avec le JSON {"items": [...]}. Chaque élément du tableau items comprend :
      • key_id : identifiant unique de clé (chaîne)
      • label : libellé de clé (chaîne ou null)
      • status : statut ("active", "disabled" ou "revoked")
      • created_at : horodatage de création (chaîne ISO 8601)
      • revoked_at : horodatage de révocation (chaîne, ou null si non révoquée)
  4. Révoquer les clés inutilisées ou compromises :
    • Point de terminaison : POST /keys/{key_id}/revoke (remarque : utilise POST avec le key_id cible dans le chemin ; corps de requête vide)
    • En-tête : Authorization: Bearer <token>
    • Comportement : idempotent ; les clés ayant le statut active ou disabled peuvent être révoquées. Si elle est déjà révoquée, la requête renvoie HTTP 200 à l'identique. Après révocation, les requêtes utilisant cette clé sont rejetées.
    • Réponse : HTTP 200 renvoyant l'objet de clé révoquée (les champs correspondent à l'objet de clé ci-dessus, avec status: "revoked" et un horodatage dans revoked_at).

Sécurité des clés et des secrets

Stockez les clés privées de portefeuille et les API keys dans des variables d'environnement ou un gestionnaire de secrets. Ne les commitez jamais dans des dépôts de code, ne les écrivez pas dans des logs et ne les collez pas dans des conversations avec l'IA.

Recommandations de sécurité

  • Utiliser des clés à court terme et les révoquer une fois terminé : pour les tâches automatisées ou éphémères, créez des clés à courte durée de vie avec expires_in_secs et révoquez-les immédiatement via POST /keys/{key_id}/revoke dès la fin du travail.

Limites de débit à l'inscription (signup_rate_limited)

La création de compte est soumise à des limites de débit d'inscription. Le seau à jetons par IP dispose d'une capacité de 100 comptes et se recharge à raison de 100 comptes/heure par adresse IPv4 ou préfixe IPv6 /64, partagé entre les inscriptions SIWE et OAuth :

  • En cas de dépassement des limites d'inscription, POST /auth/siwe/login renvoie HTTP 429 signup_rate_limited avec un en-tête Retry-After indiquant le nombre de secondes à attendre.
  • Le champ reason distingue la portée de la limite :
    • per_ip : le budget d'inscription pour le préfixe IP demandeur a été épuisé.
    • global : la limite globale d'inscription de la plateforme a été atteinte.
  • Les limites de débit d'inscription n'évaluent que les nouveaux enregistrements de comptes. La connexion de comptes existants n'est pas bloquée par ces limites.

Ressources associées

Prochaines étapes

Dernière mise à jour :

Sur cette page