> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.haloinvest.ng/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.haloinvest.ng/_mcp/server.

# Debit customer account

POST https://api.haloinvest.ng/api/banking/transactions/debit-user-account
Content-Type: application/json

Debits a customer's account and credits your pool account or one of your business accounts. The amount is in kobo.

The account to debit must be one your business opened for its own customer. Set `credit_pool_account` to true to credit your pool account, or false and send `account_to_credit`, which must be your pool account or one of your business accounts.

The request runs as two legs: the debit and then the credit. If the credit fails, Halo reverses the debit.

Each request is checked against your per-transaction limit (default 500,000,000 kobo, NGN 5,000,000) and your daily limit (default 5,000,000,000 kobo, NGN 50,000,000). Halo can set different limits for your business. Transfers that are still unconfirmed count toward the daily limit.

The `idempotency_key` is required. Sending a key you already used returns the outcome recorded for it and sends nothing to the bank again. After a refusal or a reversal, use a new key to try again. A 202 means the outcome is unknown: do not retry, and check the reference named in the message with check-transaction-status.

Reference: https://docs.haloinvest.ng/api-reference/transfers-and-debits/debit-user-account

## Authentication

- `Authorization` header (bearer token, required) — Your Halo partner API key, sent as `Authorization: Bearer <key>`.

## Request

### Body (application/json)

This endpoint expects an object.

- `account_number` (string, required) — The customer account to debit. It must be one your business opened.
- `amount` (integer, required) — Amount in kobo. Must be greater than 0.
- `credit_pool_account` (boolean, required) — True to credit your pool account. False to credit account_to_credit.
- `idempotency_key` (string, required) — Your unique key for this request, at most 64 characters.
- `account_to_credit` (string, optional, nullable) — Required when credit_pool_account is false. Your pool account or one of your business accounts.
- `narration` (string, optional, nullable) — Narration, at most 100 characters. Defaults to "Debit Account".

## Response

### 200

Both legs succeeded.

- `status` (boolean, required) — True on success, false otherwise.
- `message` (EnvelopeMessage, required) — A short message. On a 422 validation failure it is an object of field names to error lists.
- `status_code` (integer, required) — The HTTP status code.
- `data` (any, optional) — The result. Left out on most errors.

### 202

Outcome unknown. Do not retry. Check the status with the reference in the message.

- `status` (boolean, required) — True on success, false otherwise.
- `message` (EnvelopeMessage, required) — A short message. On a 422 validation failure it is an object of field names to error lists.
- `status_code` (integer, required) — The HTTP status code.
- `data` (any, optional) — The result. Left out on most errors.

## Errors

### 400 Bad Request Error

The debit was refused, or the credit failed.

- `status` (boolean, required) — True on success, false otherwise.
- `message` (EnvelopeMessage, required) — A short message. On a 422 validation failure it is an object of field names to error lists.
- `status_code` (integer, required) — The HTTP status code.
- `data` (any, optional) — The result. Left out on most errors.

### 401 Unauthorized Error

The API key is missing or not recognised, or your business is switched off.

- `error` (UnauthorizedErrorError, optional)

### 403 Forbidden Error

The account is held by Halo for investments and cannot be debited.

- `status` (boolean, required) — True on success, false otherwise.
- `message` (EnvelopeMessage, required) — A short message. On a 422 validation failure it is an object of field names to error lists.
- `status_code` (integer, required) — The HTTP status code.
- `data` (any, optional) — The result. Left out on most errors.

### 404 Not Found Error

The account to debit is not one your business opened for its customer.

- `status` (boolean, required) — True on success, false otherwise.
- `message` (EnvelopeMessage, required) — A short message. On a 422 validation failure it is an object of field names to error lists.
- `status_code` (integer, required) — The HTTP status code.
- `data` (any, optional) — The result. Left out on most errors.

### 422 Unprocessable Entity Error

The credit account is not allowed, a limit was exceeded, or the request failed validation.

- `status` (boolean, required) — True on success, false otherwise.
- `message` (EnvelopeMessage, required) — A short message. On a 422 validation failure it is an object of field names to error lists.
- `status_code` (integer, required) — The HTTP status code.
- `data` (any, optional) — The result. Left out on most errors.

### 429 Too Many Requests Error

Too many requests. Wait and try again.

