Cadastro programático: login com carteira e criação de API key para Agents e CI

Cadastre-se e crie uma API key de forma programática usando uma assinatura de carteira Ethereum (EIP-191) sem a necessidade de um navegador para AI Agents, scripts e fluxos de CI.

Para AI Agents autônomos, pipelines de CI e scripts automatizados executados sem um navegador, a BlockVectra oferece um fluxo programático de login e abertura de conta baseado em assinaturas de carteira Ethereum (EIP-4361 / EIP-191).

Key security

Nunca cole chaves privadas, tokens de sessão ou API keys em conversas com IA nem as passe como argumentos de ferramentas MCP.

Antes de se cadastrar, você pode experimentar o endpoint público sem chave https://api.blockvectra.com/v1/robinhood_mainnet/public primeiro (apenas métodos JSON-RPC de carteira; a Data API exige uma chave; os métodos e limites estão sujeitos a /v1/chains); cadastre uma conta se a cota não for suficiente.

Visão geral do fluxo

O fluxo de registro programático e provisionamento de chaves é composto por quatro etapas:

  1. Solicitar challenge: envie uma requisição para POST /auth/siwe/challenge para obter uma mensagem de login gerada pelo servidor.
  2. Assinar mensagem: assine o texto exato da mensagem com uma carteira EOA Ethereum usando EIP-191 (personal_sign).
  3. Fazer login / abrir conta: envie a mensagem original e a assinatura para POST /auth/siwe/login. No primeiro login de uma carteira, uma conta é criada automaticamente (account_created: true). Novas contas recebem 30,000,000 CU no cadastro — sem cartão de crédito.
  4. Criar API key: use o token de sessão para chamar POST /keys e criar uma API key.

Exemplos executáveis completos

Comece aqui: use um assinador EOA Ethereum local, crie uma chave e verifique-a com eth_blockNumber. Para o exemplo em Bash, você precisa de curl, jq e cast do Foundry. Mantenha as credenciais da carteira em seu ambiente de assinatura local.

Modelo inicial completo: blockvectra/agent-quickstart

Os scripts a seguir leem as credenciais da carteira, concluem a sequência de challenge e login, provisionam uma API key, exportam ou exibem export BLOCKVECTRA_API_KEY=... para configuração de ambiente e enviam uma requisição de verificação eth_blockNumber:

Novas chaves levam alguns segundos para se tornarem ativas; estes exemplos tentam novamente de forma automática.

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 base e modo programático

Todos os endpoints de autenticação e gerenciamento de chaves usam a URL base oficial:

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

Omissão do cabeçalho Origin

As requisições programáticas operam no modo programático:

  • Tanto a requisição de challenge (POST /auth/siwe/challenge) quanto a de login (POST /auth/siwe/login) não devem incluir o cabeçalho Origin (curl e clientes HTTP padrão omitem esse cabeçalho por padrão; não o adicione manualmente).
  • Se um cabeçalho Origin for enviado mas não for um domínio configurado do console web (incluindo string vazia ou null), a requisição de challenge retornará HTTP 400 invalid_request.
  • Se o modo no login não coincidir com o modo do challenge (por exemplo, solicitar um challenge programático sem Origin e depois enviar o login com um cabeçalho Origin, ou vice-versa), a requisição de login retornará HTTP 400 siwe_invalid com reason: domain_mismatch.

Integridade da mensagem e requisitos da carteira

  • Assinatura e envio idênticos: os clientes devem assinar e enviar o texto da mensagem exatamente como retornado pelo endpoint de challenge. Não altere espaços em branco, domínio, Chain ID ou qualquer outro campo. Qualquer modificação resulta em HTTP 400 siwe_invalid com reason: signature.
  • Carteiras suportadas: Contas Externamente Proprietárias (EOA) da rede Ethereum mainnet (Chain ID 1). A assinatura deve ser uma assinatura ECDSA de 65 bytes (personal_sign). Carteiras de contrato (EIP-1271) e contas inteligentes (smart accounts) não são suportadas.
  • Validade do challenge: cada nonce de challenge é de uso único e expira após 5 minutos.

Corpo da requisição e atribuição de cadastro (opcional)

O corpo da requisição POST /auth/siwe/login aceita parâmetros obrigatórios de autenticação e campos opcionais de atribuição de cadastro:

  • Campos obrigatórios:
    • message: a string completa da mensagem SIWE obtida do endpoint de challenge.
    • signature: a assinatura hexadecimal de 65 bytes (com prefixo 0x) produzida ao assinar message via EIP-191 com uma carteira Ethereum.
  • Campos opcionais de atribuição (salvos apenas uma vez quando uma nova conta é criada; ignorados em logins subsequentes):
    • ref: um token de canal em minúsculas correspondente a ^[a-z0-9._-]{1,64}$ (letras ASCII minúsculas, dígitos, ., _, -, de 1 a 64 caracteres). Por exemplo, agents autônomos podem definir isso como seu identificador de framework ou runtime (ex.: my-agent.v1). Valores fora do padrão (incluindo letras maiúsculas, strings vazias, comprimento excessivo ou caracteres não suportados) retornam HTTP 400 invalid_request sem conversão automática de maiúsculas/minúsculas e impedem a criação da conta; omita ou passe null quando não aplicável.
    • referrer: uma URL de origem ou string de hostname; apenas tipos diferentes de string retornam HTTP 400.

Enviar campos indefinidos como signup_method retorna HTTP 400 invalid_request.

