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

# Create Spend Account for Authorized User

> Create a spend account on your account and assign an authorized user as its owner.

Spend accounts are always created **on the caller's account** — there is no way to create one that lives on someone else's account. What you can do is create the spend account and then record an authorized user as its **owner**, so the account has a named person responsible for it.

Unlike [`createVirtualCard`](/features/create-virtual-card-for-authorized-user), `createUserCashBalance` does **not** take an `authUserId`. Ownership is a separate, second call: [`assignObjectOwner`](/api-reference/mutations/assign-object-owner) with `objectType: SPEND_ACCOUNTS`.

<Note>
  **Ownership is metadata, not access.**

  Assigning an owner records who is responsible for a spend account. It does not, on its own, grant that person the ability to spend from it. Effective access is still the higher of the user's account role ([`UACRoleType`](/api-reference/types/uacrole-type)) and any item-level access granted on the spend account itself.

  Assign the owner **and** make sure the user's role gives them the access you actually intend.
</Note>

***

## Prerequisites

<Steps>
  <Step title="The authorized user exists and is ACTIVE">
    Add them with [`addAuthorizedUser`](/features/create-authorized-users) and confirm the returned `status` is `ACTIVE`. A `PENDING` assignment cannot be used as an owner — the user must accept the invite first.
  </Step>

  <Step title="Your token carries both scopes">
    `createUserCashBalance` requires `MANAGE_PAYMENT`. `assignObjectOwner` requires `MANAGE_SUBUSERS`. A single Bearer token needs both to run this flow end to end.
  </Step>

  <Step title="You have the authorized user's userId">
    `assignObjectOwner` is keyed on `userId`, not `authUserId`. See [Resolving the userId](#resolving-the-userid) below.
  </Step>
</Steps>

***

## Step 1 — Create the spend account

Create the spend account exactly as you normally would. It is created on the caller's account with no owner attached.

```graphql theme={null}
mutation CreateUserCashBalance($input: CreateUserCashBalanceInput!) {
  createUserCashBalance(input: $input) {
    userCashBalanceId
    nickname
    availableCashBalance
    status
    createdAt
  }
}
```

```json theme={null}
{
  "input": {
    "nickname": "Ada — Field Ops"
  }
}
```

Save the returned `userCashBalanceId`. That value is the `objectId` in Step 3.

<Info>
  Give the account a nickname that identifies the owner. Ownership metadata is not surfaced in every list view, so a nickname like `"Ada — Field Ops"` keeps the account legible in [`getUserCashBalances`](/features/get-spend-accounts) without an extra lookup.
</Info>

***

## Resolving the userId

`assignObjectOwner` takes the authorized user's **`userId`** — the underlying user record. This is a different value from the **`authUserId`** returned by `addAuthorizedUser` and [`authorizedUsers`](/features/query-authorized-user), which identifies the UAC *role assignment*.

The `AuthorizedUser` type does not currently expose `userId`. Today the documented ways to obtain it are:

| Source                                                                   | How you get it                                                                                                                      |
| :----------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------- |
| [`createVirtualCard`](/features/create-virtual-card-for-authorized-user) | When called with `authUserId`, the response `userId` is the authorized user's user ID.                                              |
| [`registerUser`](/user-registration)                                     | If your platform registered the user, persist the user ID at registration time and store it against your own record of that person. |

<Warning>
  Do not pass an `authUserId` where `userId` is expected. The two are both `UUID` and the mutation will not catch the substitution as a type error — you will get a failed or misdirected ownership assignment instead.
</Warning>

***

## Step 2 — Assign the authorized user as owner

<Card title="Restricted Access" icon="lock">
  This mutation requires a Bearer token with the `MANAGE_SUBUSERS` scope.
</Card>

```graphql theme={null}
mutation AssignObjectOwner(
  $objectType: ObjectOwnerObjectType!
  $objectId: UUID!
  $userId: UUID!
) {
  assignObjectOwner(
    objectType: $objectType
    objectId: $objectId
    userId: $userId
  ) {
    success
    objectOwnerId
    accountId
    objectType
    objectId
    userId
    createdAt
    error {
      code
      message
    }
  }
}
```

### Parameters

| Parameter    | Type                     | Required | Description                                                                                  |
| :----------- | :----------------------- | :------- | :------------------------------------------------------------------------------------------- |
| `objectType` | `ObjectOwnerObjectType!` | Yes      | Use `SPEND_ACCOUNTS`. Other values are `VIRTUAL_CARDS`, `GIFT_CARDS`, and `FUNDING_SOURCES`. |
| `objectId`   | `UUID!`                  | Yes      | The `userCashBalanceId` returned in Step 1.                                                  |
| `userId`     | `UUID!`                  | Yes      | The authorized user's user ID. Must be a user on the caller's account. Not the `authUserId`. |

<Note>
  `assignObjectOwner` only assigns an owner to an object that **does not have one yet**. If the spend account already has an owner, the call will not overwrite it — use [`transferObjectOwner`](#reassigning-ownership) instead.
</Note>

### Sample response

```json theme={null}
{
  "data": {
    "assignObjectOwner": {
      "success": true,
      "objectOwnerId": "3c7a1b52-9e4d-4f88-a2c1-5d6e7f8a9b01",
      "accountId": "b41e2d90-6a77-4c35-9f12-8e0d3a4b5c6d",
      "objectType": "SPEND_ACCOUNTS",
      "objectId": "f8a3c9e1-7b2d-4f5e-9c8a-1d2e3f4a5b6c",
      "userId": "f1320ac4-52dc-4c67-9e80-24e506b18450",
      "createdAt": "2026-08-10T14:22:00.000Z",
      "error": null
    }
  }
}
```

### Response fields

| Field           | Type               | Description                                                                    |
| :-------------- | :----------------- | :----------------------------------------------------------------------------- |
| `success`       | `Boolean!`         | Whether the assignment was recorded.                                           |
| `objectOwnerId` | `UUID`             | The ownership record ID. **Save this** — `transferObjectOwner` is keyed on it. |
| `accountId`     | `UUID`             | The account the object and owner belong to.                                    |
| `objectType`    | `String`           | Echoes the object domain, `SPEND_ACCOUNTS`.                                    |
| `objectId`      | `UUID`             | The spend account ID that was assigned an owner.                               |
| `userId`        | `UUID`             | The user now recorded as owner.                                                |
| `createdAt`     | `DateTime`         | When the ownership record was created.                                         |
| `error`         | `ObjectOwnerError` | Error details when `success` is `false`.                                       |

***

## Reassigning ownership

Ownership moves with [`transferObjectOwner`](/api-reference/mutations/transfer-object-owner), which takes the `objectOwnerId` from the original assignment rather than the spend account ID.

```graphql theme={null}
mutation TransferObjectOwner($objectOwnerId: UUID!, $userId: UUID!) {
  transferObjectOwner(objectOwnerId: $objectOwnerId, userId: $userId) {
    success
    objectOwnerId
    objectId
    userId
    updatedAt
    error {
      code
      message
    }
  }
}
```

The new owner must be a user on the same account. This is the call to make when an authorized user leaves the team and their spend accounts need to land with someone else — removing the authorized user does not reassign the objects they owned.

***

## Full flow

Add an authorized user, create a spend account for them, and record them as its owner.

**Step 1 — Add the authorized user.**

```curl theme={null}
curl -X POST https://transactional-graph.staging.fluzapp.com/api/v1/graphql \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <account_owner_access_token>" \
  -d '{
  "query": "mutation AddAuthorizedUser($email: String, $roles: [UACRoleType!]!) { addAuthorizedUser(email: $email, roles: $roles) { success authUserId roles status error { code message } } }",
  "variables": {
    "email": "ada.lovelace@example.com",
    "roles": ["SPENDER"]
  }
}'
```

Continue only once `status` is `ACTIVE`.

**Step 2 — Create the spend account.**

```curl theme={null}
curl -X POST https://transactional-graph.staging.fluzapp.com/api/v1/graphql \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <account_owner_access_token>" \
  -d '{
  "query": "mutation CreateUserCashBalance($input: CreateUserCashBalanceInput!) { createUserCashBalance(input: $input) { userCashBalanceId nickname availableCashBalance status createdAt } }",
  "variables": {
    "input": {
      "nickname": "Ada — Field Ops"
    }
  }
}'
```

**Step 3 — Assign the authorized user as owner.**

```curl theme={null}
curl -X POST https://transactional-graph.staging.fluzapp.com/api/v1/graphql \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <account_owner_access_token>" \
  -d '{
  "query": "mutation AssignObjectOwner($objectType: ObjectOwnerObjectType!, $objectId: UUID!, $userId: UUID!) { assignObjectOwner(objectType: $objectType, objectId: $objectId, userId: $userId) { success objectOwnerId objectId userId createdAt error { code message } } }",
  "variables": {
    "objectType": "SPEND_ACCOUNTS",
    "objectId": "f8a3c9e1-7b2d-4f5e-9c8a-1d2e3f4a5b6c",
    "userId": "f1320ac4-52dc-4c67-9e80-24e506b18450"
  }
}'
```

**Step 4 — Fund it.** The spend account starts at a zero balance. Deposit into it with [`depositCashBalance`](/features/deposit-from-external-accounts) or move funds across from another spend account with [`transferInternalBalance`](/features/transfer-between-spend-accounts), targeting the new `userCashBalanceId`.

### TypeScript

```typescript theme={null}
const graphql = async (query: string, variables: Record<string, unknown>) => {
  const response = await fetch(
    'https://transactional-graph.staging.fluzapp.com/api/v1/graphql',
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${accessToken}`,
      },
      body: JSON.stringify({ query, variables }),
    },
  );
  return response.json();
};

