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

# Create account invoice

> Create an invoice for a specific connected account.

When the invoice is paid, funds settle into the targeted account's balance flow rather than being hard-wired to the integrator's main company.




## OpenAPI

````yaml /openapi/connect.yaml post /accounts/invoices/create
openapi: 3.0.4
info:
  title: SideShift Connect
  version: 1.0.0
  description: >
    Embed payment infrastructure directly into your platform. Create accounts
    for your users, transfer funds in any direction, and drop in pre-built
    payout and pay-in widgets — all through a single API.


    ## Setup Guide


    ### 1. Generate an API Key


    Go to [Settings → Connect](https://app.sideshift.app/settings?tab=embed) and
    click **Generate API Key**.


    Copy it immediately — keys are only shown once.


    - `sk_live_*` — Production (real money)

    - `sk_test_*` — Sandbox (isolated balances, simulated payouts)


    > **Never expose your API key in client-side code.** All API calls must be
    made from your backend.


    ### 2. Add Allowed Domains


    In Settings → Connect, add the domains where you'll embed widgets:


    | Pattern | Matches |

    |---------|---------|

    | `app.example.com` | Exact match |

    | `*.example.com` | All subdomains |

    | `localhost` | Any port (auto-allowed for development) |


    ### 3. Create User Accounts


    Every user who needs access to payments needs a SideShift Connect account:


    ```bash

    curl -X POST https://app.sideshift.app/api/embed/accounts/create \
      -H "x-api-key: sk_live_YOUR_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "email": "jane@example.com", "name": "Jane Creator", "externalId": "usr_123" }'
    ```


    Store the returned `sideshiftAccountId` — you'll need it for everything
    else.


    ### 4. Generate a Widget Token


    Tokens authenticate embedded widget sessions. Generate them server-side:


    ```bash

    curl -X POST https://app.sideshift.app/api/embed/auth/token \
      -H "x-api-key: sk_live_YOUR_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "sideshiftAccountId": "acct_abc123", "widgetType": "both" }'
    ```


    The response includes `widgetUrls.payout` and `widgetUrls.payin` — use these
    as iframe sources or pass them to the SDK.


    ### 5. Embed the Widget


    **iframe (recommended):**

    ```html

    <iframe
      src="WIDGET_URL"
      width="100%" height="500"
      frameborder="0"
      allow="payment; camera; microphone"
      style="border:0; border-radius:12px"
    ></iframe>

    ```

    The iframe is the most reliable method — it works in any framework, needs no
    build tooling, and avoids dependency conflicts. The `allow="payment; camera;
    microphone"` attribute is required for KYC/identity verification inside the
    widget.


    **npm SDK (alternative):**

    ```jsx

    import { SideShiftPayout } from '@sideshiftapp/connect/react';


    <SideShiftPayout
      token={token}
      theme={{ theme: 'light', primaryColor: '#3D8CFA', borderRadius: 12 }}
      onWithdrawCompleted={(data) => console.log('Withdrew', data.amountCents)}
      onSessionExpired={() => refreshToken()}
    />

    ```

    The SDK is a thin wrapper around the same iframe — you get typed props,
    auto-resize, and event callbacks. Also available as
    `@sideshiftapp/connect/vanilla`.


    **iOS (SwiftUI):**

    ```swift

    SideShiftConnect.configure(apiKey: "sk_live_YOUR_KEY")

    SideShiftPayoutView(accountId: "acct_abc123", currency: "USD")

    ```

    The iOS SDK manages tokens internally — no server-side token generation
    needed.


    ### 6. Transfer Funds


    Move money between your company and user accounts:


    ```bash

    curl -X POST https://app.sideshift.app/api/embed/accounts/transfer \
      -H "x-api-key: sk_live_YOUR_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "toAccountId": "acct_abc123",
        "amountCents": 5000,
        "idempotencyKey": "payout-001",
        "metadata": {
          "obligationType": "creator_agreement",
          "obligationReference": "agreement-001",
          "description": "Approved payment for completed creator deliverable",
          "approvalReference": "approval-001"
        }
      }'
    ```


    ### 7. Set Up Webhooks


    Configure a webhook endpoint in Settings → Connect to receive
    `transfer.completed`, `deposit.*`, and `withdrawal.*` events. Always verify
    the signature:


    ```js

    const crypto = require("crypto");

    function verify(payload, timestamp, signature, secret) {
      const expected = crypto.createHmac("sha256", secret).update(`${timestamp}.${payload}`).digest("hex");
      return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
    }

    ```


    ---


    ## Authentication


    Include your API key in the `x-api-key` header on every request:


    ```

    x-api-key: sk_live_your_key_here

    ```


    Rotate your key anytime from Settings → Connect. The old key is invalidated
    immediately.


    ## Sandbox


    Use `sk_test_*` keys to test without moving real money. Sandbox balances are
    fully isolated from live. Webhooks still fire so you can validate your full
    pipeline. All API endpoints behave identically (same validation, same error
    codes, same response shapes).


    ### Sandbox behavior


    - `paymentAccountId` values are prefixed with `sim_biz_*` (simulated)

    - Company → User transfers are simulated — no real payout is executed, but
    the internal ledger is updated normally

    - User → Company and User → User transfers work identically to production

    - Webhook events are delivered to your configured endpoint

    - Leaderboard and notification side effects are **not** triggered


    ### Payout widget in sandbox


    When a widget token is generated with a `sk_test_*` key, the payout widget
    automatically uses SideShift's sandbox payout environment. No additional
    configuration is required.


    > **Important:** The payout widget shows "Pending Balance from your
    platform" instead of the actual balance in sandbox mode. This is expected.


    When you transfer funds with a `sk_test_*` key, the sandbox wallet is
    credited correctly on the internal ledger. However, the payout widget's
    withdrawal UI cannot display the real balance because the company ID is
    simulated (`sim_biz_*`) and the widget relies on the real payments
    infrastructure to resolve balances.


    - The `passedInBalance` field (if set) appears as a display-only "Pending
    Balance" label

    - The withdrawal flow (bank account linking, payout initiation) is not fully
    functional in sandbox


    **In production** with `sk_live_*` keys, transfers call the real payments
    API, funds land in the creator's real wallet, and the balance + withdrawal
    UI works normally.


    **To verify sandbox transfers are working**, use the balance API — this is
    the source of truth:


    ```bash

    GET /accounts/balance?sideshiftAccountId=ACCOUNT_ID

    ```


    The `balanceCents` and `transactions` in the response accurately reflect all
    sandbox transfers.


    ### Testing checklist


    1. Generate `sk_test_*` key and store securely

    2. Create at least two sandbox accounts

    3. Test all three transfer directions (company→user, user→company,
    user→user)

    4. Verify balances via the balance API after each transfer

    5. Replay a transfer with the same `idempotencyKey` — confirm no duplicate

    6. Confirm webhook arrives and signature verification passes

    7. Trigger error cases (insufficient balance, invalid account) and verify
    your handling

    8. Test widget token generation and embedding


    ### Go-live checklist


    Before switching to `sk_live_*`:


    1. Store your live API key in a production secrets manager

    2. Confirm production domains in Settings → Connect (remove dev wildcards)

    3. Verify webhook endpoint uses HTTPS and validates signatures

    4. Add retry handling with idempotency keys in your backend

    5. Attach commercial evidence metadata to every transfer

    6. Run a small live test (e.g. $0.50 transfer) before full volume


    ## Idempotency


    Always include an `idempotencyKey` on transfer requests. Replaying a request
    with the same key returns the original successful result instead of creating
    a duplicate.


    ## Rate Limits


    | Endpoint | Limit |

    |----------|-------|

    | Account creation | 100/hour |

    | Token generation | 30/min per account |

    | Transfers | 60/min (configurable) |

    | General | 100/min |


    Exceeding limits returns `429` with a `Retry-After` header.


    ## Base URL


    `https://app.sideshift.app/api/embed`
  contact:
    name: SideShift Support
    url: https://app.sideshift.app
servers:
  - url: https://app.sideshift.app/api/embed
    description: Production / Sandbox (determined by API key prefix)
security:
  - apiKeyAuth: []
tags:
  - name: Accounts
    description: >-
      Create and manage user accounts. Each user gets a `sideshiftAccountId` and
      a wallet for receiving and sending funds.
  - name: Verifications
    description: >-
      Read identity verification status and required actions for connected
      accounts.
  - name: Transfers
    description: >-
      Move funds between your company and user accounts. Supports company→user,
      user→company, and user→user directions.
  - name: Tokens
    description: >-
      Generate short-lived access tokens that authenticate embedded widget
      sessions.
  - name: Checkout
    description: >-
      Create public hosted checkout links that settle into your SideShift
      wallet.
  - name: Webhooks
    description: >
      Receive real-time event notifications when transfers, deposits, and
      withdrawals complete or fail. Configure endpoints in Settings → Connect.


      **Available events:** `deposit.pending`, `deposit.confirmed`,
      `deposit.failed`, `transfer.completed`, `withdrawal.created`,
      `withdrawal.updated`, `withdrawal.completed`, `account.risk_flagged`


      `withdrawal.completed` is a derived alias of `withdrawal.updated` filtered
      to `status === "completed"`. Subscribe to it if you only want the
      terminal-success event; subscribe to `withdrawal.updated` for the full
      lifecycle (`requested → awaiting_payment → in_transit → completed | failed
      | canceled | denied`).


      All webhook deliveries include `x-sideshift-signature` and
      `x-sideshift-timestamp` headers for signature verification. Non-2xx
      responses are retried with exponential backoff (up to 5 attempts).
      Webhooks fire in both sandbox and production modes.
paths:
  /accounts/invoices/create:
    post:
      tags:
        - Accounts
      summary: Create account invoice
      description: >
        Create an invoice for a specific connected account.


        When the invoice is paid, funds settle into the targeted account's
        balance flow rather than being hard-wired to the integrator's main
        company.
      operationId: createAccountInvoice
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - sideshiftAccountId
                - customerName
                - customerEmail
                - lineItems
                - dueDate
              properties:
                sideshiftAccountId:
                  type: string
                  description: Connected account that should receive invoice proceeds
                  example: acct_a1b2c3d4e5f6
                customerId:
                  type: string
                  nullable: true
                  description: Existing customer ID to associate with the invoice
                customerName:
                  type: string
                  description: Invoice recipient full name
                customerEmail:
                  type: string
                  format: email
                  description: Primary invoice recipient email
                additionalEmails:
                  type: array
                  description: >-
                    Additional recipient emails that should also receive the
                    invoice email
                  items:
                    type: string
                    format: email
                customerAddress:
                  type: object
                  nullable: true
                  description: Optional recipient mailing address
                  properties:
                    line1:
                      type: string
                    line2:
                      type: string
                    city:
                      type: string
                    state:
                      type: string
                    postalCode:
                      type: string
                    country:
                      type: string
                lineItems:
                  type: array
                  description: One or more invoice line items
                  items:
                    type: object
                    required:
                      - description
                      - quantity
                      - unitPriceCents
                    properties:
                      description:
                        type: string
                        description: Line item label shown on the invoice
                      quantity:
                        type: integer
                        minimum: 1
                        description: Positive integer quantity
                      unitPriceCents:
                        type: integer
                        minimum: 1
                        description: Price per unit in cents
                dueDate:
                  type: string
                  format: date-time
                  description: Invoice due date as an ISO 8601 timestamp
                paymentType:
                  type: string
                  enum:
                    - one_time
                    - renewal
                  default: one_time
                  description: Billing mode for the invoice
                currency:
                  type: string
                  pattern: ^[a-z]{3}$
                  default: usd
                  description: 3-letter lowercase ISO 4217 currency code
                  example: usd
                taxCents:
                  type: integer
                  minimum: 0
                  default: 0
                  description: Optional tax amount in cents
                discountCents:
                  type: integer
                  minimum: 0
                  default: 0
                  description: Optional discount amount in cents
                collectCustomerFee:
                  type: boolean
                  default: true
                  description: Whether customer-facing processing fees should be collected
                feeConfig:
                  type: object
                  description: >-
                    Optional fee overrides. Supported keys are `card` and
                    `us_bank_account`
                  properties:
                    card:
                      type: object
                      properties:
                        percentFee:
                          type: number
                          minimum: 0
                        fixedFeeCents:
                          type: integer
                          minimum: 0
                    us_bank_account:
                      type: object
                      properties:
                        percentFee:
                          type: number
                          minimum: 0
                        fixedFeeCents:
                          type: integer
                          minimum: 0
                allowedPaymentTypes:
                  type: array
                  minItems: 1
                  default:
                    - card
                  description: >
                    Checkout payment methods allowed for this invoice.

                    Supported values: `card`, `apple_pay`, `google_pay`, `link`,
                    `us_bank_account`,

                    `sepa_debit`, `bacs_debit`, `acss_debit`, `au_becs_debit`,
                    `cashapp`, `paypal`,

                    `venmo`, `klarna`, `affirm`, `afterpay_clearpay`, `crypto`
                  items:
                    type: string
                    enum:
                      - card
                      - apple_pay
                      - google_pay
                      - link
                      - us_bank_account
                      - sepa_debit
                      - bacs_debit
                      - acss_debit
                      - au_becs_debit
                      - cashapp
                      - paypal
                      - venmo
                      - klarna
                      - affirm
                      - afterpay_clearpay
                      - crypto
                description:
                  type: string
                  nullable: true
                  description: Optional internal invoice description
                notes:
                  type: string
                  nullable: true
                  description: Optional invoice notes
                terms:
                  type: string
                  nullable: true
                  description: Optional payment terms text
                sendReminders:
                  type: boolean
                  default: true
                  description: >-
                    Whether invoice reminders should be enabled on the invoice
                    record
                sendNow:
                  type: boolean
                  default: true
                  description: When false, create without sending the initial invoice email
            example:
              sideshiftAccountId: acct_a1b2c3d4e5f6
              customerId: cust_123
              customerName: Jane Doe
              customerEmail: jane@example.com
              additionalEmails:
                - ap@customer.com
              customerAddress:
                line1: 123 Market St
                city: San Francisco
                state: CA
                postalCode: '94105'
                country: US
              lineItems:
                - description: Campaign budget
                  quantity: 1
                  unitPriceCents: 50000
              dueDate: '2026-04-01T00:00:00.000Z'
              paymentType: one_time
              currency: usd
              taxCents: 2500
              discountCents: 500
              collectCustomerFee: true
              feeConfig:
                card:
                  percentFee: 0.029
                  fixedFeeCents: 30
                us_bank_account:
                  percentFee: 0.008
                  fixedFeeCents: 0
              allowedPaymentTypes:
                - card
                - us_bank_account
              description: April campaign budget
              notes: 'PO #1048'
              terms: Payment due within 14 days
              sendReminders: true
              sendNow: true
      responses:
        '200':
          description: Invoice created
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      sideshiftAccountId:
                        type: string
                      url:
                        type: string
                      invoice:
                        type: object
                        properties:
                          id:
                            type: string
                          companyId:
                            type: string
                          customerEmail:
                            type: string
                          status:
                            type: string
                          totalCents:
                            type: integer
              example:
                success: true
                data:
                  sideshiftAccountId: acct_a1b2c3d4e5f6
                  url: https://app.sideshift.app/invoice/inv_local_123
                  invoice:
                    id: inv_local_123
                    companyId: acct_a1b2c3d4e5f6
                    customerEmail: jane@example.com
                    status: open
                    totalCents: 50000
        '400':
          description: Validation error
        '404':
          description: Account not found or not owned by this integration
components:
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        Your SideShift Connect API key (`sk_live_*` or `sk_test_*`). Generate
        from Settings → Connect.

````