Đăng ký bằng lập trình: đăng nhập bằng ví và tạo API key cho Agent và CI
Đăng ký và tạo API key bằng lập trình qua chữ ký ví Ethereum (EIP-191), không cần trình duyệt, cho AI Agent, script và quy trình CI.
Đối với AI Agent tự chủ, pipeline CI và script tự động chạy không cần trình duyệt, BlockVectra cung cấp quy trình đăng nhập và mở tài khoản bằng lập trình dựa trên chữ ký ví Ethereum (EIP-4361 / EIP-191).
Key security
Không bao giờ dán khóa riêng, session token hoặc API key vào cuộc trò chuyện với AI hay truyền chúng dưới dạng đối số công cụ MCP.
Trước khi đăng ký, bạn có thể thử endpoint công khai không cần API key https://api.blockvectra.com/v1/robinhood_mainnet/public (chỉ các phương thức JSON-RPC dành cho ví, Data API cần API key; phương thức và giới hạn theo /v1/chains); đăng ký tài khoản nếu hạn mức không đủ.
Tổng quan quy trình
Quy trình đăng ký và cấp API key bằng lập trình gồm bốn bước:
- Yêu cầu challenge: Gửi yêu cầu tới
POST /auth/siwe/challengeđể lấy thông điệp đăng nhập do máy chủ tạo. - Ký thông điệp: Ký chính xác thông điệp bằng ví Ethereum EOA qua EIP-191 (
personal_sign). - Đăng nhập / mở tài khoản: Gửi nguyên văn thông điệp và chữ ký tới
POST /auth/siwe/login. Khi ví đăng nhập lần đầu, tài khoản được tạo tự động (account_created: true). Tài khoản mới nhận 30,000,000 CU khi đăng ký — không cần thẻ tín dụng. - Tạo API key: Dùng session token để gọi
POST /keysvà tạo API key.
Ví dụ đầy đủ có thể chạy
Bắt đầu tại đây: dùng bộ ký Ethereum EOA cục bộ, tạo API key và xác minh bằng eth_blockNumber. Ví dụ Bash cần curl, jq và Foundry cast. Giữ thông tin xác thực ví trong môi trường ký cục bộ của bạn.
Mẫu khởi đầu đầy đủ: blockvectra/agent-quickstart
Các script sau đọc thông tin xác thực ví, hoàn tất chuỗi challenge và đăng nhập, cấp API key, xuất hoặc in export BLOCKVECTRA_API_KEY=... để cấu hình môi trường, rồi gửi yêu cầu eth_blockNumber để xác minh:
API key mới cần vài giây để có hiệu lực; các ví dụ này tự động thử lại.
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
doneURL cơ sở và chế độ lập trình
Tất cả endpoint xác thực và quản lý API key dùng URL cơ sở chính thức:
https://console-api.blockvectra.com/v1Bỏ header Origin
Yêu cầu bằng lập trình hoạt động trong chế độ lập trình:
- Cả yêu cầu challenge (
POST /auth/siwe/challenge) và đăng nhập (POST /auth/siwe/login) đều không được chứa headerOrigin(curlvà HTTP client tiêu chuẩn mặc định bỏ header này; không thêm thủ công). - Nếu gửi header
Originnhưng giá trị không phải miền bảng điều khiển web đã cấu hình (kể cả chuỗi rỗng hoặcnull), yêu cầu challenge trả HTTP 400invalid_request. - Nếu chế độ khi đăng nhập không khớp chế độ challenge (ví dụ yêu cầu challenge bằng lập trình không có
Origin, sau đó gửi đăng nhập có headerOrigin, hoặc ngược lại), yêu cầu đăng nhập trả HTTP 400siwe_invalidvớireason: domain_mismatch.
Tính toàn vẹn thông điệp và yêu cầu đối với ví
- Ký và gửi nguyên văn: Client phải ký và gửi văn bản thông điệp chính xác như endpoint challenge trả về. Không thay đổi khoảng trắng, miền, Chain ID hay bất kỳ trường nào. Mọi thay đổi đều dẫn đến HTTP 400
siwe_invalidvớireason: signature. - Ví được hỗ trợ: Tài khoản do cá nhân sở hữu (EOA) trên Ethereum mainnet (Chain ID 1). Chữ ký phải là chữ ký ECDSA 65 byte (
personal_sign). Không hỗ trợ ví hợp đồng (EIP-1271) và tài khoản thông minh. - Hiệu lực challenge: Mỗi nonce challenge chỉ dùng một lần và hết hạn sau 5 phút.
Body yêu cầu và nguồn đăng ký (tùy chọn)
Body yêu cầu POST /auth/siwe/login chấp nhận tham số xác thực bắt buộc và các trường nguồn đăng ký tùy chọn:
- Trường bắt buộc:
message: Chuỗi thông điệp SIWE đầy đủ lấy từ endpoint challenge.signature: Chữ ký thập lục phân 65 byte (có tiền tố0x) tạo bằng cách kýmessagequa EIP-191 bằng ví Ethereum.
- Trường nguồn đăng ký tùy chọn (chỉ lưu một lần khi tạo tài khoản mới; bỏ qua trong các lần đăng nhập sau):
ref: Token kênh viết thường khớp^[a-z0-9._-]{1,64}$(chữ cái ASCII viết thường, chữ số,.,_,-, 1–64 ký tự). Ví dụ, Agent tự chủ có thể đặt giá trị này thành mã định danh framework hoặc runtime (nhưmy-agent.v1). Giá trị không hợp lệ (gồm chữ hoa, chuỗi rỗng, quá dài hoặc ký tự không được hỗ trợ) trả HTTP 400invalid_requestmà không chuyển đổi chữ hoa thành chữ thường và ngăn tạo tài khoản; bỏ qua hoặc truyềnnullnếu không áp dụng.referrer: Chuỗi URL nguồn hoặc hostname; chỉ kiểu không phải chuỗi mới trả HTTP 400.
Gửi trường chưa được định nghĩa như signup_method trả HTTP 400 invalid_request.
Session token và API key
Vòng đời session token
- Định dạng:
rgs_theo sau bởi 64 ký tự thập lục phân viết thường. - Hiệu lực: Thời gian tồn tại tuyệt đối là 7 ngày; tự động hết hạn sau 24 giờ không hoạt động.
- Không có refresh token: Khi session token hết hạn, bắt đầu quy trình challenge và đăng nhập mới.
- Header: Truyền session token trong header yêu cầu
Authorization: Bearer rgs_....
Tạo API key
- Gọi
POST /keysbằng session token để tạo API key (rgw_theo sau bởi 64 ký tự thập lục phân). - Mỗi tài khoản có tối đa 20 API key chưa bị thu hồi và chưa hết hạn (
active+disabled); API key hết hạn không được tính. Vượt giới hạn trả HTTP 409key_limit_reachedvớireason: active_keysvàlimit: 20; hãy thu hồi một API key trước. Giới hạn áp dụng trên tất cả danh tính, phiên và chuỗi của tài khoản. Tạo và xoay vòng API key cũng bị giới hạn ở 20 lần mỗi 24 giờ; vượt giới hạn trả HTTP 429rate_limitedvớiRetry-After: 3600. - Hạn mức và thời hạn tùy chọn: bạn có thể cung cấp
cu_cap(hạn mức CU trọn đời của API key, là hạn mức mềm) và thời hạn (expires_in_secshoặcexpires_at, tối đa số ngày chính sách API key cho phép); khi hết hạn hoặc dùng hết hạn mức, máy chủ trả 403 (JSON-RPC-32025, reason làkey_expiredhoặckey_cap_exhausted). - Giá trị bí mật
api_keychỉ được trả một lần khi tạo. Lưu an toàn ngay vào trình quản lý bí mật hoặc biến môi trường. - Một API key hoạt động trên tất cả chuỗi được hỗ trợ cho JSON-RPC và Data API.
Mất session token hoặc API key?
Trong BlockVectra, danh tính tài khoản của Agent gắn với địa chỉ ví Ethereum dùng khi đăng ký. Nếu session token hết hạn hoặc API key bị mất hay lộ, bạn có thể khôi phục toàn quyền kiểm soát chỉ bằng ví đó:
- Xác thực lại bằng cùng ví: Yêu cầu challenge, ký bằng cùng ví và gửi yêu cầu đăng nhập (
POST /auth/siwe/login). Máy chủ xác minh chữ ký, đăng nhập tài khoản hiện có vớiaccount_created: falsevà cấp session token mới. - Tạo API key mới: Dùng session token mới để gọi
POST /keysvới{"label": "..."}và headerAuthorization: Bearer <token>. Endpoint trả HTTP 201 với chi tiết API key đã tạo trongkeyvà giá trị bí mật chỉ trả một lần trongapi_key. Lưu API key này ngay vào biến môi trường hoặc trình quản lý bí mật. - Liệt kê tất cả API key của tài khoản:
- Endpoint:
GET /keys - Header:
Authorization: Bearer <token> - Tham số truy vấn:
include_revoked=truetùy chọn (khi làtrue, bao gồm API key đã thu hồi; mặc định chỉ gồm API key active/disabled). - Phản hồi: HTTP 200 với JSON
{"items": [...]}. Mỗi phần tử trong mảngitemsgồm:key_id: mã định danh API key duy nhất (chuỗi)label: nhãn API key (chuỗi hoặcnull)status: trạng thái ("active","disabled"hoặc"revoked")created_at: dấu thời gian tạo (chuỗi ISO 8601)revoked_at: dấu thời gian thu hồi (chuỗi, hoặcnullnếu chưa thu hồi)
- Endpoint:
- Thu hồi API key không dùng hoặc bị lộ:
- Endpoint:
POST /keys/{key_id}/revoke(lưu ý: dùngPOSTvớikey_idđích trong đường dẫn; body yêu cầu rỗng) - Header:
Authorization: Bearer <token> - Hành vi: lũy đẳng; API key ở trạng thái
activehoặcdisabledđều có thể thu hồi. Nếu đã thu hồi, trả HTTP 200 và không thay đổi. Sau khi thu hồi, yêu cầu dùng API key đó bị từ chối. - Phản hồi: HTTP 200 trả đối tượng API key đã thu hồi (các trường khớp đối tượng API key ở trên, với
status: "revoked"và dấu thời gian trongrevoked_at).
- Endpoint:
Key and secret security
Lưu khóa riêng của ví và API key trong biến môi trường hoặc trình quản lý bí mật. Không bao giờ commit chúng vào kho mã, ghi vào log hay dán vào cuộc trò chuyện với AI.
Khuyến nghị bảo mật
- Dùng API key ngắn hạn và thu hồi khi hoàn tất: Với tác vụ tự động hoặc tạm thời, tạo API key ngắn hạn bằng
expires_in_secsvà thu hồi ngay quaPOST /keys/{key_id}/revokekhi hoàn tất công việc.
Giới hạn tốc độ đăng ký (signup_rate_limited)
Việc tạo tài khoản chịu giới hạn tốc độ đăng ký. Token bucket mỗi IP có dung lượng 100 tài khoản và nạp lại 100 tài khoản/giờ cho mỗi địa chỉ IPv4 hoặc tiền tố IPv6 /64, dùng chung cho đăng ký SIWE và OAuth:
- Khi vượt giới hạn đăng ký,
POST /auth/siwe/logintrả HTTP 429signup_rate_limitedvới headerRetry-Aftercho biết số giây cần chờ. - Trường
reasonphân biệt phạm vi giới hạn:per_ip: hạn mức đăng ký của tiền tố IP yêu cầu đã cạn.global: giới hạn đăng ký tổng hợp của nền tảng đã cạn.
- Giới hạn tốc độ đăng ký chỉ áp dụng cho đăng ký tài khoản mới. Tài khoản hiện có đăng nhập không bị chặn bởi giới hạn tốc độ đăng ký.
Tài nguyên liên quan
- Đọc hướng dẫn tích hợp AI Agent để tìm hiểu MCP server không cần API key và tệp ngữ cảnh máy đọc được.
- Xem Bắt đầu nhanh để lấy ví dụ client bằng nhiều ngôn ngữ.
- Xem tham chiếu lỗi để biết đầy đủ mã lỗi, reason và cách khôi phục tự động.
Các bước tiếp theo
- Gửi lệnh gọi JSON-RPC hoặc Data API đầu tiên bằng
x-api-key: $BLOCKVECTRA_API_KEY. - Kiểm tra số dư và giới hạn tài khoản bằng
GET /v1/account. - Làm theo hướng dẫn nạp tiền bằng lập trình cho Agent để duy trì số dư.
Cập nhật lần cuối:
Một API key cho nhiều chuỗi
Dùng cùng một API key trên mọi chuỗi được hỗ trợ. Tìm hiểu cấu trúc URL, cách khám phá chuỗi bằng lập trình và cách chia sẻ số dư, giới hạn.
Đọc hiểu giá CU
Đọc trọng số CU và các đơn vị định giá của RPC và Data API, tính toán giá cho mỗi triệu lệnh gọi và ước tính chi phí sử dụng từ API kế hoạch hiện tại.