- `status` (boolean, required) — True on success, false otherwise.
- `message` (EnvelopeMessage, required) — A short message. On a 422 validation failure it is an object of field names to error lists.
- `status_code` (integer, required) — The HTTP status code.
- `data` (any, optional) — The result. Left out on most errors.

## Types

### EnvelopeMessage

A short message. On a 422 validation failure it is an object of field names to error lists.

- string
- map from string to list of string

### UnauthorizedErrorError

- `message` (string, optional)

## Examples

### Transfers and debits_debitUserAccount_example

**Request**

```json
{
  "account_number": "1100000001",
  "amount": 150000,
  "credit_pool_account": true,
  "idempotency_key": "order-1001-debit"
}
```

**Response**

```json
{
  "status": true,
  "message": "Request Successful",
  "status_code": 200,
  "data": null
}
```

**SDK Code**

```python Transfers and debits_debitUserAccount_example
import requests

url = "https://api.haloinvest.ng/api/banking/transactions/debit-user-account"

payload = {
    "account_number": "1100000001",
    "amount": 150000,
    "credit_pool_account": True,
    "idempotency_key": "order-1001-debit"
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript Transfers and debits_debitUserAccount_example
const url = 'https://api.haloinvest.ng/api/banking/transactions/debit-user-account';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"account_number":"1100000001","amount":150000,"credit_pool_account":true,"idempotency_key":"order-1001-debit"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Transfers and debits_debitUserAccount_example
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.haloinvest.ng/api/banking/transactions/debit-user-account"

	payload := strings.NewReader("{\n  \"account_number\": \"1100000001\",\n  \"amount\": 150000,\n  \"credit_pool_account\": true,\n  \"idempotency_key\": \"order-1001-debit\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Transfers and debits_debitUserAccount_example
require 'uri'
require 'net/http'

url = URI("https://api.haloinvest.ng/api/banking/transactions/debit-user-account")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"account_number\": \"1100000001\",\n  \"amount\": 150000,\n  \"credit_pool_account\": true,\n  \"idempotency_key\": \"order-1001-debit\"\n}"

response = http.request(request)
puts response.read_body
```

```java Transfers and debits_debitUserAccount_example
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.haloinvest.ng/api/banking/transactions/debit-user-account")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"account_number\": \"1100000001\",\n  \"amount\": 150000,\n  \"credit_pool_account\": true,\n  \"idempotency_key\": \"order-1001-debit\"\n}")
  .asString();
```

```php Transfers and debits_debitUserAccount_example
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.haloinvest.ng/api/banking/transactions/debit-user-account', [
  'body' => '{
  "account_number": "1100000001",
  "amount": 150000,
  "credit_pool_account": true,
  "idempotency_key": "order-1001-debit"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Transfers and debits_debitUserAccount_example
using RestSharp;

var client = new RestClient("https://api.haloinvest.ng/api/banking/transactions/debit-user-account");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"account_number\": \"1100000001\",\n  \"amount\": 150000,\n  \"credit_pool_account\": true,\n  \"idempotency_key\": \"order-1001-debit\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Transfers and debits_debitUserAccount_example
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "account_number": "1100000001",
  "amount": 150000,
  "credit_pool_account": true,
  "idempotency_key": "order-1001-debit"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.haloinvest.ng/api/banking/transactions/debit-user-account")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Debit unconfirmed

**Request**

```json
{
  "account_number": "1100000001",
  "amount": 150000,
  "credit_pool_account": true,
  "idempotency_key": "order-1001-debit"
}
```

**Response**

```json
{
  "status": false,
  "message": "The debit has not been confirmed by the bank yet. Do not retry; check its status with reference PD1A2B3C4D5E.",
  "status_code": 202,
  "data": null
}
```

**SDK Code**

```python Debit unconfirmed
import requests

url = "https://api.haloinvest.ng/api/banking/transactions/debit-user-account"

