Skill Integration (Interactive)
For agents that can run shell commands but don’t have a pre-provisioned API key. The agent handles authentication mid-session by guiding the user through the Nava UI.
Authentication
Check if NAVA_API_KEY and WALLET_ADDRESS are already set. If so, skip ahead to Submit a Transaction.
If not, prefer a headless wallet flow first:
- Check if your runtime has wallet-signing capability (wallet MCP/tool exposing
getAddressandsignMessage, or equivalent). - If wallet signing is available, perform SIWE bootstrap to create a user API key.
- Only if wallet signing is unavailable, fall back to UI code-based login.
Headless Wallet SIWE Bootstrap (Preferred)
Step 1: Get wallet address using your wallet tool (e.g. via getAddress).
Step 2: Request SIWE nonce
curl -s -X POST "https://internal.navalabs.dev/api/auth/siwe/nonce" \
-H "Content-Type: application/json" \
-d '{
"walletAddress": "<walletAddress>"
}'
Step 3: Build SIWE message string exactly
<domain> wants you to sign in with your Ethereum account:
<address>
<statement>
URI: <uri>
Version: 1
Chain ID: <chainId>
Nonce: <nonce>
Issued At: <issuedAt>
Step 4: Sign the exact SIWE message string with your wallet signing tool.
Step 5: Verify SIWE signature
curl -s -X POST "https://internal.navalabs.dev/api/auth/siwe/verify" \
-H "Content-Type: application/json" \
-d '{
"message": "<siweMessage>",
"signature": "<signature>"
}'
Step 6: Create a user API key
curl -s -X POST "https://internal.navalabs.dev/api/user-api-keys" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <accessToken>" \
-d '{
"name": "agent-session"
}'
Store key as NAVA_API_KEY and user.ethereumAddress as WALLET_ADDRESS.
UI Code-Based Login (Fallback)
Step 1: Initiate:
curl -s -X POST "https://internal.navalabs.dev/api/auth/connect/initiate" \
-H "Content-Type: application/json"
Response contains:
code: a 32-character hex connection code (expires after 10 minutes)authUrl: a URL for the user to visit
Present the authUrl to the user and ask them to open it in their browser, log in, and approve the connection.
Step 2: Poll for credentials:
curl -s -X GET "https://internal.navalabs.dev/api/auth/connect/status?code=<code>" \
-H "Content-Type: application/json"
Poll every 3-5 seconds. When the user completes authentication:
status:"ready"apiKey: the provisioned API key (returned exactly once)walletAddress: the authenticated wallet address
Submit a Transaction
curl -s -X POST "https://internal.navalabs.dev/api/transactions" \
-H "Content-Type: application/json" \
-H "x-api-key:$NAVA_API_KEY" \
-d '{
"escrowAddress": "'"$WALLET_ADDRESS"'",
"userPrompt": "<human-readable description of the transaction>",
"tx": {
"to": "<target address>",
"value": "<value in Wei>",
"data": "<encoded calldata>"
},
"chainId": 11155111
}'
Check Verification Status
curl -s -X GET "https://internal.navalabs.dev/api/transactions/<requestHash>/approval-status" \
-H "Content-Type: application/json" \
-H "x-api-key:$NAVA_API_KEY"
Workflow
- Check if
NAVA_API_KEYandWALLET_ADDRESSare set. - If missing, check for wallet-signing capability and run SIWE bootstrap.
- If wallet signing is unavailable, run UI code-based login.
- Call
POST /transactionswith transaction details. - Extract
requestHashfrom the response. - Poll
GET /transactions/{requestHash}/approval-statusevery 2-3 seconds. - Stop when
orion[0].decisionis"APPROVED","REJECTED", or"UNDECIDED". - If approved, proceed with on-chain execution. If rejected, read the
analysisand adapt.