# Customer Portal

The Customer Portal enables platforms and marketplaces to direct sub accounts to a self-service interface for `account_onboarding` and `account_management`.
This functionality is accessed using the `account_link` endpoint, which generates a secure, one-time-use session URL.

---

## CustomerPortalAccountLink object

| Property | Type | Description |
|----------|------|-------------|
| object | string | Always returns "CustomerPortalAccountLink". |
| link | string | One-time-use session URL for initiating the Customer Portal. |
| created_at | timestamp | One-time-use session URL for initiating the Customer Portal. |
| expires_at | timestamp | ISO 8601 timestamp when the link will expire (5 minutes from creation). |

Example Object:

```json
{
  "object": "CustomerPortalAccountLink",
  "created_at": "2026-10-06T17:30:30Z",
  "expires_at": "2026-10-06T17:35:30Z",
  "link": "https://app.easypost.com/customer-portal/onboarding?session_id={SESSION_ID}"
}
```

---

**Production Only**

## Creating a Portal Session

### 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"}
  }'
```

#### Go

```go
package example

import (
	"fmt"

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

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

	accountLink, _ := client.CreateCustomerPortalAccountLink(
		&easypost.CustomerPortalAccountLinkParameters{
			SessionType: "account_management",
			UserId:      "user_...",
			RefreshUrl:  "https://example.com/refresh",
			ReturnUrl:   "https://example.com/return",
			Metadata: map[string]interface{}{
				"target": "wallet",
			},
		},
	)

	fmt.Println(accountLink)
}
```

#### Java

```java
package customer_portals;

import java.util.HashMap;

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

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

        HashMap<String, Object> params = new HashMap<>();
        params.put("session_type", "account_management");
        params.put("user_id", "user_...");
        params.put("refresh_url", "https://example.com/refresh");
        params.put("return_url", "https://example.com/return");

        HashMap<String, Object> metadata = new HashMap<>();
        metadata.put("target", "wallet");
        params.put("metadata", metadata);

        CustomerPortalAccountLink accountLink = client.customerPortal.createAccountLink(params);

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

#### C#

```csharp
using System;
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.CustomerPortal.CreateAccountLink parameters = new()
            {
                SessionType = "account_management",
                UserId = "user_...",
                RefreshUrl = "https://example.com/refresh",
                ReturnUrl = "https://example.com/return",
                Metadata = new System.Collections.Generic.Dictionary<string, object>
                {
                    { "target", "wallet" }
                }
            };

            EasyPost.Models.API.CustomerPortal.AccountLink accountLink = await client.CustomerPortal.CreateAccountLink(parameters);

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

#### Node.js

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

const client = new EasyPostClient('EASYPOST_API_KEY');

(async () => {
  const accountLink = await client.CustomerPortal.createAccountLink({
    session_type: 'account_management',
    user_id: 'user_...',
    refresh_url: 'https://example.com/refresh',
    return_url: 'https://example.com/return',
    metadata: { target: 'wallet' },
  });

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

#### PHP

```php
<?php

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

$accountLink = $client->customerPortal->createAccountLink([
    'session_type' => 'account_management',
    'user_id' => 'user_...',
    'refresh_url' => 'https://example.com/refresh',
    'return_url' => 'https://example.com/return',
    'metadata' => ['target' => 'wallet'],
]);

echo $accountLink;
```

#### Python

```python
import easypost

client = easypost.EasyPostClient("EASYPOST_API_KEY")

account_link = client.customer_portal.create_account_link(
    session_type="account_management",
    user_id="user_...",
    refresh_url="https://example.com/refresh",
    return_url="https://example.com/return",
    metadata={"target": "wallet"},
)

print(account_link)
```

#### Ruby

```ruby
require 'easypost'

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

account_link = client.customer_portal.create_account_link(
  {
    session_type: 'account_management',
    user_id: 'user_...',
    refresh_url: 'https://example.com/refresh',
    return_url: 'https://example.com/return',
    metadata: { target: 'wallet' },
  },
)

puts account_link
```

This endpoint generates a one-time Customer Portal URL. The integrator must redirect the sub account user to this URL within the expiration window.

---

## Handling redirects

- **Refresh URL:** Redirected here if the session link has expired or has already been used. Should trigger a new `POST /customer_portal/account_link` call.
- **Return URL:** Redirected here when the session ends. Session outcome is not included; use webhooks or fetch account status via API.

---

## Additional resources

- Get started with Forge
- Forge Help Center