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

# Guide: multichain payroll batch

> Pay many recipients across many chains as one batch of confidential intents. SDK walkthrough.

This guide walks through building a payroll batch that pays N recipients on N chains, each with their preferred asset, in one signed submission.

## Prerequisites

* Tachyon SDK installed ([sdk/installation](/sdk/installation)) **or** ready to call the relayer HTTP endpoints directly (see [endpoints and helpers](/reference/endpoints-and-helpers))
* A funding wallet with USDC on a supported source chain
* Contract addresses for the source-chain bridge on your chain of choice (see [endpoints and helpers](/reference/endpoints-and-helpers#on-chain-contract-addresses))
* A list of recipients with `{ address, chain, asset, amount }`

## 1. Build the batch

```ts theme={null}
import { Tachyon } from "@tachyon/sdk";

const tachyon = new Tachyon({ network: "testnet" });

const intents = await Promise.all(
  contributors.map((c) =>
    tachyon.intent.build({
      sourceChain: "arbitrum",
      destChain: c.chain,
      tokenIn: USDC_ARB,
      tokenOut: c.asset,
      amountIn: c.amount,
      minAmountOut: applySlippage(c.amount, 0.01),
      deadline: Math.floor(Date.now() / 1000) + 3600,
      recipient: c.address,
      metadata: { payrollPeriod: "2026-04", contributorId: c.id },
    })
  )
);
```

`metadata` is integrator-defined and never published on-chain. Use it to correlate intents with your internal records.

## 2. Sign once

```ts theme={null}
const signedBatch = await wallet.signBatch(intents);
```

A single signature authorizes the entire batch. Tachyon validates each intent in the batch independently.

## 3. Submit

```ts theme={null}
const { intentIds } = await tachyon.intent.submitBatch(signedBatch);
```

You receive an `intentId` for each intent in the batch, in the same order.

<Note>
  Today, this loops `createIntent` calls for each contributor. An atomic batch-submission path is planned so the whole batch lands in one on-chain transaction.
</Note>

## 4. Track the batch

```ts theme={null}
const results = new Map(intentIds.map((id) => [id, "pending"]));

intentIds.forEach((id) => {
  tachyon.intent.subscribe(id, (intent) => {
    results.set(id, intent.status);
    updateDashboard(results);
  });
});
```

Each intent settles independently. Some recipients may receive their payment seconds before others, payouts are not coordinated as an all-or-nothing batch.

## 5. Notify recipients (optional)

For better UX, send each recipient a settlement reference once their intent settles:

```ts theme={null}
tachyon.intent.subscribe(id, async (intent) => {
  if (intent.status === "completed") {
    await notify(contributor.email, {
      settleTxHash: intent.settleTxHash,
      solveTxHash:  intent.solveTxHash,
      destChain:    contributor.chain,
      intentId:     id,
    });
  }
});
```

The recipient can verify the payment using their viewing key, no on-chain trace links it to your organization.

## Recurring schedules

There is no on-chain "stream" object in Confidential Payroll. Schedule the batch from your own backend (cron, scheduler, etc.) on whatever cadence you need. Each cycle is an independent batch, which keeps confidentiality maximal because cycle N reveals nothing about cycle N+1.

## Compliance and audit access

You can grant a finance team or auditor scoped viewing access to the entire batch (or to selected intents) at submission time. See [viewing permissions](/guides/viewing-permissions).

<Card title="Try it on testnet" icon="play" href="/quickstart">
  Walk through a smaller version end-to-end.
</Card>
