> ## Documentation Index
> Fetch the complete documentation index at: https://docs.riseworks.io/llms.txt
> Use this file to discover all available pages before exploring further.

# External Entity Payments (Bill Pay)

> Pay vendors and recipients who are not Rise users with instant external-entity payments

External entity payments let a team pay recipients who are **not** Rise members — vendors, contractors, or suppliers identified by email. Unlike standard payments (which target a Rise member of the team), external-entity payments create or reference an external recipient and disburse funds directly.

<Note>
  External entity payments are a team-scoped operation. The signer must hold a wallet with payment permissions on the team's RiseID, exactly like standard payments.
</Note>

## When to use this

<CardGroup cols={2}>
  <Card title="Standard payments" icon="user-check">
    Recipient is already a member of your team. Use `client.payments.*` and `POST /v2/payments`.
  </Card>

  <Card title="External entity payments" icon="building">
    Recipient is an outside vendor/supplier identified by email. Use `client.billPay.*` and the `external_entity` endpoints.
  </Card>
</CardGroup>

## Payment flow

External-entity instant payments follow the same secure prepare → sign → execute pattern as standard payments. The signature is produced locally with your wallet; the private key never leaves your process.

<Steps>
  <Step title="Create or reference a recipient">
    Register the external recipient under the team (or reuse an existing one).
  </Step>

  <Step title="Prepare the payment">
    Request EIP-712 typed data for the instant payment.
  </Step>

  <Step title="Sign with your wallet">
    Sign the returned typed data locally.
  </Step>

  <Step title="Execute">
    Submit the signature to execute the payment on-chain.
  </Step>
</Steps>

## SDK usage

### Manage recipients

```ts theme={null}
import { RiseApiClient, type TeamNanoid } from '@riseworks/riseworks-sdk'

const client = new RiseApiClient({
  environment: 'stg',
  jwtToken: process.env.RISE_JWT_TOKEN!,
})

// List existing external recipients for a team
const recipients = await client.billPay.listRecipients({
  team_nanoid: 'te_123' as TeamNanoid,
})

// Register a new external recipient
await client.billPay.createRecipient(
  { team_nanoid: 'te_123' as TeamNanoid },
  { email: 'vendor@example.com' },
)
```

### Send an instant payment (one call)

`sendInstantPayment` runs the full prepare → sign → execute flow for you. It needs a private key to sign — either passed inline or configured on the client via `riseIdAuth`.

```ts theme={null}
const result = await client.billPay.sendInstantPayment({
  from: 'te_123',
  amount_cents: 125_000, // 1,250.00
  currency_symbol: 'USD',
  external_recipient_email: 'vendor@example.com',
  payment_data: {
    role_description: 'Design work',
    invoice_description: 'Invoice INV-2026-001',
    services_description: 'Landing page design',
    payment_details: 'Net 15',
    rise_sow: false,
  },
  privateKey: process.env.RISE_PRIVATE_KEY, // omit if set via riseIdAuth
})

console.log(result.data.transaction)
```

### Prepare and execute separately

If you sign with an external wallet (hardware wallet, custody service), split the flow:

```ts theme={null}
// 1. Prepare — returns EIP-712 typed data
const prepared = await client.billPay.prepareInstantPayment({
  from: 'te_123',
  amount_cents: 125_000,
  currency_symbol: 'USD',
  external_recipient_email: 'vendor@example.com',
  payment_data: { role_description: 'Design work', rise_sow: false },
})

// 2. Sign prepared.data.typed_data with your wallet (returns a signature)

// 3. Execute
const executed = await client.billPay.executeInstantPayment({
  from: 'te_123',
  amount_cents: 125_000,
  currency_symbol: 'USD',
  external_recipient_email: 'vendor@example.com',
  payment_data: { role_description: 'Design work', rise_sow: false },
  signer: walletAddress,
  typed_data: prepared.data.typed_data,
  signature,
})
```

## REST endpoints

| Operation               | Method & path                                            |
| ----------------------- | -------------------------------------------------------- |
| List recipients         | `GET /v2/payments/teams/{team_nanoid}/external_entity`   |
| Create recipient        | `POST /v2/payments/teams/{team_nanoid}/external_entity/` |
| Prepare instant payment | `POST /v2/payments/external_entity/instant`              |
| Execute instant payment | `PUT /v2/payments/external_entity/instant`               |

See the [API Reference](/api-reference/introduction) for full request and response schemas.

## Idempotency with `external_id`

Payments accept an optional `external_id` — your own reference for the payment (an invoice number, an internal transaction id). Rise enforces that `external_id` is **unique per payer (team)**: a second payment from the same team with an `external_id` it has already used is rejected with `409 Conflict`. Use it to make retries safe and to prevent accidental double-payments.

<Warning>
  `external_id` uniqueness is enforced **going forward** and is scoped per payer. Omit it (leave it unset) when you do not need idempotency — unset values are never treated as duplicates. Reuse the same `external_id` on a retry to guarantee the payment is only created once.
</Warning>

## Related

* [Payment Integration Guide](/guides/payment-integration) — standard payments to team members
* [Payments concept](/concepts/payments) — payment flow and on-chain security
* [Error Handling](/guides/error-handling) — handling `409` and validation errors
