# Decentralized (EasyPost-Managed Billing) Implementation Guide

## Overview

The **Decentralized** white-label option in Forge enables Platforms and Marketplaces to embed shipping capabilities **without managing postage and other
fees** on behalf of their customers. This implementation option has unique onboarding requirements that can be found in this guide.

For this option, the sub-account object type is the `ReferralCustomer`.

  **IMPORTANT:** Before starting, review the prerequisites section of the
  Get Started with Forge guide to understand white-label
  implementations with EasyPost.

Related:

- [ReferralCustomers](https://docs.easypost.com/docs/users/referral-customers)

---

## Create a ReferralCustomer

A `ReferralCustomer` is an independent sub account with its own billing methods and wallet.
These users can be created via API or through the Forge Dashboard.

ReferralCustomer users can be created using **one of two methods**:

### API Integration

1. Use the POST /referral_customers API to create a `ReferralCustomer` account.

   1. This request must be made in **Production** mode using the parent account's EasyPost API Key.
   2. Securely store the **API keys** for future use. If lost, they can be retrieved from the **Sub Account Details** page.

[Content omitted: API request example. Review the rendered documentation for complete request payloads, parameters, and code samples.]

### Forge Dashboard

1. Log in to the Forge Dashboard.
2. Navigate to the Sub Accounts section of the Forge Dashboard.
3. Click **New Referral Account** and complete the required fields.
4. Securely store the API keys generated for the `ReferralCustomer` user. If lost, API keys can be retrieved through the **Sub Account Details** page.

ReferralCustomer accounts are automatically enrolled in a pay-as-you-go EasyPost subscription that enables access to standard rates, postage, insurance,
and other shipping-related features.

  **IMPORTANT:** Creating a `ReferralCustomer` via API certifies that the `ReferralCustomer` user agrees to the
  EasyPost Terms of Service.

---

## Managing ReferralCustomer Accounts via Customer Portals

ReferralCustomer users can manage onboarding and account configuration through EasyPost-hosted portals.

### Onboarding Portal

Co-branded, conversion-optimized flow for collecting billing and account details.

### Account Management Portal

Customizable interface for managing carriers, billing, and other account-level settings.

Portals are accessed via the `POST /customer_portal/account_link` endpoint.

### Advanced Shipping

Platforms may optionally enable Advanced Shipping, a white-labeled shipping interface that allows sub-accounts to purchase labels and manage
shipments through a hosted experience.

When Advanced Shipping is used with the Decentralized (EasyPost-Managed Billing) option, shipments and billing continue to be processed through the
ReferralCustomer's wallet and carrier configuration.

### Example: POST /customer_portal/account_link

#### cURL

```shell
curl -X POST https://api.easypost.com/v2/customer_portal/account_link \
  -u "EASYPOST_API_KEY": \
  -H 'Content-Type: application/json' \
  -d '{
    "session_type": "account_management",
    "user_id": "user_...",
    "refresh_url": "https://example.com/refresh",
    "return_url": "https://example.com/return",
    "metadata": {"target": "wallet"}
  }'
```

Related:

- [Advanced Shipping](https://support.easypost.com/hc/en-us/articles/44018208194829-Forge-Advanced-Shipping)

---

## ReferralCustomer Billing Management

Platforms and marketplaces must build an interface that allows customers to:

- Set up Payment Methods
- Manage Wallet Settings within their application.

  **IMPORTANT:** If Stripe Connect is already in use to collect customer payments, the
  Decentralized with Stripe Connect Guide provides an
  expedited integration process.

---

## Step 1: Set up the Stripe.js Client

EasyPost uses the Stripe.js client to securely add payment methods for `ReferralCustomer` users.

1. The Stripe Public Key must be retrieved before initializing Stripe.js.

[Content omitted: API request example. Review the rendered documentation for complete request payloads, parameters, and code samples.]

2. Include Stripe.js in the user's browser:

   `<script src="https://js.stripe.com/v3/"></script>`

3. Once the Stripe.js script is loaded in the DOM, the Stripe.js client can then be initialized using the public key retrieved above.

   `const stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx');`

---

## Step 2: Create and Attach Payment Methods

The Forge Decentralized option without Stripe Connect offers **credit card** and **bank account** payment methods. Each `ReferralCustomer` user can
have one primary and one secondary payment method.

### Adding Credit Cards

1. Retrieve a single-use unique `client_secret` using `EasyPost’s POST /beta/setup_intents` endpoint to be used with Stripe Elements.

### Example: POST /beta/setup_intents

#### cURL

```shell
curl -X POST "https://api.easypost.com/beta/setup_intents" \
  -u "$REFERRAL_USER_API_KEY:" \
  -H "Content-Type: application/json"
```

#### Go

```go
package example

import (
	"fmt"

	"github.com/EasyPost/easypost-go/v5"
)

func createStripeCreditCardSecret() {
	client := easypost.New("EASYPOST_API_KEY")

	response, _ := client.BetaCreateCreditCardClientSecret()

	fmt.Println(response)
}
```

#### Java

```java
package billing;

import com.easypost.exception.EasyPostException;
import com.easypost.service.EasyPostClient;

public class CreateStripeCreditCardSecret {
    public static void main(String[] args) throws EasyPostException {
        EasyPostClient client = new EasyPostClient("EASYPOST_API_KEY");

        ClientSecret response = client.betaReferralCustomer.createCreditCardClientSecret();

        System.out.println(response);
    }
}
```

#### C#

```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using EasyPost;
using Newtonsoft.Json;

namespace EasyPostExamples
{
    public class Examples
    {
        public static async Task Main()
        {
            var client = new EasyPost.Client(new EasyPost.ClientConfiguration("EASYPOST_API_KEY"));

            EasyPost.Models.API.StripeClientSecret response = await client.Beta.ReferralCustomer.CreateCreditCardClientSecret();

            Console.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));
        }
    }
}
```

#### Node.js

```javascript
const EasyPostClient = require('@easypost/api');

const client = new EasyPostClient('EASYPOST_API_KEY');

(async () => {
  const response = await client.BetaReferralCustomer.createCreditCardClientSecret();

  console.log(response);
})();
```

#### PHP

```php
<?php

$client = new \EasyPost\EasyPostClient('EASYPOST_API_KEY');

$response = $client->betaReferralCustomer->createCreditCardClientSecret();

echo $response;
```

#### Python

```python
import easypost

client = easypost.EasyPostClient("EASYPOST_API_KEY")

response = client.beta_referral_customer.create_credit_card_client_secret()

print(response)
```

#### Ruby

```ruby
require 'easypost'

client = EasyPost::Client.new(api_key: 'EASYPOST_API_KEY')

response = client.beta_referral_customer.create_credit_card_client_secret

puts response
```

2. Using the Stripe.js client, use Stripe Elements to create a secure form for collecting credit card details and mount it to the DOM. The appearance and layout of
   this element can be customized using the options available in the Stripe create_element documentation. An event listener is also needed for handling errors and collecting the Stripe payment method ID.
3. Initialize Stripe Elements and capture the payment method ID.
4. Attach the credit card to the`ReferralCustomer` user’s account using EasyPost’s `POST /credit_cards` endpoint with the payment method ID previously retrieved.

### Example: POST /credit_cards

#### cURL

```shell
curl -X POST https://api.easypost.com/v2/credit_cards \
  -u "$REFERRAL_USER_API_KEY": \
  -H "Content-Type: application/json" \
  -d '{
    "credit_card": {
      "payment_method_id": "pm_...",
      "priority": "primary"
    }
  }'
```

#### Go

```go
package example

import (
	"fmt"

	"github.com/EasyPost/easypost-go/v5"
)

func createEpCreditCard() {
	client := easypost.New("EASYPOST_API_KEY")

	creditCard, _ := client.AddReferralCustomerCreditCard("REFERRAL_USER_API_KEY", &easypost.CreditCardOptions{
		Number:   "0123456789101234",
		ExpMonth: "01",
		ExpYear:  "2025",
		Cvc:      "111",
	}, easypost.PrimaryPaymentMethodPriority)

	fmt.Println(creditCard)
}
```

#### Java

```java
package referral;

import com.easypost.exception.EasyPostException;
import com.easypost.service.EasyPostClient;

public class Create {
    public static void main(String[] args) throws EasyPostException {
        EasyPostClient client = new EasyPostClient("EASYPOST_API_KEY");

        PaymentMethodObject creditCard = client.referralCustomer.addCreditCardToUser("REFERRAL_USER_API_KEY",
                "0123456789101234", 01, 2025, "111", PaymentMethod.Priority.PRIMARY);

        System.out.println(referralUser);
    }
}
```

#### C#

```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using EasyPost;
using Newtonsoft.Json;

namespace EasyPostExamples
{
    public class Examples
    {
        public static async Task Main()
        {
            var client = new EasyPost.Client(new EasyPost.ClientConfiguration("EASYPOST_API_KEY"));

            EasyPost.Models.API.PaymentMethod paymentMethod = await client.ReferralCustomer.AddCreditCardToUser("REFERRAL_USER_API_KEY", "0123456789101234", "01", "2025", "111", PaymentMethod.Priority.Primary);

            Console.WriteLine(JsonConvert.SerializeObject(paymentMethod, Formatting.Indented));
        }
    }
}
```

#### Node.js

```javascript
const EasyPostClient = require('@easypost/api');

const client = new EasyPostClient('EASYPOST_API_KEY');

(async () => {
  const creditCard = await client.Referral.addCreditCard(
    'REFERRAL_USER_API_KEY',
    '0123456789101234',
    '01',
    '2025',
    '111',
  );

  console.log(creditCard);
})();
```

#### PHP

```php
<?php

$client = new \EasyPost\EasyPostClient('EASYPOST_API_KEY');

$creditCard = $client->referralCustomer->addCreditCard(
    'REFERRAL_USER_API_KEY',
    '0123456789101234',
    '01',
    '2025',
    '111'
);

echo $creditCard;
```

#### Python

```python
import easypost

client = easypost.EasyPostClient("EASYPOST_API_KEY")

credit_card = client.referral_customer.add_credit_card(
    referral_api_key="REFERRAL_USER_API_KEY",
    number="0123456789101234",
    expiration_month="01",
    expiration_year="2025",
    cvc="111",
)

print(credit_card)
```

#### Ruby

```ruby
require 'easypost'

client = EasyPost::Client.new(api_key: 'EASYPOST_API_KEY')

credit_card = client.referral_customer.add_credit_card(
  'REFERRAL_USER_API_KEY',
  '0123456789101234',
  '01',
  '2025',
  '111',
)

puts credit_card
```

### Adding Bank Accounts (ACH Direct Debits)

1. Retrieve a single-use unique client secret using EasyPost’s `POST /beta/financial_connections_sessions` endpoint to be used with Stripe Financial Connections.

     **NOTE:** The return URL specifies where the user will be redirected after completing the bank account addition
     process in Stripe Financial Connections.

   &nbsp;

### Example: POST /beta/financial_connections_sessions

#### cURL

```shell
curl -X POST "https://api.easypost.com/beta/financial_connections_sessions" \
  -u "$REFERRAL_USER_API_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "return_url": "https://www.yourwebsite.com/redirect"
  }'
```

#### Go

```go
package example

import (
	"fmt"

	"github.com/EasyPost/easypost-go/v5"
)

func createStripeBankAccountSecret() {
	client := easypost.New("EASYPOST_API_KEY")

	response, _ := client.BetaCreateBankAccountClientSecret()

	fmt.Println(response)
}
```

#### Java

```java
package billing;

import com.easypost.exception.EasyPostException;
import com.easypost.service.EasyPostClient;

public class CreateStripeBankAccountSecret {
    public static void main(String[] args) throws EasyPostException {
        EasyPostClient client = new EasyPostClient("EASYPOST_API_KEY");

        ClientSecret response = client.betaReferralCustomer.createBankAccountClientSecret();

        System.out.println(response);
    }
}
```

#### C#

```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using EasyPost;
using Newtonsoft.Json;

namespace EasyPostExamples
{
    public class Examples
    {
        public static async Task Main()
        {
            var client = new EasyPost.Client(new EasyPost.ClientConfiguration("EASYPOST_API_KEY"));

            EasyPost.Models.API.StripeClientSecret response = await client.Beta.ReferralCustomer.CreateBankAccountClientSecret();

            Console.WriteLine(JsonConvert.SerializeObject(response, Formatting.Indented));
        }
    }
}
```

#### Node.js

```javascript
const EasyPostClient = require('@easypost/api');

const client = new EasyPostClient('EASYPOST_API_KEY');

(async () => {
  const response = await client.BetaReferralCustomer.createBankAccountClientSecret();

  console.log(response);
})();
```

#### PHP

```php
<?php

$client = new \EasyPost\EasyPostClient('EASYPOST_API_KEY');

$response = $client->betaReferralCustomer->createBankAccountClientSecret();

echo $response;
```

#### Python

```python
import easypost

client = easypost.EasyPostClient("EASYPOST_API_KEY")

response = client.beta_referral_customer.create_bank_account_client_secret()

print(response)
```

#### Ruby

```ruby
require 'easypost'

client = EasyPost::Client.new(api_key: 'EASYPOST_API_KEY')

response = client.beta_referral_customer.create_bank_account_client_secret

puts response
```

2. Have the user accept a mandate indicating consent to having their bank account automatically charged.

![ACH Mandate Agreement](https://docs.easypost.com/images/ach-mandate-agreement.png)

3. Open the Stripe Financial Connections modal in the user’s browser using the Stripe.js client with the client secret obtained during the previous step. See the official Stripe documentation.

     **NOTE:** When the above promise is resolved successfully, the returned result will contain a list of accounts in
     `result.financialConnectionsSession.accounts`. The `id` for each of these accounts is what must be used to create
     the bank account using the EasyPost API endpoint.

4. Create a bank account for the referral customer using EasyPost’s `POST /bank_accounts` endpoint once per ID retrieved along with data for the mandate acceptance.

     **NOTE:** Payment methods can be deleted using EasyPost’s
     `DELETE /bank_accounts/:id` and
     `DELETE /credit_cards/:id` endpoints.

   &nbsp;

### Example: POST /bank_accounts

#### cURL

```shell
curl -X POST "https://api.easypost.com/v2/bank_accounts" \
  -u "$REFERRAL_USER_API_KEY:" \
  -H "Content-Type: application/json" \
  -d '{
    "financial_connections_id": "fca_...",
    "mandate_data": {
      "ip_address": "127.0.0.1",
      "user_agent": "Mozilla/5.0",
      "accepted_at": 1722510730,
    },
    "priority": "primary"
  }'
```

#### Go

```go
package example

import (
	"fmt"

	"github.com/EasyPost/easypost-go/v5"
)

func addStripeBankAccount() {
	client := easypost.New("EASYPOST_API_KEY")

	bankAccount, _ := client.AddReferralCustomerBankAccountFromStripe(
		"REFERRAL_USER_API_KEY",
		"fca_...",
		&easypost.MandateData{
			IpAddress:  "127.0.0.1",
			UserAgent:  "Mozilla/5.0",
			AcceptedAt: 1722510730,
		},
		easypost.PrimaryPaymentMethodPriority,
	)

	fmt.Println(bankAccount)
}
```

#### Java

```java
package billing;

import com.easypost.exception.EasyPostException;
import com.easypost.model.PaymentMethod;
import com.easypost.service.EasyPostClient;

public class CreateStripeCreditCardSecret {
    public static void main(String[] args) throws EasyPostException {
        EasyPostClient client = new EasyPostClient("EASYPOST_API_KEY");

        HashMap<String, Object> mandateData = new HashMap<String, Object>();
        mandateData.put("ip_address", "127.0.0.1");
        mandateData.put("user_agent", "Mozilla/5.0");
        mandateData.put("accepted_at", 1722510730);

        PaymentMethodObject paymentMethod = client.referralCustomer.addBankAccountFromStripe(
                "REFERRAL_USER_API_KEY",
                "fca_...",
                mandateData,
                PaymentMethod.Priority.PRIMARY
        );

        System.out.println(paymentMethod);
    }
}
```

#### C#

```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using EasyPost;
using Newtonsoft.Json;

namespace EasyPostExamples
{
    public class Examples
    {
        public static async Task Main()
        {
            var client = new EasyPost.Client(new EasyPost.ClientConfiguration("EASYPOST_API_KEY"));

            EasyPost.Models.API.PaymentMethod paymentMethod = await Client.ReferralCustomer.AddBankAccountFromStripe(
                "REFERRAL_USER_API_KEY",
                "fca_...",
                new Dictionary<string, object>
                {
                    { "ip_address", "127.0.0.1" },
                    { "user_agent", "Mozilla/5.0" },
                    { "accepted_at", 1722510730 }
                },
                EasyPost.Models.API.PaymentMethod.Priority.Primary
            );

            Console.WriteLine(JsonConvert.SerializeObject(paymentMethod, Formatting.Indented));
        }
    }
}
```

#### Node.js

```javascript
const EasyPostClient = require('@easypost/api');

const client = new EasyPostClient('EASYPOST_API_KEY');

(async () => {
  const paymentMethod = await client.ReferralCustomer.addBankAccountFromStripe(
    'REFERRAL_USER_API_KEY',
    'fca_...',
    {
      ip_address: '127.0.0.1',
      user_agent: 'Mozilla/5.0',
      accepted_at: 172251073,
    },
    'primary',
  );

  console.log(paymentMethod);
})();
```

#### PHP

```php
<?php

$client = new \EasyPost\EasyPostClient('EASYPOST_API_KEY');

$paymentMethod = $client->referralCustomer->addBankAccountFromStripe(
    'REFERRAL_USER_API_KEY',
    'fca_...',
    [
        'ip_address' => '127.0.0.1',
        'user_agent' => 'Mozilla/5.0',
        'accepted_at' => 172251073,
    ],
    'primary',
);

echo $paymentMethod;
```

#### Python

```python
import easypost

client = easypost.EasyPostClient("EASYPOST_API_KEY")

payment_method = client.referral_customer.add_bank_account_from_stripe(
    referral_api_key="REFERRAL_USER_API_KEY",
    financial_connections_id="fca_...",
    mandate_data={
        "ip_address": "127.0.0.1",
        "user_agent": "Mozilla/5.0",
        "accepted_at": 172251073,
    },
    priority="primary",
)

print(payment_method)
```

#### Ruby

```ruby
require 'easypost'

client = EasyPost::Client.new(api_key: 'EASYPOST_API_KEY')

payment_method = client.referral_customer.add_bank_account_from_stripe(
  'REFERRAL_USER_API_KEY',
  'fca_...',
  {
    ip_address: '127.0.0.1',
    user_agent: 'Mozilla/5.0',
    accepted_at: 172_251_073,
  },
  'primary',
)

puts payment_method
```

---

## Step 3: Fund the EasyPost Wallet

`ReferralCustomer` users can deposit an initial amount into the EasyPost Wallet using EasyPost’s `POST /bank_accounts/:id/charges` or `POST /credit_cards/:id/charges`
to start using services immediately.

### Example: Add Funds

#### cURL

```shell
curl -X POST https://api.easypost.com/v2/credit_cards/card_.../charges \
  -u "EASYPOST_API_KEY": \
  -H 'Content-Type: application/json' \
  -d '{
    "amount": "2000"
  }'
```

#### Go

```go
package example

import (
	"github.com/EasyPost/easypost-go/v5"
)

func fund() {
	client := easypost.New("EASYPOST_API_KEY")

	_ = client.FundWallet("2000", easypost.PrimaryPaymentMethodPriority)
}
```

#### Java

```java
package billing;

import com.easypost.exception.EasyPostException;
import com.easypost.model.PaymentMethod;
import com.easypost.service.EasyPostClient;

public class Fund {
    public static void main(String[] args) throws EasyPostException {
        EasyPostClient client = new EasyPostClient("EASYPOST_API_KEY");

        client.billing.fundWallet("2000", PaymentMethod.Priority.PRIMARY);
    }
}
```

#### C#

```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using EasyPost;
using Newtonsoft.Json;

namespace EasyPostExamples
{
    public class Examples
    {
        public static async Task Main()
        {
            var client = new EasyPost.Client(new EasyPost.ClientConfiguration("EASYPOST_API_KEY"));

            await client.Billing.FundWallet("2000", PaymentMethod.Priority.Primary);
        }
    }
}
```

#### Node.js

```javascript
const EasyPostClient = require('@easypost/api');

const client = new EasyPostClient('EASYPOST_API_KEY');

(async () => {
  await client.Billing.fundWallet('2000', 'primary');
})();
```

#### PHP

```php
<?php

$client = new \EasyPost\EasyPostClient('EASYPOST_API_KEY');

$client->billing->fundWallet(2000, 'primary');
```

#### Python

```python
import easypost

client = easypost.EasyPostClient("EASYPOST_API_KEY")

client.billing.fund_wallet(
    amount="2000",
    primary_or_secondary="primary",
)
```

#### Ruby

```ruby
require 'easypost'

client = EasyPost::Client.new(api_key: 'EASYPOST_API_KEY')

client.billing.fund_wallet('2000', 'primary')
```

---

## Step 4: Configure Recharge Threshold and Recharge Amount

Once a payment method is established, EasyPost can automatically charge a `recharge_amount` if a wallet balance falls below a `recharge_threshold`. To ensure
uninterrupted service, platforms using the Decentralized white-label option should provide clear guidance on the recharge threshold and recharge amount system.

### Default Recharge Settings

- `recharge_amount` is set to $100
- `recharge_threshold` is set to zero

This means that the wallet will not automatically recharge unless the balance falls below zero. A negative balance can occur if shipment adjustments are
applied due to inaccurately specified weights, dimensions, or other shipment details.

### Handling Failed Payments

If a charge to the primary payment method fails, EasyPost will automatically attempt to charge the `ReferralCustomer`’s secondary payment method, if one
is available. To avoid service interruptions, It is recommended that `ReferralCustomers` have both a primary and secondary payment method configured.

### Customizing Recharge Settings

Forge customers can configure the `recharge_threshold`, `recharge_amount` and `secondary_recharge_amount` for a `ReferralCustomer` using EasyPost’s `PATCH /users` API.
These settings allow automatic maintenance of the wallet balance and prevent disruptions in service.

### Example: PATCH /users/:id

#### cURL

```shell
# Update the authenticated user
curl -X PATCH https://api.easypost.com/v2/users \
  -u "EASYPOST_API_KEY": \
  -H 'Content-Type: application/json' \
  -d '{
    "user": {
      "recharge_threshold": "50.00"
    }
  }'

# Update a child user
curl -X PATCH https://api.easypost.com/v2/users/user_... \
  -u "EASYPOST_API_KEY": \
  -H 'Content-Type: application/json' \
  -d '{
    "user": {
      "name": "Test Child"
    }
  }'
```

#### Go

```go
package example

import (
	"fmt"

	"github.com/EasyPost/easypost-go/v5"
)

func update() {
	client := easypost.New("EASYPOST_API_KEY")

	rechargeAmount := "50.00"

	user, _ := client.UpdateUser(
		&easypost.UserOptions{
			ID:             "user_...",
			RechargeAmount: &rechargeAmount,
		},
	)

	fmt.Println(user)
}
```

#### Java

```java
package users;

import com.easypost.exception.EasyPostException;
import com.easypost.model.User;
import com.easypost.service.EasyPostClient;

import java.util.HashMap;

public class Update {
    public static void main(String[] args) throws EasyPostException {
        EasyPostClient client = new EasyPostClient("EASYPOST_API_KEY");

        HashMap<String, Object> params = new HashMap<String, Object>();
        params.put("recharge_threshold", "50.00");

        User user = client.user.update("user_...", params);

        System.out.println(user);
    }
}
```

#### C#

```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using EasyPost;
using Newtonsoft.Json;

namespace EasyPostExamples
{
    public class Examples
    {
        public static async Task Main()
        {
            var client = new EasyPost.Client(new EasyPost.ClientConfiguration("EASYPOST_API_KEY"));

            EasyPost.Parameters.User.Update parameters = new()
            {
                RechargeThreshold = "50.00"
            };

            EasyPost.Models.API.User user = await client.User.Update("user_...", parameters);

            Console.WriteLine(JsonConvert.SerializeObject(user, Formatting.Indented));
        }
    }
}
```

#### Node.js

```javascript
const EasyPostClient = require('@easypost/api');

const client = new EasyPostClient('EASYPOST_API_KEY');

(async () => {
  const user = await client.User.update('user_...', { recharge_threshold: '50.00' });

  console.log(user);
})();
```

#### PHP

```php
<?php

$client = new \EasyPost\EasyPostClient('EASYPOST_API_KEY');

$user = $client->user->update(
    'user_...',
    ['recharge_threshold' => '50.00']
);

echo $user;
```

#### Python

```python
import easypost

client = easypost.EasyPostClient("EASYPOST_API_KEY")

user = client.user.retrieve_me()

updated_user = client.user.update(user.id, recharge_threshold="50.00")

print(updated_user)
```

#### Ruby

```ruby
require 'easypost'

client = EasyPost::Client.new(api_key: 'EASYPOST_API_KEY')

retrieved_user = client.user.retrieve_me

user = client.user.update(retrieved_user.id, recharge_amount: '50.00')

puts user
```

---

## ReferralCustomer Carrier Account Management

Upon creation, the `ReferralCustomer` user automatically receives access to several Wallet Carrier Accounts, which are billed through the referralCustomer's wallet.

To add additional carrier accounts for a `ReferralCustomer` user, one of the following options can be used:

- **API Integration:** Use the Carrier Account API with the `ReferralCustomer` user’s Production API Key of the sub account to integrate additional carriers.
- **Forge Dashboard:** Manually add carriers through the Carriers section of the Forge Dashboard.

Related:

- [Carrier Management](https://support.easypost.com/hc/en-us/sections/34550349817869-Carrier-Management)

---

## ReferralCustomer Shipment Creation

Creating shipments for `ReferralCustomer` users follows the same process as Parent Users, with key differences being the requirement to use the `ReferralCustomer` user’s API Keys.

A `Shipment Object` consists of:

- A valid `to_address` and `from_address`
- A `parcel` with shipping details
- Any required `forms` for international deliveries

Once a `shipment` is created, a `Shipment Object` is used to retrieve shipping rates and purchase a label.

---

## Additional Resources

Please visit the Help Center for more information.