> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.upwardli.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.upwardli.com/_mcp/server.

# Bill Switch / Deposit Switch

> **Important**
>
> Bill Switch and Deposit Switch are only available to Credit Builder Card users.

Upward has partnered with Atomic to automatically Switch Bill Pay and deposit functionality to your Consumer's Payment Cards. In this updated flow, you will first request either a Bill Switch or Deposit Switch token from the Upward API platform, and then use that Token to initialize the Atomic SDK. Once a connection is successful, you will receive regular updates/webhooks directly from Atomic as per their documentation.

## Requesting a Bill Switch Token

Request a Bill Switch Token by calling `POST /v2/payment-cards/{payment_card_id}/bill-switch/token`. You will use this token to initialize the Atomic client-side SDK.

Response:

```json
{
  "public_token": "string"
}
```

*You can view more details about the Deposit Switch endpoint [here](/api-access/api-reference/payment-cards/switch-bill-switch-token)*

## Requesting a Deposit Switch Token

Request a Deposit Switch Token by calling `POST /v2/payment-cards/{payment_card_id}/deposit-switch/token`. You will use this token to initialize the Atomic client-side SDK.

Response:

```json
{
  "public_token": "string"
}
```

*You can view more details about the Deposit Switch endpoint [here](/api-access/api-reference/payment-cards/switch-deposit-switch-response)*

