> ## 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.

# Crear cuenta de gasto para usuario autorizado

> Crea una cuenta de gasto en tu cuenta y asigna a un usuario autorizado como su propietario.

Las cuentas de gasto siempre se crean **en la cuenta del solicitante** — no hay forma de crear una que viva en la cuenta de otra persona. Lo que puedes hacer es crear la cuenta de gasto y luego registrar a un usuario autorizado como su **propietario**, para que la cuenta tenga una persona responsable con nombre.

A diferencia de [`createVirtualCard`](/features/create-virtual-card-for-authorized-user), `createUserCashBalance` **no** recibe un `authUserId`. La titularidad es una llamada separada y posterior: [`assignObjectOwner`](/api-reference/mutations/assign-object-owner) con `objectType: SPEND_ACCOUNTS`.

<Note>
  **La titularidad es metadato, no acceso.**

  Asignar un propietario registra quién es responsable de una cuenta de gasto. Por sí sola, no otorga a esa persona la capacidad de gastar de ella. El acceso efectivo sigue siendo el mayor entre el rol de cuenta del usuario ([`UACRoleType`](/api-reference/types/uacrole-type)) y cualquier acceso a nivel de ítem concedido en la propia cuenta de gasto.

  Asigna al propietario **y** asegúrate de que el rol del usuario le brinde el acceso que realmente pretendes.
</Note>

***

## Requisitos previos