Tokens de sessão e API keys

Ciclo de vida do token de sessão

  • Formato: rgs_ seguido por 64 caracteres hexadecimais minúsculos.
  • Validade: tempo de vida absoluto de 7 dias; expira automaticamente após 24 horas de inatividade.
  • Sem token de atualização: quando um token de sessão expirar, inicie um novo fluxo de challenge e login.
  • Cabeçalho: passe o token de sessão no cabeçalho de requisição Authorization: Bearer rgs_....

Criação de API key

  • Chame POST /keys com o token de sessão para criar uma API key (rgw_ seguido por 64 caracteres hexadecimais).
  • Por conta, no máximo 20 chaves não revogadas e não expiradas (active + disabled); chaves expiradas não contam. Exceder esse limite retorna HTTP 409 key_limit_reached com reason: active_keys e limit: 20; revogue uma chave primeiro. O limite se aplica a todas as identidades, sessões e redes da conta. A criação e rotação de chaves também são limitadas a 20 por período de 24 horas; exceder isso retorna HTTP 429 rate_limited com Retry-After: 3600.
  • Limite e expiração opcionais: você pode fornecer cu_cap (limite vitalício de CU para a chave, que é um limite flexível) e expiração (expires_in_secs ou expires_at, até o máximo de dias permitido pela política de chaves); uma vez expirada ou com o limite esgotado, o servidor retorna 403 (JSON-RPC -32025, motivo key_expired ou key_cap_exhausted).
  • O segredo api_key é retornado apenas uma vez na criação. Armazene-o com segurança imediatamente em seu gerenciador de segredos ou variáveis de ambiente.
  • Uma API key funciona em todas as redes suportadas no JSON-RPC e na Data API.

Perdeu sua sessão ou API key?

Na BlockVectra, a identidade da conta de um agent é vinculada ao endereço da carteira Ethereum usado no cadastro. Se o token de sessão expirar ou uma API key for perdida ou vazada, você pode recuperar o controle total usando apenas essa carteira:

  1. Re-autenticar com a mesma carteira: solicite um challenge, assine-o com a mesma carteira e envie a requisição de login (POST /auth/siwe/login). O servidor verifica a assinatura, faz login na conta existente com account_created: false e emite um novo token de sessão.
  2. Criar uma nova API key: com o novo token de sessão, chame POST /keys com {"label": "..."} e o cabeçalho Authorization: Bearer <token>. O endpoint retorna HTTP 201 com os detalhes da chave criada em key e o segredo único em api_key. Salve essa chave imediatamente em suas variáveis de ambiente ou gerenciador de segredos.
  3. Listar todas as chaves da conta:
    • Endpoint: GET /keys
    • Cabeçalho: Authorization: Bearer <token>
    • Parâmetro de consulta: include_revoked=true opcional (quando true, inclui chaves revogadas; por padrão, retorna apenas chaves ativas/desativadas).
    • Resposta: HTTP 200 com JSON {"items": [...]}. Cada elemento no array items inclui:
      • key_id: identificador exclusivo da chave (string)
      • label: rótulo da chave (string ou null)
      • status: status ("active", "disabled" ou "revoked")
      • created_at: carimbo de data/hora de criação (string ISO 8601)
      • revoked_at: carimbo de data/hora de revogação (string, ou null se não revogada)
  4. Revogar chaves não utilizadas ou comprometidas:
    • Endpoint: POST /keys/{key_id}/revoke (observação: usa POST com o key_id de destino no caminho; corpo de requisição vazio)
    • Cabeçalho: Authorization: Bearer <token>
    • Comportamento: idempotente; chaves com status active ou disabled podem ser revogadas. Se já revogada, retorna HTTP 200 inalterada. Após a revogação, requisições usando essa chave são rejeitadas.
    • Resposta: HTTP 200 retornando o objeto da chave revogada (os campos coincidem com o objeto da chave acima, com status: "revoked" e um carimbo de data/hora em revoked_at).

Key and secret security

Armazene chaves privadas de carteiras e API keys em variáveis de ambiente ou em um gerenciador de segredos. Nunca as confirme em repositórios de código, grave-as em logs ou cole-as em conversas de chat com IA.

Recomendações de segurança

  • Use chaves de curta duração e revogue ao concluir: para tarefas automatizadas ou efêmeras, crie chaves de curta duração com expires_in_secs e revogue-as imediatamente via POST /keys/{key_id}/revoke assim que o trabalho for concluído.

Limites de taxa de cadastro (signup_rate_limited)

A criação de contas está sujeita a limites de taxa de cadastro. O bucket de tokens por IP tem capacidade para 100 contas e se reabastece a 100 contas/hora por endereço IPv4 ou prefixo IPv6 /64, compartilhado entre cadastros via SIWE e OAuth:

  • Ao exceder os limites de cadastro, POST /auth/siwe/login retorna HTTP 429 signup_rate_limited com um cabeçalho Retry-After indicando o número de segundos a aguardar.
  • O campo reason diferencia o escopo do limite:
    • per_ip: o orçamento de registro para o prefixo IP solicitante foi esgotado.
    • global: o limite agregado de cadastros da plataforma foi esgotado.
  • Os limites de taxa de cadastro avaliam apenas novos registros de contas. Contas existentes fazendo login não são bloqueadas por limites de taxa de cadastro.

Recursos relacionados

Próximos passos

Última atualização:

Nesta página