Avoid a payout pause for sender details

Send a real person's name, date of birth and address with a business's payouts, and resume a transfer that paused for sender details.

This recipe sends a real person's name, date of birth and address with a business's payouts, and resumes a transfer that paused for sender details.

Who it is for. Adire Logistics, the business from Onboard a business and its owners, which pays a supplier in Ghana 250.00 USD. It is also for any business whose older customers have no date of birth or address.

Status. Available. Only some payout routes need sender details. The API has no call that lists those routes in advance, so always send the details.

Money example

  1. Adire sends 250.00 USD to a Ghana mobile-money payee. The bank that pays out on that route must name a real person as the sender: first and last name, date of birth, email, street address and country.
  2. Adire is a company, so its profile has a business name but no person's name or date of birth. Gravv creates the transfer paused, instead of sending it and having the bank refuse it. Gravv charges your fee now, as for any transfer, and pays nothing out yet.
  3. You resume with the director's name and date of birth. Gravv pays out the 250.00 USD and charges no second fee.
  4. If you never resume, the pause expires after 72 hours by default (expires_at is exact). The transfer fails with reason sender_details_expired, and Gravv refunds the fee.

Before you start

  • The customer you send the transfer for (customer_id), and a funded source account.
  • For a business, the name, date of birth, country and address of a director or authorized signatory, such as the associated person you created.
  • An email on the customer's profile. Gravv reads the email only from the profile.

Find out what is required

The paused response lists one requirements[] entry per missing detail. Its type is the exact additional_information field to send:

requirements[].type What to send
remitter_full_name First and last name, such as "Tunde Bakare". Gravv splits it at the first space, so one word still counts as missing
remitter_date_of_birth "1984-07-22"
remitter_address The whole object: address_line1, city, postal_code, country and state
remitter_country An ISO code, such as "NG"
customer_email This is not a body field. Add email to the customer with PUT /v1/customers/{customer_id}, then resume with {}

Gravv reads each detail first from your additional_information. For anything not sent there, Gravv reads the customer's profile.

Steps

Avoid the pause

Individual customers that you create through the API today already have a name, date of birth, email and address, so their payouts do not pause for sender details. A business customer's payouts do, so send a real person's details with every payout.

curl --request POST \
 --url https://api.gravv.xyz/v1/transfer \
 --header 'Api-Key: <API_KEY>' \
 --header 'Idempotency-Key: 47e3da9e-3600-41b1-90a2-9cc43beeb744' \
 --header 'Content-Type: application/json' \
 --data '
{
"customer_id": "0a9b8c7d-6e5f-4a3b-8c2d-1e0f9a8b7c6d",
"amount": "250.00",
"source": {
"source_type": "internal_account",
"id": "8e1a3c5b-7d9f-4b2e-a4c6-0e2f4a6c8b1d"
},
"destination": {
"destination_type": "external_account",
"id": "4f3e2d1c-0b9a-4876-9543-2a1b0c9d8e7f"
},
"client_reference": "adire-inv-3310",
"additional_information": {
"remitter_full_name": "Tunde Bakare",
"remitter_date_of_birth": "1984-07-22",
"remitter_country": "NG",
"remitter_address": {
  "address_line1": "22 Creek Road",
  "city": "Apapa",
  "postal_code": "102272",
  "state": "NG-LA",
  "country": "NG"
}
}
}
'
const response = await fetch("https://api.gravv.xyz/v1/transfer", {
method: "POST",
headers: {
"Api-Key": process.env.GRAVV_API_KEY,
"Idempotency-Key": "47e3da9e-3600-41b1-90a2-9cc43beeb744",
"Content-Type": "application/json",
},
body: JSON.stringify({
"customer_id": "0a9b8c7d-6e5f-4a3b-8c2d-1e0f9a8b7c6d",
"amount": "250.00",
"source": {
  "source_type": "internal_account",
  "id": "8e1a3c5b-7d9f-4b2e-a4c6-0e2f4a6c8b1d"
},
"destination": {
  "destination_type": "external_account",
  "id": "4f3e2d1c-0b9a-4876-9543-2a1b0c9d8e7f"
},
"client_reference": "adire-inv-3310",
"additional_information": {
  "remitter_full_name": "Tunde Bakare",
  "remitter_date_of_birth": "1984-07-22",
  "remitter_country": "NG",
  "remitter_address": {
    "address_line1": "22 Creek Road",
    "city": "Apapa",
    "postal_code": "102272",
    "state": "NG-LA",
    "country": "NG"
  }
}
}),
});
console.log(response.status, await response.json());
import os

