Get Virtual Account Group
curl --request GET \
--url https://api.hopnow.io/v1/accounts/{account_id}/virtual-account-groups/{group_id} \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.hopnow.io/v1/accounts/{account_id}/virtual-account-groups/{group_id}"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.hopnow.io/v1/accounts/{account_id}/virtual-account-groups/{group_id}', 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.hopnow.io/v1/accounts/{account_id}/virtual-account-groups/{group_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$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.hopnow.io/v1/accounts/{account_id}/virtual-account-groups/{group_id}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.hopnow.io/v1/accounts/{account_id}/virtual-account-groups/{group_id}")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hopnow.io/v1/accounts/{account_id}/virtual-account-groups/{group_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"id": "<string>",
"object": "<string>",
"account_id": "<string>",
"type": "<string>",
"status": "<string>",
"onboarding_status": "<string>",
"enabled_at": "<string>",
"suspended_at": "<string>",
"closed_at": "<string>",
"requirements": [
{
"key": "<string>",
"type": "<string>",
"label": "<string>",
"associated_person_id": "<string>",
"is_target_resolved": true,
"accepted_document_types": [
{}
],
"reason": "<string>"
}
],
"agreements": {
"status": "<string>",
"pending_ids": [
{}
]
},
"created": "<string>",
"updated": "<string>",
"created_by": "<string>",
"updated_by": "<string>"
}Virtual Account Groups
Get Virtual Account Group
Retrieve one virtual account group with its outstanding onboarding requirements
GET
/
v1
/
accounts
/
{account_id}
/
virtual-account-groups
/
{group_id}
Get Virtual Account Group
curl --request GET \
--url https://api.hopnow.io/v1/accounts/{account_id}/virtual-account-groups/{group_id} \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.hopnow.io/v1/accounts/{account_id}/virtual-account-groups/{group_id}"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.hopnow.io/v1/accounts/{account_id}/virtual-account-groups/{group_id}', 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.hopnow.io/v1/accounts/{account_id}/virtual-account-groups/{group_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$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.hopnow.io/v1/accounts/{account_id}/virtual-account-groups/{group_id}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.hopnow.io/v1/accounts/{account_id}/virtual-account-groups/{group_id}")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hopnow.io/v1/accounts/{account_id}/virtual-account-groups/{group_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"id": "<string>",
"object": "<string>",
"account_id": "<string>",
"type": "<string>",
"status": "<string>",
"onboarding_status": "<string>",
"enabled_at": "<string>",
"suspended_at": "<string>",
"closed_at": "<string>",
"requirements": [
{
"key": "<string>",
"type": "<string>",
"label": "<string>",
"associated_person_id": "<string>",
"is_target_resolved": true,
"accepted_document_types": [
{}
],
"reason": "<string>"
}
],
"agreements": {
"status": "<string>",
"pending_ids": [
{}
]
},
"created": "<string>",
"updated": "<string>",
"created_by": "<string>",
"updated_by": "<string>"
}Works on any account you own that has a virtual account group open. Create Virtual Account Group covers who can open one and what the account needs before onboarding can progress: an identity profile, plus an associated person marked as a signer on a business account.
Poll this endpoint during onboarding. The detail response is a superset of the list item: every field List Virtual Account Groups returns, plus
requirements, the outstanding actions the provider is waiting on, and an agreements summary.
Poll it after opening a group with Create Virtual Account Group and after every document upload or agreement response. requirements is rewritten each time Hop refreshes the group from the provider, so requirements is replaced on every refresh. A satisfied requirement disappears; new ones can appear at any time, including after the group is live: a requirement disappears once it is satisfied, and new ones can appear at any time, including after the group is live.
A group is usable only when status is enabled and onboarding_status is approved. Until both hold, Create Virtual Account rejects the group with 422 VIRTUAL_ACCOUNT_GROUP_NOT_ENABLED.
A group opened before the account’s identity profile was set carries a single account_profile.required requirement, labelled Add the Account identity profile. Setting the profile with Update Account clears it and resumes onboarding. The group does not have to be opened again.
Requires an API key with read access on the virtual_accounts scope.
Path Parameters
string
required
The account’s external ID (starts with
acct_). It must belong to your customer: your own account, one of your end-customer accounts, or your fee-collection account.string
required
The group’s external ID (starts with
vag_). A group that belongs to another account returns 404.Response
Returns every field of the list item, plusrequirements and agreements.
string
Virtual account group identifier (starts with
vag_)string
Always returns
"virtual_account_group"string
Account the group belongs to (starts with
acct_)string
Group type, for example
business_virtual_accounts. See List Group Types.string
Activation state, controlled by Hop:
pending, enabled or disabledstring
KYC/KYB progress:
action_needed, under_review, approved, rejected, suspended or closed. See Create Virtual Account Group for what each means and how they transition.string
ISO 8601 timestamp when Hop first enabled the group, or
nullstring
ISO 8601 timestamp when onboarding most recently became
suspended, or nullstring
ISO 8601 timestamp when onboarding was closed, or
nullarray
Current onboarding actions for this group. An empty array means nothing is outstanding. Either the provider is reviewing what you sent, or onboarding is done.
Show Requirement Fields
Show Requirement Fields
string
Opaque Hop identifier for this requirement, never a provider code: for example
req_9c1f4a7b2e06d38a5f4c1b72, account_profile.required or account_profile.customer_creation. Quote it as requirement_key when you satisfy a document requirement through Upload Document.string
What kind of action clears it:
document: upload evidence with Upload Document, choosing a type fromaccepted_document_typesaccount_profile: identity data is missing or invalid on the account itself. The keyaccount_profile.requiredmeans no identity profile has been set at all, set one with Update Account; on any otheraccount_profilekey,reasonnames the fields to correct.associated_person: data is missing on a director, signer or beneficial owner of the account, or no associated person has been added yet. Only business accounts raise it; individual accounts have no associated persons.hosted_verification: the subject must complete a provider-hosted verification flow. Reserved; no currently configured provider raises it.
string
Human-readable description of the action, for example
Complete the business profile (max 255 characters). Safe to show to the end customer.string
The associated person the action is about (starts with
aap_), or null. null with is_target_resolved true means the action is at account level.boolean
Whether a person-targeted action could be matched to an associated person Hop holds.
false means the provider is asking about a subject Hop cannot map. You cannot clear it yourself, so contact Hop.array
Document types that satisfy a
document requirement, for example ["passport", "national_id"]. Empty for every other requirement type.string
Why the requirement was raised, for example the exact fields to update (max 1000 characters), or
nullobject
Progress on the group’s agreements
Show Agreement Summary Fields
Show Agreement Summary Fields
string
not_started (nothing has been synced from the provider yet), action_needed (at least one agreement is pending), rejected (at least one agreement was rejected) or complete (nothing pending or rejected)array
Ids of the agreements still awaiting a response (each starts with
agr_). Pass them to Submit Agreement Actions; List Agreements has their titles and content.string
ISO 8601 timestamp when created
string
ISO 8601 timestamp when last updated
string
Actor that created the group: the API key id (starts with
ak_) when opened through this API, otherwise the actor Hop recordedstring
Actor that last updated the group, or
nullErrors
| Status | code | When |
|---|---|---|
404 | RESOURCE_NOT_FOUND | account_id is unknown or belongs to another customer, or group_id is unknown or belongs to another account |
Request Example
curl "https://api.hopnow.io/v1/accounts/acct_ka44qsvpo8q3wtzuwfqf0h6u/virtual-account-groups/vag_7m2k9x4c1b6v3n8q5z0j2p7t" \
-H "X-API-Key: your_api_key" \
-H "X-Signature: hmac_signature" \
-H "X-Timestamp: 1234567890" \
-H "X-Nonce: abc123"
Response Example
{
"id": "vag_7m2k9x4c1b6v3n8q5z0j2p7t",
"object": "virtual_account_group",
"account_id": "acct_ka44qsvpo8q3wtzuwfqf0h6u",
"type": "business_virtual_accounts",
"status": "pending",
"onboarding_status": "action_needed",
"enabled_at": null,
"suspended_at": null,
"closed_at": null,
"requirements": [
{
"key": "account_profile.customer_creation",
"type": "account_profile",
"label": "Complete the business profile",
"associated_person_id": null,
"is_target_resolved": true,
"accepted_document_types": [],
"reason": "Update these Account fields: business_industry, registration_number"
},
{
"key": "req_9c1f4a7b2e06d38a5f4c1b72",
"type": "document",
"label": "Proof of identity",
"associated_person_id": "aap_5r8t1v4x6z0b3n5q7w2e9y4u",
"is_target_resolved": true,
"accepted_document_types": ["passport", "national_id"],
"reason": null
}
],
"agreements": {
"status": "action_needed",
"pending_ids": ["agr_3f8k1m5p9r2t6v4x7z0b3n5q"]
},
"created": "2026-01-15T10:00:00Z",
"updated": "2026-01-16T08:12:00Z",
"created_by": "ak_3f7k9m2p5r8t1v4x6z0b3n5q",
"updated_by": null
}