> **Atomic Financial**
>
> For more on the Atomic Switch Product, view the documentation [here](https://docs.atomicfi.com/products/manage/implementation#overview).

---

## Integration Steps

Once you have obtained the token from Upwardli's bill-switch or deposit-switch endpoint, follow these steps to complete the integration:

### Step 1: Initialize the Atomic Transact SDK

Use the `public_token` received from Upwardli to initialize the Atomic Transact SDK. This will create a session and validate the token.

> **Important: Configuration Differences**
>
> **Bill Switch** requires:
>
> * `scope: "pay-link"`
> * `tasks: [{ operation: "switch" }]`
>
> **Direct Deposit Switch** requires:
>
> * `scope: "user-link"`
> * `tasks: [{ operation: "deposit" }]`

**Bill Switch - Web Implementation Example:**

```javascript
import { Atomic } from '@atomicfi/transact';

// Use the token from Upwardli's bill-switch endpoint
const publicToken = 'YOUR_PUBLIC_TOKEN_FROM_UPWARDLI';

Atomic.transact({
  config: {
    publicToken: publicToken,
    scope: 'pay-link', // Required for Bill Switch
    tasks: [{ operation: 'switch' }], // Required for Bill Switch
    theme: {
      brandColor: '#9460FE',
      dark: false
    },
    language: 'en'
  },
  onAuthStatusUpdate: (status) => {
    console.log('Authentication status:', status.status);
  },
  onTaskStatusUpdate: (task) => {
    console.log('Task status update:', task.taskId, task.status);
  },
  onError: (error) => {
    console.error('Atomic SDK error:', error);
  },
  onFinish: (data) => {
    console.log('Task completed:', data.taskId);
  }
});
```

**Direct Deposit Switch - Web Implementation Example:**

```javascript
import { Atomic } from '@atomicfi/transact';

// Use the token from Upwardli's deposit-switch endpoint
const publicToken = 'YOUR_PUBLIC_TOKEN_FROM_UPWARDLI';

Atomic.transact({
  config: {
    publicToken: publicToken,
    scope: 'user-link', // Required for Direct Deposit Switch
    tasks: [{ operation: 'deposit' }], // Required for Direct Deposit Switch
    theme: {
      brandColor: '#9460FE',
      dark: false
    },
    language: 'en'
  },
  onAuthStatusUpdate: (status) => {
    console.log('Authentication status:', status.status);
  },
  onTaskStatusUpdate: (task) => {
    console.log('Task status update:', task.taskId, task.status);
  },
  onError: (error) => {
    console.error('Atomic SDK error:', error);
  },
  onFinish: (data) => {
    console.log('Task completed:', data.taskId);
  }
});
```

**Bill Switch - React Native Example:**

```javascript
import { Atomic } from "@atomicfi/transact-react-native";

const publicToken = 'YOUR_PUBLIC_TOKEN_FROM_UPWARDLI';

Atomic.transact({
  config: {
    scope: "pay-link", // Required for Bill Switch
    publicToken: publicToken,
    tasks: [{ operation: "switch" }], // Required for Bill Switch
    theme: {
      brandColor: "#9460FE",
      dark: false
    },
    language: "en"
  },
  onAuthStatusUpdate: status => {
    console.log('Auth status:', status.status);
  },
  onTaskStatusUpdate: task => {
    console.log('Task', task.taskId, 'status:', task.status);
  },
  onError: error => {
    console.log('Error:', error);
  }
});
```

**Direct Deposit Switch - React Native Example:**

```javascript
import { Atomic } from "@atomicfi/transact-react-native";

const publicToken = 'YOUR_PUBLIC_TOKEN_FROM_UPWARDLI';

Atomic.transact({
  config: {
    scope: "user-link", // Required for Direct Deposit Switch
    publicToken: publicToken,
    tasks: [{ operation: "deposit" }], // Required for Direct Deposit Switch
    theme: {
      brandColor: "#9460FE",
      dark: false
    },
    language: "en"
  },
  onAuthStatusUpdate: status => {
    console.log('Auth status:', status.status);
  },
  onTaskStatusUpdate: task => {
    console.log('Task', task.taskId, 'status:', task.status);
  },
  onError: error => {
    console.log('Error:', error);
  }
});
```

### Step 2: Confirm Event Delivery

Atomic will send webhook events for transaction updates. Ensure your webhook endpoint is configured to receive these events.

**Key Events to Monitor:**

1. **task-status-update** - Fired when a task status changes (processing, completed, failed)
2. **auth-status-update** - Fired when authentication status changes
3. **task-completed** - Fired when a switch task completes successfully
4. **task-failed** - Fired when a task fails

**Webhook Configuration:**

Configure your webhook endpoint in the [Atomic Console](https://console.atomicfi.com/settings/webhooks). Your endpoint should accept POST requests with the following structure:

```json
{
  "event": "task-status-update",
  "data": {
    "taskId": "abc123",
    "userId": "user_xyz",
    "product": "switch",
    "status": "completed",
    "company": {
      "_id": "company_123",
      "name": "Example Payroll"
    },
    "switchData": {
      "paymentMethod": {
        "type": "card",
        "brand": "Visa",
        "lastFour": "1111",
        "expiry": "03/29"
      }
    }
  }
}
```

**Example Webhook Handler:**

```javascript
app.post('/webhooks/atomic', (req, res) => {
  const { event, data } = req.body;
  
  console.log('Received Atomic webhook:', event);
  
  switch(event) {
    case 'task-status-update':
      console.log(`Task ${data.taskId} status: ${data.status}`);
      if (data.status === 'completed') {
        // Handle successful switch
        console.log('Switch completed for company:', data.company.name);
      } else if (data.status === 'failed') {
        // Handle failed switch
        console.log('Switch failed:', data.failReason);
      }
      break;
      
    case 'auth-status-update':
      console.log('User authenticated with:', data.company.name);
      break;
      
    default:
      console.log('Unhandled event type:', event);
  }
  
  // Always respond with 200 to acknowledge receipt
  res.status(200).send('OK');
});
```

---

## Testing Your Integration

Atomic provides test credentials to simulate various scenarios. You can use these in development:

**Successful Flow:**

* Username: `test-good`
* Password: Any password
* Description: Tests a successful operation

**MFA Flow:**

* Username: `test-code-mfa`
* Password: Any password
* Description: Tests authentication with device code MFA

**Failure Scenarios:**

* Username: `test-bad` - Tests unsuccessful authentication
* Username: `test-system-unavailable` - Tests third-party system outage
* Username: `test-failure` - Tests post-authentication failure

For a complete list of test credentials and scenarios, refer to the [Atomic SDK Testing Documentation](https://docs.atomicfi.com/paylink/reference/transact-sdk#testing).

---

## Complete Integration Checklist

* [ ] Request token from Upwardli's `/bill-switch/token` or `/deposit-switch/token` endpoint
* [ ] Initialize Atomic Transact SDK with the received `public_token`
* [ ] Implement `onDataRequest` callback to provide card details via SDK or API
* [ ] Configure webhook endpoint in Atomic Console
* [ ] Verify webhook events are being received for task status updates
* [ ] Test with Atomic's test credentials
* [ ] Handle error scenarios appropriately

---

## Additional Resources

* [Atomic Transact SDK Reference](https://docs.atomicfi.com/paylink/reference/transact-sdk)
* [Atomic PayLink API Reference](https://docs.atomicfi.com/paylink/reference/api)
* [Atomic Webhook Events](https://docs.atomicfi.com/paylink/reference/webhooks)
* [Upwardli Bill Switch API](/api-access/api-reference/payment-cards/switch-bill-switch-token)
* [Upwardli Deposit Switch API](/api-access/api-reference/payment-cards/switch-deposit-switch-response)