import requests

response = requests.post(
"https://api.gravv.xyz/v1/transfer",
headers={
    "Api-Key": os.environ["GRAVV_API_KEY"],
    "Idempotency-Key": "47e3da9e-3600-41b1-90a2-9cc43beeb744",
    "Content-Type": "application/json",
},
json={
    "customer_id": "0a9b8c7d-6e5f-4a3b-8c2d-1e0f9a8b7c6d",
    "amount": "250.00",
    "source": {
        "source_type": "internal_account",
        "id": "8e1a3c5b-7d9f-4b2e-a4c6-0e2f4a6c8b1d",
    },
    "destination": {
        "destination_type": "external_account",
        "id": "4f3e2d1c-0b9a-4876-9543-2a1b0c9d8e7f",
    },
    "client_reference": "adire-inv-3310",
    "additional_information": {
        "remitter_full_name": "Tunde Bakare",
        "remitter_date_of_birth": "1984-07-22",
        "remitter_country": "NG",
        "remitter_address": {
            "address_line1": "22 Creek Road",
            "city": "Apapa",
            "postal_code": "102272",
            "state": "NG-LA",
            "country": "NG",
        },
    },
},
)
print(response.status_code, response.json())

Check that transfer_status is pending, not paused. Gravv uses the business's own email from its profile.

Fix a paused transfer

1. Recognize the pause

The transfer request returns 200, not an error:

{
  "data": {
    "amount": "250",
    "amount_currency": "USD",
    "reference": "c7d8e9f0-a1b2-4c3d-8e4f-5a6b7c8d9e0f",
    "transfer_status": "paused",
    "transaction_id": "d1e2f3a4-b5c6-4d7e-8f90-a1b2c3d4e5f6",
    "fee": "2",
    "fee_currency": "USD",
    "status": "awaiting_remitter_information",
    "pause_reason": "sender_details_required",
    "requirements": [
      {"type": "remitter_full_name", "description": "resume with additional_information.remitter_full_name: the sender's first and last name"},
      {"type": "remitter_date_of_birth", "description": "resume with additional_information.remitter_date_of_birth: the sender's date of birth as YYYY-MM-DD"}
    ],
    "expires_at": "2026-10-16T11:20:05Z"
  },
  "error": null
}

The fee shown is an example. Your fee follows your pricing. Save reference.

2. Add the email if it is listed

If customer_email is in requirements, update the customer first. The email must be unique in your business.

curl --request PUT \
 --url https://api.gravv.xyz/v1/customers/0a9b8c7d-6e5f-4a3b-8c2d-1e0f9a8b7c6d \
 --header 'Api-Key: <API_KEY>' \
 --header 'Content-Type: application/json' \
 --data '
{
"email": "finance@adirelogistics.example"
}
'
const response = await fetch("https://api.gravv.xyz/v1/customers/0a9b8c7d-6e5f-4a3b-8c2d-1e0f9a8b7c6d", {
method: "PUT",
headers: {
"Api-Key": process.env.GRAVV_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
"email": "finance@adirelogistics.example"
}),
});
console.log(response.status, await response.json());
import os

import requests

response = requests.put(
"https://api.gravv.xyz/v1/customers/0a9b8c7d-6e5f-4a3b-8c2d-1e0f9a8b7c6d",
headers={
    "Api-Key": os.environ["GRAVV_API_KEY"],
    "Content-Type": "application/json",
},
json={
    "email": "finance@adirelogistics.example",
},
)
print(response.status_code, response.json())

3. Resume with every missing field in one call