<Steps>
  <Step title="El usuario autorizado existe y está ACTIVE">
    Agrégalo con [`addAuthorizedUser`](/features/create-authorized-users) y confirma que el `status` devuelto sea `ACTIVE`. Una asignación `PENDING` no puede usarse como propietario — el usuario debe aceptar la invitación primero.
  </Step>

  <Step title="Tu token incluye ambos alcances (scopes)">
    `createUserCashBalance` requiere `MANAGE_PAYMENT`. `assignObjectOwner` requiere `MANAGE_SUBUSERS`. Un único token Bearer necesita ambos para ejecutar este flujo de principio a fin.
  </Step>

  <Step title="Tienes el userId del usuario autorizado">
    `assignObjectOwner` se basa en `userId`, no en `authUserId`. Consulta [Cómo resolver el userId](#resolving-the-userid) abajo.
  </Step>
</Steps>

***

## Paso 1 — Crea la cuenta de gasto

Crea la cuenta de gasto exactamente como lo harías normalmente. Se crea en la cuenta del solicitante sin propietario asignado.

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

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

Guarda el `userCashBalanceId` devuelto. Ese valor es el `objectId` en el Paso 3.

<Info>
  Dale a la cuenta un apodo que identifique al propietario. Los metadatos de titularidad no se muestran en todas las vistas de lista, por lo que un apodo como `"Ada — Field Ops"` mantiene la cuenta legible en [`getUserCashBalances`](/features/get-spend-accounts) sin una búsqueda adicional.
</Info>

***

## Cómo resolver el userId

`assignObjectOwner` recibe el **`userId`** del usuario autorizado — el registro subyacente del usuario. Este es un valor diferente del **`authUserId`** devuelto por `addAuthorizedUser` y [`authorizedUsers`](/features/query-authorized-user), que identifica la *asignación de rol* de UAC.

El tipo `AuthorizedUser` actualmente no expone `userId`. Hoy, las formas documentadas de obtenerlo son:

| Fuente                                                                   | Cómo lo obtienes                                                                                                                            |
| :----------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------ |
| [`createVirtualCard`](/features/create-virtual-card-for-authorized-user) | Cuando se llama con `authUserId`, el `userId` en la respuesta es el ID de usuario del usuario autorizado.                                   |
| [`registerUser`](/user-registration)                                     | Si tu plataforma registró al usuario, conserva el ID de usuario en el momento del registro y guárdalo en tu propio registro de esa persona. |

<Warning>
  No envíes un `authUserId` donde se espera `userId`. Ambos son `UUID` y la mutación no detectará la sustitución como un error de tipo — en su lugar obtendrás una asignación de titularidad fallida o mal dirigida.
</Warning>

***

## Paso 2 — Asigna al usuario autorizado como propietario

<Card title="Acceso restringido" icon="lock">
  Esta mutación requiere un token Bearer con el alcance `MANAGE_SUBUSERS`.
</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
    }
  }
}
```

### Parámetros

| Parámetro    | Tipo                     | Requerido | Descripción                                                                                                       |
| :----------- | :----------------------- | :-------- | :---------------------------------------------------------------------------------------------------------------- |
| `objectType` | `ObjectOwnerObjectType!` | Sí        | Usa `SPEND_ACCOUNTS`. Otros valores son `VIRTUAL_CARDS`, `GIFT_CARDS` y `FUNDING_SOURCES`.                        |
| `objectId`   | `UUID!`                  | Sí        | El `userCashBalanceId` devuelto en el Paso 1.                                                                     |
| `userId`     | `UUID!`                  | Sí        | El ID de usuario del usuario autorizado. Debe ser un usuario en la cuenta del solicitante. No es el `authUserId`. |

<Note>
  `assignObjectOwner` solo asigna un propietario a un objeto que **aún no tiene uno**. Si la cuenta de gasto ya tiene un propietario, la llamada no lo sobrescribirá — usa [`transferObjectOwner`](#reassigning-ownership) en su lugar.
</Note>

### Respuesta de ejemplo

```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
    }
  }
}
```

### Campos de respuesta

| Campo           | Tipo               | Descripción                                                                            |
| :-------------- | :----------------- | :------------------------------------------------------------------------------------- |
| `success`       | `Boolean!`         | Indica si se registró la asignación.                                                   |
| `objectOwnerId` | `UUID`             | El ID del registro de titularidad. **Guárdalo** — `transferObjectOwner` se basa en él. |
| `accountId`     | `UUID`             | La cuenta a la que pertenecen el objeto y el propietario.                              |
| `objectType`    | `String`           | Repite el dominio del objeto, `SPEND_ACCOUNTS`.                                        |
| `objectId`      | `UUID`             | El ID de la cuenta de gasto a la que se asignó un propietario.                         |
| `userId`        | `UUID`             | El usuario ahora registrado como propietario.                                          |
| `createdAt`     | `DateTime`         | Cuándo se creó el registro de titularidad.                                             |
| `error`         | `ObjectOwnerError` | Detalles del error cuando `success` es `false`.                                        |

***

## Reasignación de titularidad

La titularidad se traslada con [`transferObjectOwner`](/api-reference/mutations/transfer-object-owner), que recibe el `objectOwnerId` de la asignación original en lugar del ID de la cuenta de gasto.

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

El nuevo propietario debe ser un usuario en la misma cuenta. Esta es la llamada que debes hacer cuando un usuario autorizado deja el equipo y sus cuentas de gasto deben pasar a otra persona — eliminar al usuario autorizado no reasigna los objetos que poseía.

***

## Flujo completo

Agrega un usuario autorizado, crea una cuenta de gasto para él y regístralo como su propietario.

**Paso 1 — Agrega al usuario autorizado.**

```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"]
  }
}'
```

Continúa solo cuando `status` sea `ACTIVE`.

**Paso 2 — Crea la cuenta de gasto.**

```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"
    }
  }
}'
```

**Paso 3 — Asigna al usuario autorizado como propietario.**

```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"
  }
}'
```

**Paso 4 — Fondea la cuenta.** La cuenta de gasto comienza con saldo cero. Deposita en ella con [`depositCashBalance`](/features/deposit-from-external-accounts) o mueve fondos desde otra cuenta de gasto con [`transferInternalBalance`](/features/transfer-between-spend-accounts), apuntando al nuevo `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;
```

***

## Códigos de error

| Código      | Descripción                                                                                                                                               |
| :---------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ARG-0001`  | Falta una entrada requerida o es inválida — `objectId` no es una cuenta de gasto en la cuenta del solicitante, o `userId` no es un usuario en esa cuenta. |
| `AUTH-0008` | No se pudo resolver el token Bearer a un solicitante. Verifica que el token sea válido.                                                                   |
| `AUTH-0031` | Al token le falta el alcance `MANAGE_SUBUSERS` requerido para asignar o transferir la titularidad del objeto.                                             |

***

<CardGroup cols={2}>
  <Card title="Descripción general de usuario autorizado" icon="users" href="/features/authorized-user-overview">
    Roles, estados y el ciclo de vida completo del usuario autorizado.
  </Card>

  <Card title="Crear tarjeta virtual para usuario autorizado" icon="credit-card" href="/features/create-virtual-card-for-authorized-user">
    Emite una tarjeta en nombre de un usuario autorizado con `authUserId`.
  </Card>

  <Card title="Descripción general de cuentas de gasto" icon="wallet" href="/features/spend-accounts">
    Crear, leer, editar y cerrar cuentas de gasto.
  </Card>

  <Card title="Eliminar usuario autorizado" icon="user-minus" href="/features/remove-authorized-user">
    Qué sucede con los objetos en titularidad cuando se revoca el acceso.
  </Card>
</CardGroup>
