Skip to main content

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:

  1. Check if your runtime has wallet-signing capability (wallet MCP/tool exposing getAddress and signMessage, or equivalent).
  2. If wallet signing is available, perform SIWE bootstrap to create a user API key.
  3. 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

  1. Check if NAVA_API_KEY and WALLET_ADDRESS are set.
  2. If missing, check for wallet-signing capability and run SIWE bootstrap.
  3. If wallet signing is unavailable, run UI code-based login.
  4. Call POST /transactions with transaction details.
  5. Extract requestHash from the response.
  6. Poll GET /transactions/{requestHash}/approval-status every 2-3 seconds.
  7. Stop when orion[0].decision is "APPROVED", "REJECTED", or "UNDECIDED".
  8. If approved, proceed with on-chain execution. If rejected, read the analysis and adapt.