curl --request POST \
 --url https://api.gravv.xyz/v1/transfer/c7d8e9f0-a1b2-4c3d-8e4f-5a6b7c8d9e0f/resume \
 --header 'Api-Key: <API_KEY>' \
 --header 'Idempotency-Key: 0e6f40e4-59e1-445a-93aa-d829a53a7c24' \
 --header 'Content-Type: application/json' \
 --data '
{
"additional_information": {
"remitter_full_name": "Tunde Bakare",
"remitter_date_of_birth": "1984-07-22"
}
}
'
const response = await fetch("https://api.gravv.xyz/v1/transfer/c7d8e9f0-a1b2-4c3d-8e4f-5a6b7c8d9e0f/resume", {
method: "POST",
headers: {
"Api-Key": process.env.GRAVV_API_KEY,
"Idempotency-Key": "0e6f40e4-59e1-445a-93aa-d829a53a7c24",
"Content-Type": "application/json",
},
body: JSON.stringify({
"additional_information": {
  "remitter_full_name": "Tunde Bakare",
  "remitter_date_of_birth": "1984-07-22"
}
}),
});
console.log(response.status, await response.json());
import os

import requests

response = requests.post(
"https://api.gravv.xyz/v1/transfer/c7d8e9f0-a1b2-4c3d-8e4f-5a6b7c8d9e0f/resume",
headers={
    "Api-Key": os.environ["GRAVV_API_KEY"],
    "Idempotency-Key": "0e6f40e4-59e1-445a-93aa-d829a53a7c24",
    "Content-Type": "application/json",
},
json={
    "additional_information": {
        "remitter_full_name": "Tunde Bakare",
        "remitter_date_of_birth": "1984-07-22",
    },
},
)
print(response.status_code, response.json())
{
  "data": {
    "transfer_id": "c7d8e9f0-a1b2-4c3d-8e4f-5a6b7c8d9e0f",
    "status": "approved_awaiting_execution",
    "transfer_status": "pending",
    "resumed": true
  },
  "error": null
}

Gravv merges the fields you send one by one into the original request, so send only what the response listed. The resume runs the transfer's checks again: balance, payee, rate, limits and sender details.

4. If the answer is resumed: false

The response lists what is still missing. Send those details in a new resume with another new key. The same key replays the old resumed: false.

5. Fix the profile for next time

For a person, add date_of_birth and address with PUT /v1/customers/{customer_id}, so later payouts do not pause. For a business, keep sending the director in additional_information.

What can go wrong

Response Why Fix
Every payout for a business pauses with remitter_full_name and remitter_date_of_birth A business profile has no person's name or date of birth Send a director in additional_information on each payout
remitter_full_name still listed after you sent "Tunde" With one word, the last name is empty Send a first and last name
remitter_address still listed after you sent only city An address you send replaces the profile address as a whole Send address_line1, city and postal_code together
remitter_country listed although you sent "Nigeria" The country must be an ISO code Send "NG"
400 remitter_date_of_birth must be a date as YYYY-MM-DD / remitter_date_of_birth cannot be in the future The format is wrong, or the year has a typo Send a date such as "1984-07-22", with a new key
400 invalid request body: json: unknown field "remitter_full_name" on resume You sent the field at the top level Nest it inside additional_information
410 this paused transfer has expired and can no longer be resumed; please initiate a new transfer The pause passed expires_at, and Gravv refunded the fee Start a new transfer, with additional_information
410 this paused transfer was cancelled and can no longer be resumed; please initiate a new transfer Gravv cancelled it (reason sender_details_cancelled) Start a new transfer
Support cannot release it for you The paying bank would refuse it without the details Resume with the details

Webhooks you will receive

  1. transfer.requires_information, with event_data.status paused, reason sender_details_required, and limit_details.requirements[], the same list as in the response.
  2. After a successful resume, transfer.resumed (reason resumed), then the usual transfer.status.pending and transfer.status.completed.
  3. If the pause expires or Gravv cancels it, transfer.status.failed with reason sender_details_expired or sender_details_cancelled.

See Transfer events.

Testing in sandbox

Whether a sandbox payout reaches a route that needs sender details depends on the sandbox setup, so the pause may not appear. You can test that Gravv accepts a business payout with additional_information.

Reference

Was this page helpful?