curl --request POST \
--url https://api.venlyfinance.com/v1/accounts/{accountId}/wallets/{walletId}/allowance-verification \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.venlyfinance.com/v1/accounts/{accountId}/wallets/{walletId}/allowance-verification"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.venlyfinance.com/v1/accounts/{accountId}/wallets/{walletId}/allowance-verification', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.venlyfinance.com/v1/accounts/{accountId}/wallets/{walletId}/allowance-verification",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.venlyfinance.com/v1/accounts/{accountId}/wallets/{walletId}/allowance-verification"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.venlyfinance.com/v1/accounts/{accountId}/wallets/{walletId}/allowance-verification")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.venlyfinance.com/v1/accounts/{accountId}/wallets/{walletId}/allowance-verification")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"success": true,
"result": {
"walletId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"status": "VERIFYING_ALLOWANCE",
"verificationExpiresAt": "2026-08-20T15:04:05Z",
"assets": [
{
"supportedAssetId": "5d4c5b99-2ce8-40a1-bc1d-173dd400fa89",
"asset": "USDC",
"contractAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"allowanceSufficient": true,
"permitStatus": "CONFIRMED"
},
{
"supportedAssetId": "352fa5ad-ca00-4701-905f-744b867f6d5d",
"asset": "EURC",
"contractAddress": "0x808456652fdb597867f38412077a9182bf77359f",
"allowanceSufficient": false,
"permitStatus": "PENDING"
}
]
}
}{
"success": false,
"errors": [
{
"code": "invalid-request",
"message": "The request contains invalid parameters."
}
],
"result": {}
}{
"success": false,
"errors": [
{
"code": "unauthenticated",
"message": "Please authenticate to perform this action."
}
]
}{
"success": false,
"errors": [
{
"code": "forbidden",
"message": "You do not have permission to access this resource."
}
]
}{
"success": false,
"errors": [
{
"code": "account-not-found",
"message": "The requested resource was not found."
}
]
}{
"success": false,
"errors": [
{
"code": "internal-error",
"message": "An unexpected error occurred. Please try again later."
}
]
}Verify wallet allowances
Activate a self-custody wallet from the allowances it has already granted on-chain.
curl --request POST \
--url https://api.venlyfinance.com/v1/accounts/{accountId}/wallets/{walletId}/allowance-verification \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.venlyfinance.com/v1/accounts/{accountId}/wallets/{walletId}/allowance-verification"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.venlyfinance.com/v1/accounts/{accountId}/wallets/{walletId}/allowance-verification', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.venlyfinance.com/v1/accounts/{accountId}/wallets/{walletId}/allowance-verification",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.venlyfinance.com/v1/accounts/{accountId}/wallets/{walletId}/allowance-verification"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.venlyfinance.com/v1/accounts/{accountId}/wallets/{walletId}/allowance-verification")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.venlyfinance.com/v1/accounts/{accountId}/wallets/{walletId}/allowance-verification")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"success": true,
"result": {
"walletId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"status": "VERIFYING_ALLOWANCE",
"verificationExpiresAt": "2026-08-20T15:04:05Z",
"assets": [
{
"supportedAssetId": "5d4c5b99-2ce8-40a1-bc1d-173dd400fa89",
"asset": "USDC",
"contractAddress": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"allowanceSufficient": true,
"permitStatus": "CONFIRMED"
},
{
"supportedAssetId": "352fa5ad-ca00-4701-905f-744b867f6d5d",
"asset": "EURC",
"contractAddress": "0x808456652fdb597867f38412077a9182bf77359f",
"allowanceSufficient": false,
"permitStatus": "PENDING"
}
]
}
}{
"success": false,
"errors": [
{
"code": "invalid-request",
"message": "The request contains invalid parameters."
}
],
"result": {}
}{
"success": false,
"errors": [
{
"code": "unauthenticated",
"message": "Please authenticate to perform this action."
}
]
}{
"success": false,
"errors": [
{
"code": "forbidden",
"message": "You do not have permission to access this resource."
}
]
}{
"success": false,
"errors": [
{
"code": "account-not-found",
"message": "The requested resource was not found."
}
]
}{
"success": false,
"errors": [
{
"code": "internal-error",
"message": "An unexpected error occurred. Please try again later."
}
]
}ACTIVE from the moment it is created, so this call answers 400 wallet-not-verifiable. To let Venly move a self-custody wallet’s funds, sign a permit.manage:accounts — see Required scopes.
Activates a self-custody account wallet by reading the allowances it has already granted on-chain, instead of going through the permit flow.
The wallet grants the permission with a plain approve(spender, amount) transaction instead of a permit. (Self-custody wallets are single-key wallets only for now — smart-contract wallets aren’t supported.)
The allowance is the consent: only the wallet’s controller could have granted it. So this endpoint reads public chain state and takes no request body and no proof.
What happens when you call it
Allowances are read synchronously
All assets covered → ACTIVE
Some assets missing → VERIFYING_ALLOWANCE
verificationExpiresAt. Venly keeps re-checking until then, so granting the remaining allowances is enough — you don’t have to call again.VERIFYING_ALLOWANCE is a waiting room, not a usable state. Every check that requires an active wallet treats it exactly like PENDING, so don’t offer the wallet to an end-user until it reads ACTIVE.If the window closes with assets still uncovered, the wallet falls back to PENDING and you start again.assets[] to see exactly which allowances are still missing — allowanceSufficient is per asset.
Both activation routes end in the same place: a wallet is ACTIVE once every supported asset is covered. See Permits and allowances.
Errors
The codes this endpoint can return, in addition to the standard errors. Branch oncode, never the message.
| HTTP | code | When |
|---|---|---|
400 | wallet-not-verifiable | the wallet cannot enter verification: it is already ACTIVE, or it is FROZEN/CLOSED |
400 | invalid-request | the wallet is Venly-managed, so it activates through the permit flow instead |
Authorizations
OAuth2 client credentials flow. Token endpoints:
Headers
Which tenant the request is scoped to, among those your token grants. Omit it when the token grants exactly one tenant; it is required when the token grants more than one. A supplied value must exactly match a tenant the token grants.
Absent when required, blank, malformed, or naming a tenant the token does not grant — each gets
the same generic 403 forbidden, which reveals neither whether a tenant exists nor which ones
you may use. Send the header once: a repeated header is rejected the same way.
"3fa85f64-5717-4562-b3fc-2c963f66afa6"
Path Parameters
Unique account identifier
Unique wallet identifier
Was this page helpful?