payload = {
    "account_number": "1100000001",
    "amount": 150000,
    "credit_pool_account": True,
    "idempotency_key": "order-1001-debit"
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript Debit unconfirmed
const url = 'https://api.haloinvest.ng/api/banking/transactions/debit-user-account';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"account_number":"1100000001","amount":150000,"credit_pool_account":true,"idempotency_key":"order-1001-debit"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Debit unconfirmed
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.haloinvest.ng/api/banking/transactions/debit-user-account"

	payload := strings.NewReader("{\n  \"account_number\": \"1100000001\",\n  \"amount\": 150000,\n  \"credit_pool_account\": true,\n  \"idempotency_key\": \"order-1001-debit\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Debit unconfirmed
require 'uri'
require 'net/http'

url = URI("https://api.haloinvest.ng/api/banking/transactions/debit-user-account")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"account_number\": \"1100000001\",\n  \"amount\": 150000,\n  \"credit_pool_account\": true,\n  \"idempotency_key\": \"order-1001-debit\"\n}"

response = http.request(request)
puts response.read_body
```

```java Debit unconfirmed
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.haloinvest.ng/api/banking/transactions/debit-user-account")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"account_number\": \"1100000001\",\n  \"amount\": 150000,\n  \"credit_pool_account\": true,\n  \"idempotency_key\": \"order-1001-debit\"\n}")
  .asString();
```

```php Debit unconfirmed
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.haloinvest.ng/api/banking/transactions/debit-user-account', [
  'body' => '{
  "account_number": "1100000001",
  "amount": 150000,
  "credit_pool_account": true,
  "idempotency_key": "order-1001-debit"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Debit unconfirmed
using RestSharp;

var client = new RestClient("https://api.haloinvest.ng/api/banking/transactions/debit-user-account");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"account_number\": \"1100000001\",\n  \"amount\": 150000,\n  \"credit_pool_account\": true,\n  \"idempotency_key\": \"order-1001-debit\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Debit unconfirmed
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "account_number": "1100000001",
  "amount": 150000,
  "credit_pool_account": true,
  "idempotency_key": "order-1001-debit"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.haloinvest.ng/api/banking/transactions/debit-user-account")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Credit unconfirmed

**Request**

```json
{
  "account_number": "1100000001",
  "amount": 150000,
  "credit_pool_account": true,
  "idempotency_key": "order-1001-debit"
}
```

**Response**

```json
{
  "status": false,
  "message": "The account was debited and the credit has not been confirmed yet. Do not retry; check its status with reference PC1A2B3C4D5E.",
  "status_code": 202,
  "data": null
}
```

**SDK Code**

```python Credit unconfirmed
import requests

url = "https://api.haloinvest.ng/api/banking/transactions/debit-user-account"

payload = {
    "account_number": "1100000001",
    "amount": 150000,
    "credit_pool_account": True,
    "idempotency_key": "order-1001-debit"
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript Credit unconfirmed
const url = 'https://api.haloinvest.ng/api/banking/transactions/debit-user-account';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"account_number":"1100000001","amount":150000,"credit_pool_account":true,"idempotency_key":"order-1001-debit"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Credit unconfirmed
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.haloinvest.ng/api/banking/transactions/debit-user-account"

	payload := strings.NewReader("{\n  \"account_number\": \"1100000001\",\n  \"amount\": 150000,\n  \"credit_pool_account\": true,\n  \"idempotency_key\": \"order-1001-debit\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Credit unconfirmed
require 'uri'
require 'net/http'

url = URI("https://api.haloinvest.ng/api/banking/transactions/debit-user-account")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"account_number\": \"1100000001\",\n  \"amount\": 150000,\n  \"credit_pool_account\": true,\n  \"idempotency_key\": \"order-1001-debit\"\n}"

response = http.request(request)
puts response.read_body
```

```java Credit unconfirmed
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.haloinvest.ng/api/banking/transactions/debit-user-account")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"account_number\": \"1100000001\",\n  \"amount\": 150000,\n  \"credit_pool_account\": true,\n  \"idempotency_key\": \"order-1001-debit\"\n}")
  .asString();
```

```php Credit unconfirmed
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.haloinvest.ng/api/banking/transactions/debit-user-account', [
  'body' => '{
  "account_number": "1100000001",
  "amount": 150000,
  "credit_pool_account": true,
  "idempotency_key": "order-1001-debit"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Credit unconfirmed
using RestSharp;

var client = new RestClient("https://api.haloinvest.ng/api/banking/transactions/debit-user-account");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"account_number\": \"1100000001\",\n  \"amount\": 150000,\n  \"credit_pool_account\": true,\n  \"idempotency_key\": \"order-1001-debit\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Credit unconfirmed
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "account_number": "1100000001",
  "amount": 150000,
  "credit_pool_account": true,
  "idempotency_key": "order-1001-debit"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.haloinvest.ng/api/banking/transactions/debit-user-account")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```