Charge a user a custom fee
curl --request POST \
--url https://api-dev.rain.xyz/v1/issuing/users/{userId}/charges \
--header 'Api-Key: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"amount": 2,
"description": "<string>"
}
'import requests
url = "https://api-dev.rain.xyz/v1/issuing/users/{userId}/charges"
payload = {
"amount": 2,
"description": "<string>"
}
headers = {
"Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({amount: 2, description: '<string>'})
};
fetch('https://api-dev.rain.xyz/v1/issuing/users/{userId}/charges', 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-dev.rain.xyz/v1/issuing/users/{userId}/charges",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'amount' => 2,
'description' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Api-Key: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api-dev.rain.xyz/v1/issuing/users/{userId}/charges"
payload := strings.NewReader("{\n \"amount\": 2,\n \"description\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Api-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
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-dev.rain.xyz/v1/issuing/users/{userId}/charges")
.header("Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"amount\": 2,\n \"description\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-dev.rain.xyz/v1/issuing/users/{userId}/charges")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"amount\": 2,\n \"description\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"createdAt": "2023-11-07T05:31:56Z",
"amount": 2,
"description": "<string>"
}Users
Charge a user a custom fee
POST
/
issuing
/
users
/
{userId}
/
charges
Charge a user a custom fee
curl --request POST \
--url https://api-dev.rain.xyz/v1/issuing/users/{userId}/charges \
--header 'Api-Key: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"amount": 2,
"description": "<string>"
}
'import requests
url = "https://api-dev.rain.xyz/v1/issuing/users/{userId}/charges"
payload = {
"amount": 2,
"description": "<string>"
}
headers = {
"Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({amount: 2, description: '<string>'})
};
fetch('https://api-dev.rain.xyz/v1/issuing/users/{userId}/charges', 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-dev.rain.xyz/v1/issuing/users/{userId}/charges",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'amount' => 2,
'description' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Api-Key: <api-key>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api-dev.rain.xyz/v1/issuing/users/{userId}/charges"
payload := strings.NewReader("{\n \"amount\": 2,\n \"description\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Api-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
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-dev.rain.xyz/v1/issuing/users/{userId}/charges")
.header("Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"amount\": 2,\n \"description\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-dev.rain.xyz/v1/issuing/users/{userId}/charges")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"amount\": 2,\n \"description\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"createdAt": "2023-11-07T05:31:56Z",
"amount": 2,
"description": "<string>"
}Read the guides before using this pageTo use this endpoint properly, make sure you are up to date on our managing users guides.
Rain-managed vs Partner-managed programs
Rain-managed programs: Custom charges are automatically processed and applied directly to the userβs balance. No additional ledgering required on your side. Partner-managed programs: You typically handle fees through your own ledgering system. This API provides an alternative for one-off charges when needed.Charges apply after authorizationCustom charges are applied after the authorization process, which means users may go negative if their balance is insufficient to cover the charge.
FX/XB fees are handled differentlyForeign exchange (FX) and cross-border (XB) fees are configured at the tenant level and included during authorization. See Pricing and fees for more information.
Example
// Apply a \$5 card setup fee when a user requests a new card
const charge = await rain.createUserCharge({
userId: "user_123",
amount: 500, // \$5.00 in cents
description: "Card setup fee",
idempotencyKey: "setup_fee_user_123_card_456"
});
Best practicesAlways use idempotency keys to prevent duplicate charges. Provide clear descriptions for charges to help with user support. Monitor user balances to avoid excessive negative balances, and consider notifying users before applying charges when possible.
Authorizations
Path Parameters
Id of the user to create a custom fee charge for
Body
application/json
Description of the custom fee charge