Issue an account

Use an account application when a customer needs a bank-backed account. Gravv validates the application, runs onboarding, and issues the internal account after approval.

Before you start, create the customer and collect the required KYC or KYB data. You also need the agreement ID for the terms the applicant accepts. Every POST request in this recipe requires an Idempotency-Key. Use a different key for each operation and reuse it only for an identical retry.

Flow overview

sequenceDiagram
    autonumber
    actor Client
    participant API as Gravv API
    participant Review as Account review

    Client->>API: Create draft application
    Client->>API: Accept terms
    Client->>API: Submit and process application
    API->>Review: Validate and provision account
    alt More information or review required
        Review-->>API: manual_review or rejected
        API-->>Client: Status and safe reason
        Client->>API: Correct and resubmit when allowed
    else Application approved
        Review-->>API: approved
        API-->>Client: Issued account
    end
    opt Processing continues asynchronously
        loop Until terminal status
            Client->>API: Retrieve application
            API-->>Client: processing, manual_review, approved, rejected, or expired
        end
    end

Create an individual or business application. The application starts in draft status.

curl --request POST \
--url https://api.gravv.xyz/v1/accounts/applications \
--header 'Api-Key: <API_KEY>' \
--header 'Idempotency-Key: account-application-<UUID>' \
--header 'Content-Type: application/json' \
--data '{
"customer_id": "123e4567-e89b-12d3-a456-426614174000",
"application_type": "individual",
"data": {
"account_type": "regular",
"currency": "USD",
"blockchain_network": "polygon",
"agreement_id": "agr_123",
"individual": {
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"phone": "+14155552671",
"date_of_birth": "1980-01-01",
"nationality": "US",
"identification_type": "passport",
"identification_number": "P1234567",
"identification_country": "US",
"identification_expiry": "2030-01-01",
"address": {
"street_line_1": "123 Main St",
"city": "San Francisco",
"state": "CA",
"postal_code": "94105",
"country": "US"
},
"id_document_front": "data:application/pdf;base64,<BASE64_DATA>",
"proof_of_address_document": "data:application/pdf;base64,<BASE64_DATA>"
}
}
}'
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"customer_id": "123e4567-e89b-12d3-a456-426614174000",
"application_type": "individual",
"status": "draft",
"validation_errors": []
},
"error": null
}

Save data.id as the application ID.

Record the applicant's acceptance while the application is still in draft status.

curl --request POST \
--url https://api.gravv.xyz/v1/accounts/applications/tos \
--header 'Api-Key: <API_KEY>' \
--header 'Idempotency-Key: account-tos-<UUID>' \
--header 'Content-Type: application/json' \
--data '{
"application_id": "550e8400-e29b-41d4-a716-446655440001",
"agreement_id": "agr_123"
}'
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"status": "draft",
"metadata": {
"tos_accepted": true
}
},
"error": null
}

Submit the application and start account creation in one call.

curl --request POST \
--url https://api.gravv.xyz/v1/accounts/applications/550e8400-e29b-41d4-a716-446655440001/submit-and-process \
--header 'Api-Key: <API_KEY>' \
--header 'Idempotency-Key: account-submit-process-<UUID>'
{
"data": {
"application": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"status": "processing"
},
"processing_result": {
"application_id": "550e8400-e29b-41d4-a716-446655440001",
"status": "processing",
"account": null,
"errors": []
},
"is_fully_processed": false
},
"error": null
}

If is_fully_processed is true, save processing_result.account.id. Otherwise, continue to the next step.

Retrieve the application until its status becomes approved. If it enters manual_review, wait for a decision and display the safe reason when one is returned. Stop and review validation_errors if it becomes rejected or expired.

curl --request GET \
--url https://api.gravv.xyz/v1/accounts/applications/550e8400-e29b-41d4-a716-446655440001 \
--header 'Api-Key: <API_KEY>'
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440001",
"customer_id": "123e4567-e89b-12d3-a456-426614174000",
"application_type": "individual",
"status": "approved",
"validation_errors": []
},
"error": null
}

List the customer's accounts after approval and save the new account ID.

curl --request GET \
--url 'https://api.gravv.xyz/v1/accounts?customer_id=123e4567-e89b-12d3-a456-426614174000' \
--header 'Api-Key: <API_KEY>'
{
"data": {
"items": [
{
"id": "a4d83e55-435e-41c9-9a0b-dcb99f690c95",
"customer_id": "123e4567-e89b-12d3-a456-426614174000",
"currency": "USD",
"type": "regular",
"status": "active",
"wallet_address": "0xf73bdd069dc31aa8f334b177b175936ba98237a2",
"virtual_account_id": "73cea894-bca7-43e2-b278-02bd6d991e2e"
}
],
"page": 1,
"items_per_page": 20,
"total_items": 1,
"total_pages": 1
},
"error": null
}

See Account applications for field requirements and lifecycle details.

Was this page helpful?