// 1. Create the spend account.
const created = await graphql(
  `mutation CreateUserCashBalance($input: CreateUserCashBalanceInput!) {
     createUserCashBalance(input: $input) {
       userCashBalanceId
       nickname
       status
     }
   }`,
  { input: { nickname: 'Ada — Field Ops' } },
);

const { userCashBalanceId } = created.data.createUserCashBalance;

// 2. Record the authorized user as its owner.
const assigned = await graphql(
  `mutation AssignObjectOwner(
     $objectType: ObjectOwnerObjectType!
     $objectId: UUID!
     $userId: UUID!
   ) {
     assignObjectOwner(
       objectType: $objectType
       objectId: $objectId
       userId: $userId
     ) {
       success
       objectOwnerId
       error { code message }
     }
   }`,
  {
    objectType: 'SPEND_ACCOUNTS',
    objectId: userCashBalanceId,
    userId: authorizedUserUserId,
  },
);

// Persist objectOwnerId — transferObjectOwner is keyed on it, not on the
// spend account ID.
const { objectOwnerId } = assigned.data.assignObjectOwner;
```

***

## Error codes

| Code        | Description                                                                                                                                  |
| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------- |
| `ARG-0001`  | Required input is missing or invalid — `objectId` is not a spend account on the caller's account, or `userId` is not a user on that account. |
| `AUTH-0008` | The Bearer token could not be resolved to a caller. Verify the token is valid.                                                               |
| `AUTH-0031` | The token is missing the `MANAGE_SUBUSERS` scope required to assign or transfer object ownership.                                            |

***

<CardGroup cols={2}>
  <Card title="Authorized User Overview" icon="users" href="/features/authorized-user-overview">
    Roles, statuses, and the full authorized user lifecycle.
  </Card>

  <Card title="Create Virtual Card for Authorized User" icon="credit-card" href="/features/create-virtual-card-for-authorized-user">
    Issue a card on an authorized user's behalf with `authUserId`.
  </Card>

  <Card title="Spend Accounts Overview" icon="wallet" href="/features/spend-accounts">
    Creating, reading, editing, and closing spend accounts.
  </Card>

  <Card title="Remove Authorized User" icon="user-minus" href="/features/remove-authorized-user">
    What happens to owned objects when access is revoked.
  </Card>
</CardGroup>
