# Viacash

The Viacash feature enables customers to make cash deposits (pay-ins) and withdrawals (payouts) to and from their Solaris accounts at participating retail locations.

Customers request a transaction in your application to generate a barcode. The merchant scans this barcode at the point-of-sale (POS) cash register to facilitate the physical cash exchange. [Viafintech](https://www.viafintech.com) acts as the technical service provider for this infrastructure via Solaris' partner bank, [Grenke Bank AG](https://www.grenke.de). Customers do not need to make an in-store purchase to use this service.

Prerequisite: Device Signing
To implement Viacash, your application must support [Device Signing](/guides/authentication/strong-customer-authentication/#implement-device-signing). All cash operation requests require Strong Customer Authentication (SCA) via the change request process.

## Operational Limits & Validations

Solaris and Viafintech impose strict limits on cash operations to mitigate risk.

### Transaction Limits

* **Per Operation Limit:** The maximum amount per individual cash operation is 300 EUR.
* **Daily Rolling Limit:** Customers are restricted to **999.99 EUR** in combined pay-ins and payouts per 24-hour rolling window.
* **Concurrent Operations:** A customer may only have **one** active pay-in request and **one** active payout request at any given time (status `CREATED` or `PENDING`).


At request, Solaris can impose additional limits on pay-ins and payouts. The following dimensions are supported:

| Dimension | Transaction type | Time period |
|  --- | --- | --- |
| Person | Pay-out | Per 24h (rolling) |
| Person | Pay-out | Per operation |
| Person | Pay-in | Per 24h (rolling) |
| Person | Pay-in | Per operation |
| Person | Combined | Per 24h (rolling) |
| Account | Combined | Per 24h (rolling) |


### Validation Rules

When you request a cash operation, Solaris verifies the following conditions. A failure in any check results in a declined request:

* **Account Status:** The account must be active and must not be in close monitoring for compliance reasons.
* **Blocks:** The account must not have active blocks or debit blocks.
* **Authorization:** The person requesting the operation must be authorized to act on the account.
* **Balance Check:** For payouts, the requested amount must be less than or equal to the available account balance.


## Architecture Flow

The following diagram illustrates the lifecycle of a cash operation across all involved parties.


```mermaid
sequenceDiagram
    autonumber
    
    participant C as Customer
    participant M as Merchant POS
    participant P as Partner App
    participant S as Solaris
    participant V as Viafintech

    C->>P: Requests a payout/payin
    
    %% API Call: Request Cash Operation
    P->>S: POST Request cash operation
    
    Note over S: Cash operation resource created
    S-->>P: 2FA challenge + verification
    
    %% API Call: Confirm 2FA
    P->>S: POST Confirm 2FA challenge
    
    Note over S: (if payout) Amount blocked<br>on customer acct.
    
    S->>V: Barcode requested
    Note over V: Barcode generated
    V-->>S: Return generated barcode
    
    S-->>P: Return 2FA confirmation (contains barcode)
    Note over P: Extract barcode from response_body
    
    P-->>C: Displays Barcode
    C->>M: Shows barcode to merchant
    
    %% Physical Exchange
    M-->>C: Customer gives or receives cash
    
    M->>V: Merchant confirms barcode
    Note over V: Payout/payin confirmed
    V->>S: Real-time signal sent to Solaris
    
    Note over S: Booking created
    Note over S: (if payout) Payout amount unblocked
    
    S-->>P: Partner notified via webhook
```

## Integration Steps

### 1. Request a Cash Operation

Initiate the cash operation by specifying the `type` (`PAYIN` or `PAYOUT`) and the `amount`.

**Endpoint:** `POST /v1/persons/{person_id}/accounts/{account_id}/cash_operations`


```json
{
  "idempotency_key": "8695a767-2d7b-460b-9c4c-dceb82fb6566",
  "reference": "de430446-1da7-4adf-b440-be6005b5cf9f",
  "provider": "barzahlen",
  "type": "PAYIN",
  "amount": {
    "currency": "EUR",
    "unit": "cents",
    "value": 5000
  }
}
```

This request returns a `change_request_id`. The customer must confirm this change request via Device Signing. Once confirmed, Solaris reserves the funds on the account using the reservation type `CashWithdrawalRetail` or `CashDepositRetail`.

### 2. Confirm 2FA and Retrieve Barcode

After the customer completes the SCA challenge, call the device signing confirmation endpoint.

The response to this confirmation will contain a `response_body` object. This object holds the newly created cash operation resource, including the generated `barcode_ean_13` and its `expires_at` timestamp.

**Confirmation Payload Example:**


```json
{
    "id": "de430446-1da7-4adf-b440-be6005b5cf9f",
    "status": "COMPLETED",
    "updated_at": "2024-09-29T14:20:25.000Z",
    "response_body": {
        "id": "ffb18faf3c004f70a44c83b787488ceeslip",
        "barcode_ean_13": "4053110826660",
        "expires_at": "2024-09-29T15:20:12.424687Z",
        "status": "CREATED",
        "reference_id": "de430446-1da7-4adf-b440-be6005b5cf9f",
        "person_id": "5af2ea4271038d5c53e68ccbf4fe43b3cper"
    },
    "response_code": 200
}
```

### 3. Display Barcode to Customer

Extract the `barcode_ean_13` string directly from the confirmation response and generate a visual [EAN-13 barcode](https://www.cognex.com/resources/symbologies/1-d-linear-barcodes/ean-13-barcodes) in your frontend UI. The customer presents this screen to the merchant.

*(Note: You can still use the `GET /v1/cash_operations/{cash_operation_id}` endpoint later if you need to fetch the barcode again after the initial session.)*

### 4. Settlement and Webhooks

When the merchant scans the barcode and completes the physical cash exchange, Viafintech notifies Solaris. Solaris then resolves the initial reservation and posts a permanent booking (`CashWithdrawalRetail` or `CashDepositRetail`) to the customer's account.

Subscribe to the `CASH_OPERATION_STATUS_CHANGED` webhook to update your UI asynchronously.

**Status Values:**

* `PAID`: The transaction was successful at the POS.
* `CANCELLED`: The transaction was aborted.
* `EXPIRED`: The barcode validity window lapsed before it was scanned.


## Managing Cash Operations

### List all operations

To retrieve a history of cash operations for a specific account, use the account-level endpoint. You can filter the paginated results by status.

**Endpoint:** `GET /v1/accounts/{account_id}/cash_operations?filter[status]=PAID`

### Cancel an operation

You can cancel an operation before it is scanned by the merchant. This action triggers the `CASH_OPERATION_STATUS_CHANGED` webhook.

Status Restriction
You can only cancel cash operations that currently have a status of `PENDING` or `CREATED`.

**Endpoint:** `DELETE /v1/cash_operations/{cash_operation_id}`

## Testing in Sandbox

You can emulate the physical POS scan in the Sandbox environment to test your webhook integration and state management.

Sandbox Constraint
You may only emulate events on cash operations that have a status of `CREATED`.

**Endpoint:** `PATCH /v1/cash_operations/{cash_operation_id}`


```json
{
  "status": "PAID"
}
```

*Allowed values for manual Sandbox testing: `PAID`, `EXPIRED`, `CANCELLED`*.

## Webhooks

### CASH_OPERATION_STATUS_CHANGED

Solaris triggers this webhook when a customer pays out or pays in to a cash operation, or when the operation expires.

**API Reference:** [`POST cash_operation_status_changed`](/api-reference/onboarding/webhooks/webhook-events/paths/cash_operation_status_changed/post)

Informational Use Only
Webhooks are intended for informational purposes only. Do not act directly on the data contained in the webhook payload. Always use the `GET` endpoint to retrieve the single source of truth for a cash operation resource before updating critical financial states in your application.

#### Payload Structure

The webhook delivers a JSON payload containing the following fields.

| Field | Type | Description |
|  --- | --- | --- |
| `id` | string | ID of the cash operation. |
| `barcode_ean_13` | string | The EAN-13 barcode that your solution must generate. |
| `expires_at` | string | The date and time when the cash operation barcode expires. |
| `status` | string | The current status of the cash operation (`PENDING`, `CREATED`, `PAID`, `EXPIRED`, or `CANCELLED`). |
| `reference_id` | string | End-to-end reference for the customer. |
| `person_id` | string | ID of the person who initiated the cash operation. |


#### Example Payload


```json
{
  "id": "ffb18faf3c004f70a44c83b787488ceeslip",
  "barcode_ean_13": "4053110826660",
  "expires_at": "2026-01-04T09:15:59.958864Z",
  "status": "PAID",
  "reference_id": "f92beb45-b46e-4733-be1a-80c085cbad0d",
  "person_id": "2231bdf43cf7b9041367d9ed5c6d4c7acper"
}
```

## API Reference

Explore the full technical specifications for the Cash Operations endpoints.

Create Cash Operation
Initiate a deposit or withdrawal request.

Manage Cash Operations
Retrieve, list, or cancel active cash operations.