Install
openclaw skills install bitnowEnd-to-end OpenBytes network API workflows for AI agents. Covers wallet signature-based authentication, on-chain top-up monitoring, consumer API key lifecycle (create, list, revoke), API calls to language models via gateway, and querying balance and usage via HTTP endpoints. Use to help users automate or debug OpenBytes network operations by direct API interaction.
openclaw skills install bitnowThis skill describes end-to-end operational workflows for the OpenBytes network from an API usage perspective.
Assumptions:
https://gateway.openbytes.ai84532Replace all <BASE_URL> with the actual gateway URL as needed.
Note: Message signing must be performed by the user with their EVM wallet. The agent can only initiate the challenge and verify a signature; it cannot produce signatures.
import { Wallet } from "ethers";
const wallet = Wallet.createRandom();
console.log("Address:", wallet.address);
console.log("Private Key (save this securely!):", wallet.privateKey);
Or using viem:
import { createWallet } from "viem/accounts";
const wallet = createWallet();
console.log("Address:", wallet.address);
console.log("Private Key (save this securely!):", wallet.privateKey);
Never share your private key. Backup and store it in a secure location. "wallet_address": "0x...", "chain_id": "8453"
message off-chain (with their wallet).curl -sS -X POST "<BASE_URL>/v1/auth/wallet/verify" \
-H "Content-Type: application/json" \
-d '{
"wallet_address": "<EVM_WALLET_ADDRESS>",
"nonce": "random-nonce",
"signature": "<WALLET_SIGNATURE>"
}'
Successful response (simplified):
{
"login_token": "sess-...",
"expires_at": "2025-01-01T00:00:00Z",
"consumer": {
"id": "consumer-uuid",
"wallet_address": "0x..."
},
"session": {
"id": "session-uuid"
}
}
The login_token (starting with sess-) is used as a session token:
Authorization: Bearer <SESSION_TOKEN> for session-auth endpoints.List Available Models
curl -sS -X GET "<BASE_URL>/v1/models"
Check:
Authorization: Bearer sess-... header during all subsequent calls requiring authentication.Authorization: Bearer <CONSUMER_API_KEY>.Consumers use API keys to access models without a session.
Requires a valid session token (login_token from section 1).
curl -sS -X POST "<BASE_URL>/v1/consumer/api-keys" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <SESSION_TOKEN>" \
-d '{
"label": "my-key"
}'
Sample response (save the api_key securely; only returned once!):
{
"id": "key-uuid",
"api_key": "sk-consumer-...",
"prefix": "sk-cons",
"suffix": "abcd",
"label": "my-key",
"status": "active",
"created_at": "2025-01-01T00:00:00Z"
}
Immediately switch to this API key for inference, balance, and usage calls:
export OPENBYTES_API_KEY="sk-consumer-..."
Then use:
curl -sS -X GET "<BASE_URL>/v1/balance" \
-H "Authorization: Bearer $OPENBYTES_API_KEY"
curl -sS -X GET "<BASE_URL>/v1/consumer/api-keys" \
-H "Authorization: Bearer <SESSION_TOKEN>"
curl -sS -X DELETE "<BASE_URL>/v1/consumer/api-keys/<KEY_ID>" \
-H "Authorization: Bearer <SESSION_TOKEN>"
The key status will be set to revoked; subsequent calls using that key will fail with an auth error.
Top-up is performed on-chain (USDC to a ConsumerDeposit contract), tracked by off-chain indexers. The API lets you verify the result.
You can use your own RPC endpoint; a default for Base Sepolia is https://sepolia.base.org.
0x10065E7b353371DD2e12348e7094cC774638EbEB0xB0E9ebf19AB710d3353c7F637DC55329d9727dCc
function deposit(uint256 amount)Verify balance:
curl -sS -X GET "<BASE_URL>/v1/balance" \
-H "Authorization: Bearer <CONSUMER_API_KEY>"
Sample response:
{
"balance_usdc": "123.45",
"total_spent": "10.00"
}
Use this to allow an account to connect to an operator's account, so the operator can top up your wallet easily. This requires a wallet signature over a structured message. The signature must be produced by the child wallet.
Endpoint:
curl -sS -X POST "<BASE_URL>/v1/consumers/me/parent" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <SESSION_TOKEN>" \
-d '{
"parent_wallet": "<PARENT_WALLET>",
"issued_at": 1710000000,
"signature": "<CHILD_WALLET_SIGNATURE>"
}'
Notes:
ethers.verifyMessage(message, signature),
and the recovered address must equal the child wallet address (case-insensitive).
This is the standard EIP-191 personal message signature (same flow as SIWE).issued_at is Unix seconds. It must be within the last 5 minutes and not more than 1 minute in the future.Authorize parent for OpenBytes
Parent wallet: <PARENT_WALLET_LOWERCASE>
Child wallet: <CHILD_WALLET_LOWERCASE>
Issued at: <ISSUED_AT>
<PARENT_WALLET_LOWERCASE> is the parent wallet address lowercased.<CHILD_WALLET_LOWERCASE> is the child wallet address lowercased (the signer).<ISSUED_AT> is the same Unix seconds integer you send in the request body.Pseudo-code (client-side):
const issuedAt = Math.floor(Date.now() / 1000);
const parentWallet = parentWalletAddress.toLowerCase();
const childWallet = childWalletAddress.toLowerCase();
const message = [
"Authorize parent for OpenBytes",
`Parent wallet: ${parentWallet}`,
`Child wallet: ${childWallet}`,
`Issued at: ${issuedAt}`,
].join("\n");
const signature = await wallet.signMessage(message); // EIP-191 personal_sign
Success response (201):
{
"parent_consumer_id": "consumer-uuid",
"parent_wallet_address": "0x...",
"created_at": "2025-01-01T00:00:00Z"
}
Common errors:
400 INVALID_REQUEST invalid body400 SIGNATURE_EXPIRED issued_at out of window404 PARENT_NOT_FOUND parent not found400 SELF_PARENT cannot declare yourself401 SIGNATURE_MISMATCH signature not from child wallet409 ALREADY_SET parent already declaredWhen handling OpenBytes network operational support, follow these best practices:
<BASE_URL>, <CONSUMER_API_KEY>, etc).error.code and context to select remediation steps.