Referência / Quadra Command API
Squads
31 operações em Quadra Command API 0.2.0.
/v1/squadsCreate a Squad shared account
Create a Squad (RFC-018) and its Config UTxO at the SquadValidator.
Thin wrapper: payload validation → idempotency cache → ``SquadAdapter.create_instance`` → response caching. The creator becomes the sole OWNER member; the squad account row is persisted with ``vk=null`` (the squad has no key — chain enforces all authority). Caller-identity (ACTOR_MISMATCH) is enforced at the API Gateway, not here. Errors follow ``adding-api-endpoints.md``. Optional ``invitee_account_ids`` creates + invites atomically (every invitee validated before the irreversible tx). Optional ``metadata`` (description, emoji, image_url, location) is off-chain display data only. Errors: 400: INVALID_NAME, INVALID_DESCRIPTION, INVALID_EMOJI, INVALID_IMAGE_URL, INVALID_LOCATION, CANNOT_INVITE_SELF 404: ACCOUNT_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: INVALID_CREATOR_TYPE, SQUAD_AS_SQUAD_MEMBER_FORBIDDEN, ALREADY_A_MEMBER 503: HYDRA_UNAVAILABLE
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
SquadCreateRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 201 | — | Resposta bem-sucedidaO contrato não declara um modelo para esta resposta, então a forma dela não está documentada aqui. Um roteiro de demonstração mostra a forma que ela realmente devolve. |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}Owner: edit a squad's display metadata (name / emoji / image / location)
Edit a squad's off-chain display fields (RFC-018). OWNER-only. **No Cardano tx** — a conditional update of the squad's display-metadata projection (name lives off-chain, not in the Config datum). Partial update: omitted fields are left unchanged; an explicit ``null`` clears an optional metadata field (``name`` is required and not clearable). Allowed on OPEN and CLOSED squads alike (purely cosmetic). Caller-identity (ACTOR_MISMATCH) is enforced at the API Gateway, not here. Errors: 400: INVALID_NAME, INVALID_DESCRIPTION, INVALID_EMOJI, INVALID_IMAGE_URL, INVALID_LOCATION 403: INSUFFICIENT_ROLE, NOT_A_SQUAD_MEMBER 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
SquadUpdateRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | SquadUpdateResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/auto-collect/consentMember: grant / refresh auto-collect consent for a conta
Grant (or refresh) a standing, capped consent to auto-settle the caller's own share of ``rex_id`` each cycle (B-SQ-04 Assinatura). Own-share-only; off-chain (a projection write). ``max_amount`` caps per-cycle collection — a posted share above it SUSPENDS the consent (``consent_state=REQUIRES_RECONSENT``) rather than over-collecting. A re-grant re-activates a suspended consent. Errors: 400: INVALID_AMOUNT, UNSUPPORTED_CURRENCY 403: INSUFFICIENT_ROLE, NOT_A_SQUAD_MEMBER 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND, REX_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: SQUAD_CLOSED, SQUAD_FROZEN
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
ConsentRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | ConsentResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/auto-collect/consent/{consent_id}Member: revoke auto-collect consent (one tap)
Revoke an auto-collect consent (B-SQ-04). Hard-deletes the consent row so future cycles no longer auto-collect this member's share. Always allowed (even when frozen / closed). The caller may only revoke their own consent. Errors: 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND, CONSENT_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| consent_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
ConsentRevokeRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | ConsentRevokeResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/closeClose the squad (OWNER; terminal, irreversible)
Close the squad (RFC-018 §5.1, SQ-14). An OWNER closes once every member is at net-zero: the tx consumes the OPEN Config UTxO and recreates it with ``state="CLOSED"``. After close every write referencing the Config fails the validator's ``configIsOpen`` check (SI-7); reads continue indefinitely. Close is irreversible — there is no ``/reopen``. The net-zero preconditions (FUNDS_REMAINING / OPEN_ACCOUNTING_ROWS) are off-chain fast-fails and carry a ``details.non_zero_positions`` breakdown. Errors: 403: NOT_A_SQUAD_MEMBER, INSUFFICIENT_ROLE 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: SQUAD_ALREADY_CLOSED, FUNDS_REMAINING, OPEN_ACCOUNTING_ROWS, SETTLEMENT_IN_PROGRESS 503: HYDRA_UNAVAILABLE
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
CloseRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 201 | SquadCloseResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/contributionsContribute to a Squad (kind=FUNDED deposits QBRL; kind=ACCOUNTING records a split)
Record a squad contribution (RFC-018 §5.1, SQ-11 / SQ-13).
``kind=FUNDED`` moves QBRL from the actor's BancoBRL custody to a Balance UTxO at the SquadValidator (Config read as a reference input) and records an obligation. ``kind=ACCOUNTING`` records a non-monetary split: it resolves the split into per-debtor **share** UTxOs and mints the vQBRL across them (no QBRL moves). Caller-identity (ACTOR_MISMATCH) is enforced at the API Gateway. Errors: 400: UNSUPPORTED_CURRENCY, INVALID_AMOUNT, INVALID_KIND, INVALID_SPLIT, AMOUNTS_DO_NOT_SUM, UNKNOWN_MEMBER_IN_SPLIT, INVALID_DESCRIPTION, INVALID_SOURCE_TX 403: NOT_A_SQUAD_MEMBER, INSUFFICIENT_ROLE 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: INSUFFICIENT_BALANCE, SQUAD_CLOSED 503: HYDRA_UNAVAILABLE
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
ContributionRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 201 | — | Resposta bem-sucedidaO contrato não declara um modelo para esta resposta, então a forma dela não está documentada aqui. Um roteiro de demonstração mostra a forma que ela realmente devolve. |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/contributions/{entry_seq}Void (forgive) an accounting entry's unsettled shares (creditor only)
Void an accounting entry's still-unsettled shares (RFC-018 §5.1, SQ-13).
Implemented via ``VoidShare``: the **creditor** (original actor) consumes and burns the entry's remaining share UTxOs (no QBRL moves). Already-settled shares are simply already-consumed UTxOs, so voiding operates on whatever remains. Caller-identity is enforced at the API Gateway. Errors: 403: NOT_THE_CREDITOR, NOT_A_SQUAD_MEMBER, INSUFFICIENT_ROLE 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND, ACCOUNTING_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: SQUAD_CLOSED 503: HYDRA_UNAVAILABLE
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| entry_seq | integer | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
VoidContributionRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | SquadVoidResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/entries/{entry_seq}/splitOwner: manually re-split one expense's open shares
OWNER escape hatch (RFC-018): manually re-divide one expense's still-open shares when the general rule can't (e.g. a partially-settled entry). The entry is then flagged so automatic re-splits leave it alone. Errors: 400: INVALID_SPLIT, AMOUNTS_DO_NOT_SUM, UNKNOWN_MEMBER_IN_SPLIT 403: INSUFFICIENT_ROLE, NOT_A_SQUAD_MEMBER 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND, ACCOUNTING_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: SQUAD_CLOSED 503: HYDRA_UNAVAILABLE
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| entry_seq | integer | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
EntrySplitOverrideRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | SquadEntrySplitOverrideResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/freezeOwner: freeze a squad (wind-down; reversible)
Freeze a squad for wind-down (RFC-018). OWNER-only. **No Cardano tx** — flips an off-chain ``frozen`` flag on the squad's META row. The squad stays ``state=OPEN`` and fully readable, but deposits/spends/accounting and all roster changes are then rejected (422 SQUAD_FROZEN); settlement, close, decline-invite, and metadata edits keep working. Freezing is a prerequisite for ``simplify-debts``. Idempotent: freezing an already-frozen squad is a 200 no-op with ``changed=false``. Errors: 403: NOT_A_SQUAD_MEMBER, INSUFFICIENT_ROLE 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: SQUAD_CLOSED
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
SquadFreezeRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | SquadFreezeResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/goalOwner: remove a squad's savings goal
Remove a squad's savings goal (B-SQ-05). OWNER-only, off-chain. Allowed on OPEN and CLOSED squads alike (cleanup). Idempotent: clearing an absent goal still returns ``goal: null``. Only ``actor_account_id`` is read from the body. Errors: 403: INSUFFICIENT_ROLE, NOT_A_SQUAD_MEMBER 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
SquadGoalDeleteRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | SquadGoalDeleteResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/goalOwner: set or edit a squad's savings goal (target amount + optional date)
Set or edit a squad's savings goal (B-SQ-05). OWNER-only, **off-chain** (a projection write — no Cardano tx). The goal constrains nothing; it only measures. ``funded_cents`` / ``progress`` are computed from the live pool balance, and ``achieved_at`` is stamped (sticky) the first moment the pool reaches the target. Errors: 400: INVALID_GOAL_AMOUNT, INVALID_GOAL_DATE 403: INSUFFICIENT_ROLE, NOT_A_SQUAD_MEMBER 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: SQUAD_CLOSED
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
SquadGoalRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | SquadGoalResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/invitationsInvite one or more accounts to a Squad
Invite one or more accounts (RFC-018 invite flow). OWNER-only. Writes a PENDING invite projection row per invitee — **no Cardano tx**; an invitee enters the on-chain roster only when they accept. **Partial-success**: the 201 body reports each invitee as ``invited``/``skipped``/``failed`` (see ``SquadBatchInviteResponse``); per-invitee problems (self, already a member/invited, not found, is a squad, duplicated) do not fail the call. Only the structural checks below hard-fail. Caller-identity (ACTOR_MISMATCH) is enforced at the API Gateway, not here. Errors: 403: INSUFFICIENT_ROLE, NOT_A_SQUAD_MEMBER 404: SQUAD_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: SQUAD_CLOSED
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
InviteCreateRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 201 | SquadBatchInviteResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/invitations/{invitee_account_id}Revoke a pending Squad invitation
Revoke a pending invite (RFC-018 invite flow). OWNER-only; projection-only state flip, no tx. Caller-identity is enforced at the API Gateway. Errors: 403: INSUFFICIENT_ROLE, NOT_A_SQUAD_MEMBER 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND, INVITE_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: SQUAD_CLOSED
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| invitee_account_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
RevokeInviteRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | SquadInviteActionResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/invitations/acceptAccept a Squad invitation
Accept a pending invite (RFC-018 invite flow). The invitee enters the on-chain roster as a SPENDER via ``build_change_membership_tx``, custodially authored by a current OWNER (ChangeMembership is OWNER-gated). Caller-identity is enforced at the API Gateway. Errors: 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND, INVITE_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: SQUAD_CLOSED, ALREADY_A_MEMBER, NO_CURRENT_OWNER 503: HYDRA_UNAVAILABLE
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
InviteAcceptRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 201 | SquadInviteAcceptResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/invitations/declineDecline a Squad invitation
Decline a pending invite (RFC-018 invite flow). Projection-only state flip; no tx. Intentionally NOT OPEN-gated, so an invitee can tidy a stale invite. Errors: 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND, INVITE_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
InviteDeclineRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | SquadInviteActionResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/members/{member_account_id}Remove a member from a Squad
Remove a member (RFC-018 §5.1, SQ-10). Consumes the Config UTxO and recreates it with the member dropped from the ``members`` map (validator enforces "≥1 OWNER remains"). The leaver's **open accounting debts are redistributed** proportionally across the entry's remaining members first (no write-offs; settled members inherit a top-up) — see ``debt_resolution`` on the response. Pooled funds still block (``MEMBER_HAS_OUTSTANDING_BALANCE``); being **owed** money on an open share still blocks (``MEMBER_HAS_OUTSTANDING_ACCOUNTING`` — creditor side only). Caller-identity (ACTOR_MISMATCH) is enforced at the API Gateway, not here. Errors: 403: INSUFFICIENT_ROLE, NOT_A_SQUAD_MEMBER 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND, MEMBER_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: SQUAD_CLOSED, LAST_OWNER_CANNOT_BE_REMOVED, MEMBER_HAS_OUTSTANDING_BALANCE, MEMBER_HAS_OUTSTANDING_ACCOUNTING 503: HYDRA_UNAVAILABLE
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| member_account_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
RemoveMemberRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | SquadMemberRemoveResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/members/{member_account_id}/quotaChange a member's quota (cota) count
Change how many people a member represents (RFC-018 quotas). A member may edit their own quota; an OWNER may edit anyone's. Re-divides every still-open EQUAL expense at the new quota. **Locked once any entry is settled/voided.** Errors: 400: INVALID_QUOTA 403: INSUFFICIENT_ROLE, NOT_A_SQUAD_MEMBER 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND, MEMBER_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED, QUOTA_CHANGE_LOCKED 422: SQUAD_CLOSED 503: HYDRA_UNAVAILABLE
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| member_account_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
UpdateMemberQuotaRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | SquadMemberQuotaResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/members/{member_account_id}/rolePromote/demote a member between OWNER and SPENDER
Change a member's role (RFC-018). OWNER-only, and an owner may only change **other** members' roles (never their own), so self-promotion is impossible. The role lives in the on-chain Config datum, so this rewrites it via ``ChangeMembership`` (no new redeemer); a request matching the member's current role is a no-op (no tx, ``changed: false``). Caller-identity is enforced at the API Gateway. Errors: 400: INVALID_ROLE 403: INSUFFICIENT_ROLE, NOT_A_SQUAD_MEMBER 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND, MEMBER_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: SQUAD_CLOSED, CANNOT_CHANGE_OWN_ROLE, LAST_OWNER_CANNOT_BE_DEMOTED 503: HYDRA_UNAVAILABLE
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| member_account_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
ChangeMemberRoleRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | SquadMemberRoleChangeResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/recurrenceOwner: enable / edit / disable a squad's monthly cycles
Enable, edit, or disable monthly cycles for a squad (B-SQ-04). OWNER-only, **off-chain** (a projection write — no Cardano tx). ``billing_day`` (1–28) is the dia de fechamento; ``null`` disables. Billing fires at 00:00 in ``timezone``. Errors: 400: INVALID_BILLING_DAY, INVALID_TIMEZONE 403: INSUFFICIENT_ROLE, NOT_A_SQUAD_MEMBER 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: SQUAD_CLOSED, SQUAD_FROZEN
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
RecurrenceRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | RecurrenceResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/recurring-expensesOwner: create a recurring expense (conta / bill template)
Create a conta that auto-posts each cycle (B-SQ-04). OWNER-only, off-chain. A fixed conta posts at ``amount``; a ``variable`` one posts a placeholder awaiting the payer's ``/confirm``. ``split`` is the same sealed split as a contribution. Errors: 400: INVALID_AMOUNT, INVALID_DESCRIPTION, INVALID_SPLIT, AMOUNTS_DO_NOT_SUM, UNKNOWN_MEMBER_IN_SPLIT, UNSUPPORTED_CURRENCY 403: INSUFFICIENT_ROLE, NOT_A_SQUAD_MEMBER 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: SQUAD_CLOSED, SQUAD_FROZEN
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
RecurringExpenseRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 201 | RecurringExpenseResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/recurring-expenses/{rex_id}Owner: delete a recurring expense (conta)
Delete a conta (B-SQ-04). OWNER-only, off-chain. Stops future postings; already-posted expenses are ordinary entries and stay. Errors: 403: INSUFFICIENT_ROLE, NOT_A_SQUAD_MEMBER 404: SQUAD_NOT_FOUND, REX_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: SQUAD_CLOSED
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| rex_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
RecurringExpenseDeleteRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | RecurringExpenseDeleteResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/recurring-expenses/{rex_id}Owner: edit a recurring expense (conta)
Edit a conta (B-SQ-04). OWNER-only, off-chain. Partial update; future cycle posts use the new values, already-posted expenses are unaffected. Errors mirror create, plus 404 REX_NOT_FOUND.
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| rex_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
RecurringExpensePatchRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | RecurringExpenseResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/recurring-expenses/{rex_id}/confirmPayer: confirm a variable conta's real amount for the current period
Confirm a variable conta's real amount (B-SQ-04). Payer-only. Turns the current period's PENDING_CONFIRMATION placeholder into a live on-chain ACCOUNTING expense (minting per-debtor shares). Errors: 400: INVALID_AMOUNT, UNSUPPORTED_CURRENCY 403: NOT_THE_PAYER 404: SQUAD_NOT_FOUND, REX_NOT_FOUND, PENDING_CONFIRMATION_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: SQUAD_CLOSED, SQUAD_FROZEN, ALREADY_CONFIRMED 503: HYDRA_UNAVAILABLE
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| rex_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
ConfirmVariableRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 201 | — | Resposta bem-sucedidaO contrato não declara um modelo para esta resposta, então a forma dela não está documentada aqui. Um roteiro de demonstração mostra a forma que ela realmente devolve. |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/rulesOwner: remove a squad's spend-approval policy
Remove a squad's spend-approval policy (B-SQ-06). OWNER-only, off-chain. Allowed on OPEN and CLOSED alike (cleanup). Pending spend-requests are unaffected — each carries the policy snapshot it was created under. Idempotent: clearing an absent policy returns ``rules: null``. Errors: 403: INSUFFICIENT_ROLE, NOT_A_SQUAD_MEMBER 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
SquadRulesDeleteRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | SquadRulesDeleteResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/rulesOwner: set or edit a squad's spend-approval policy (Regras)
Set or edit a squad's spend-approval policy (B-SQ-06). OWNER-only, **off-chain** (a projection write — no Cardano tx). A spend *above* ``threshold_amount`` then requires ``approvals_required`` distinct approvers (from ``approvers`` = OWNERS | ALL_MEMBERS) before it executes. Errors: 400: INVALID_THRESHOLD, INVALID_APPROVALS_REQUIRED, INVALID_APPROVERS 403: INSUFFICIENT_ROLE, NOT_A_SQUAD_MEMBER 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: SQUAD_CLOSED, SQUAD_FROZEN
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
SquadRulesRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | SquadRulesResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/settleSettle the caller's own shares (per-debtor self-settle)
Per-debtor self-settle (RFC-018 §5.3, SQ-13). The caller discharges the shares where THEY are the debtor: one tx pays each creditor ``share_cents`` QBRL and burns the share vQBRL via ``SettleShare``. The settle is funded from the caller's **squad deposits first** — those are drained back to their personal custody in a prior ``Spend`` tx (``squad_funds_withdrawn_cents`` / ``withdrawal_tx_id`` report it), any excess staying liquid in custody — then any shortfall comes from their existing custody. ``entry_seq`` optionally narrows to one expense. A caller who owes nothing but has a squad deposit gets **201** with ``settled_shares: 0`` and the withdrawal fields (the deposit is returned to their personal custody; ``tx_id == withdrawal_tx_id``) — ``ACCOUNTING_NOT_FOUND`` is now returned only when the caller owed nothing AND had no deposit. Caller-identity is enforced at the API Gateway. Errors: 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND, ACCOUNTING_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: SQUAD_CLOSED, INSUFFICIENT_BALANCE 503: HYDRA_UNAVAILABLE
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
SettleRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 201 | SquadSettleResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/simplify-debtsSimplify the squad's debts (OWNER; minimal multi-party netting)
Collapse the open accounting-share graph into the minimal set of net debts (RFC-018 netting). An OWNER triggers it; the handler computes the Splitwise-style minimum-cash-flow plan and rewrites the chain to match — reissuing the minimal net shares on fresh entries, then voiding all originals (which are kept as frozen history). Total open debt is conserved (``vqbrl_minted == vqbrl_burned``); only the number of debts shrinks. ``no_op: true`` when the graph is already minimal (no on-chain work). The op is a resumable multi-tx sequence — a retry with the same Idempotency-Key continues a partial run rather than restarting. Errors: 403: NOT_A_SQUAD_MEMBER, INSUFFICIENT_ROLE 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED, SIMPLIFY_IN_PROGRESS 422: SQUAD_CLOSED, CREDITOR_UNRESOLVABLE, SQUAD_TOO_LARGE_TO_SIMPLIFY 503: HYDRA_UNAVAILABLE
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
SquadSimplifyRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 201 | SquadSimplifyResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/spend-requests/{spr_id}/approveApprove a pending squad spend-request (the Nth approval executes it)
Record one approval on a PENDING_APPROVAL spend-request (B-SQ-06).
An eligible approver (distinct from the requester and prior approvers) approves. Before the Nth approval → **200** with the updated approvals list. On the Nth → the spend executes atomically and this returns **201** with the executed spend result (tx_id, …). Insufficient pool at execution → the request flips FAILED and 422 INSUFFICIENT_BALANCE is returned (no partial movement). Errors: 403: NOT_AN_APPROVER, NOT_A_SQUAD_MEMBER, CANNOT_APPROVE_OWN_REQUEST, INSUFFICIENT_ROLE 404: SPEND_REQUEST_NOT_FOUND, SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND 409: ALREADY_APPROVED, IDEMPOTENCY_KEY_REUSED 422: APPROVAL_NOT_PENDING, INSUFFICIENT_BALANCE, SQUAD_FROZEN, SQUAD_CLOSED 503: HYDRA_UNAVAILABLE
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| spr_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
SpendRequestApproveRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | SpendRequestPendingResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/spend-requests/{spr_id}/rejectReject (kill) a pending squad spend-request
A single eligible approver rejects a PENDING_APPROVAL spend-request (B-SQ-06). Sticky: a rejected request is terminal (a later approve → 422 APPROVAL_NOT_PENDING). Errors: 403: NOT_AN_APPROVER, NOT_A_SQUAD_MEMBER, INSUFFICIENT_ROLE 404: SPEND_REQUEST_NOT_FOUND, SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: APPROVAL_NOT_PENDING, SQUAD_FROZEN, SQUAD_CLOSED
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| spr_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
SpendRequestRejectRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | SpendRequestRejectResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/spendsSpend from a Squad to an external recipient
Spend QBRL out of a squad (RFC-018 §5.1, SQ-12, B-SQ-07).
Exactly one destination. **Internal** (``recipient_account_id``): a SPENDER/OWNER moves QBRL to that account's BancoBRL custody; the SquadValidator ``Spend`` redeemer enforces role/witness/value-conservation on-chain; returns **201** ``state:"OPEN"``. **External Pix** (``pix_destination``, B-SQ-07): the pool's QBRL bridges to the GL clearing account and the deferred Pix rail sends it out; the DICT key is resolved pre-debit (recipient name in the ``payout`` block), and it returns **201** ``state:"PROCESSING"`` with ``payout:{ rail, end_to_end_id, recipient_name, status }`` — the terminal SPEND_SETTLED / SPEND_FAILED (pool auto-refunded) surface in the feed. Caller-identity (ACTOR_MISMATCH) is enforced at the API Gateway, not here.
B-SQ-06 (Regras): if the squad has a ``spend_rules`` policy and the amount is *above* the threshold, no money moves — the spend (internal or Pix) is parked as a PENDING_APPROVAL request and this returns **202** with ``{spend_request_id, state:"PENDING_APPROVAL", …}``. Otherwise it executes and returns **201**. Errors: 400: UNSUPPORTED_CURRENCY, INVALID_AMOUNT, CANNOT_SPEND_TO_SELF, MISSING_DESTINATION, AMBIGUOUS_DESTINATION, INVALID_PIX_KEY 403: NOT_A_SQUAD_MEMBER, INSUFFICIENT_ROLE 404: SQUAD_NOT_FOUND, RECIPIENT_NOT_FOUND, ACCOUNT_NOT_FOUND, PIX_KEY_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: INSUFFICIENT_BALANCE, SQUAD_CLOSED, SQUAD_FROZEN, PIX_RAIL_UNAVAILABLE 503: HYDRA_UNAVAILABLE
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
SpendRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 201 | SquadSpendResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
/v1/squads/{sqd_id}/unfreezeOwner: unfreeze a squad (resume normal activity)
Unfreeze a squad (RFC-018), re-allowing deposits/spends/accounting and roster changes. OWNER-only. **No Cardano tx.** Does NOT clear the sticky ``simplified`` marker. Idempotent: unfreezing an already-open squad is a 200 no-op with ``changed=false``. Errors: 403: NOT_A_SQUAD_MEMBER, INSUFFICIENT_ROLE 404: SQUAD_NOT_FOUND, ACCOUNT_NOT_FOUND 409: IDEMPOTENCY_KEY_REUSED 422: SQUAD_CLOSED
Parâmetros
| Nome | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | pathobrigatório |
| Idempotency-Key | string | headerobrigatório |
Corpo da requisição
SquadFreezeRequest — obrigatório. Os campos estão listados em Esquemas, abaixo.
Respostas
| Status | Corpo | Detalhe |
|---|---|---|
| 200 | SquadFreezeResponse | Resposta bem-sucedida |
| 422 | HTTPValidationError | Erro de validação |
Esquemas
Os modelos que as operações acima aceitam e devolvem. Campos opcionais estão marcados como tal; um campo tipado como outro modelo está documentado sob o nome dele.
ChangeMemberRoleRequest
``PATCH /v1/squads/{sqd_id}/members/{member_account_id}/role`` (RFC-018). ``actor_account_id`` must be an OWNER; ``role`` is the member's new role. An owner may only change *other* members' roles (never their own), so self-promotion is impossible. ``role`` is upper-cased before validation.
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
| role | string | obrigatório |
CloseRequest
``POST /v1/squads/{sqd_id}/close`` (SQ-14). ``actor_account_id`` is the OWNER closing the squad (must be a current OWNER member). The close is irreversible — there is no ``/reopen``. ``reason`` is free-form audit text and does not affect the on-chain tx.
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
| reason | string, opcional |
ConfirmVariableRequest
``POST /v1/squads/{sqd_id}/recurring-expenses/{rex_id}/confirm`` — the payer sets a variable conta's real amount for the current period, turning its ``PENDING_CONFIRMATION`` placeholder into a live on-chain ACCOUNTING expense.
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
| amount | SquadAmount | obrigatório |
ConsentRequest
``PUT /v1/squads/{sqd_id}/auto-collect/consent`` — a member grants (or refreshes) a standing, capped authorization to auto-settle their share of one conta each cycle. ``caller_account_id`` is the consenting member (own-share-only — a member can only consent for themselves). ``max_amount`` caps how much may be auto-collected per cycle; a posted share above the cap SUSPENDS the consent rather than over-collecting.
| Campo | Tipo | Detalhe |
|---|---|---|
| caller_account_id | string | obrigatório |
| max_amount | SquadAmount | obrigatório |
| rex_id | string | obrigatório |
ConsentResponse
200 body for ``PUT …/auto-collect/consent``. ``state`` is ACTIVE after a grant; ``consent_state`` is ``null`` (cleared) — a re-grant re-activates a suspended consent.
| Campo | Tipo | Detalhe |
|---|---|---|
| consent_id | string | obrigatório |
| consent_state | string, opcional | |
| granted_at | string | obrigatório |
| max_amount | SquadAmount | obrigatório |
| rex_id | string | obrigatório |
| state | string | Padrão "ACTIVE" |
ConsentRevokeRequest
``DELETE /v1/squads/{sqd_id}/auto-collect/consent/{consent_id}`` body — the caller may only revoke their own consent (own-share-only).
| Campo | Tipo | Detalhe |
|---|---|---|
| caller_account_id | string | obrigatório |
ConsentRevokeResponse
200 body for a revoke — the consent row is hard-deleted; future cycles no longer auto-collect this member's share.
| Campo | Tipo | Detalhe |
|---|---|---|
| consent_id | string | obrigatório |
| revoked | boolean | Padrão true |
| sqd_id | string | obrigatório |
ContributionRequest
``POST /v1/squads/{sqd_id}/contributions`` — ``kind`` selects FUNDED (a QBRL deposit) or ACCOUNTING (a non-monetary split entry, vQBRL-minted). ``kind`` is a plain ``str`` (not a ``Literal``) on purpose: the route validates it explicitly so an unknown kind returns a structured ``400 INVALID_KIND`` rather than FastAPI's generic 422 body.
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
| amount | SquadAmount | obrigatório |
| description | string, opcional | |
| kind | string | obrigatório |
| members_snapshot | array de string, opcional | |
| source_tx_ids | array de string, opcional | |
| split | SplitSpec, opcional |
EntrySplitOverrideRequest
``PATCH /v1/squads/{sqd_id}/entries/{entry_seq}/split`` — owner escape hatch. The owner manually re-divides one expense's *still-open* shares using an explicit ``split`` (EQUAL / SHARES / AMOUNTS over the open debtors). Works even on a partially-settled entry (only the open portion is re-issued); the entry is then flagged so automatic re-splits leave it alone (RFC-018).
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
| split | SplitSpec | obrigatório |
HTTPValidationError
| Campo | Tipo | Detalhe |
|---|---|---|
| detail | array de ValidationError |
InviteAcceptRequest
``POST /v1/squads/{sqd_id}/invitations/accept`` — the invitee accepts. ``caller_account_id`` is the invitee (matching the ``/settle`` convention); the squad + caller identify the pending invite. ``quota`` (cotas, RFC-018) is how many people the invitee represents — default 1; a member bringing a +1 sets 2, making EQUAL-split expenses weight them accordingly. Accepting folds the invitee (at this quota) into every still-open prior expense (see ``retroactive`` in the response).
| Campo | Tipo | Detalhe |
|---|---|---|
| caller_account_id | string | obrigatório |
| quota | integer | Padrão 1 |
InviteCreateRequest
``POST /v1/squads/{sqd_id}/invitations`` — an OWNER invites one or more accounts. Replaces the old direct add-member: nobody joins a squad without their own accept. The accepted role is always ``SPENDER`` (no role field), so inviting a prospective OWNER is intentionally out of scope. ``invitee_account_ids`` is a list (1–50) so a client can invite several people in a single tap. The endpoint is **partial-success**: each invitee is reported as ``invited``/``skipped``/``failed`` (see :class:`SquadInviteResultEntry`); only structural errors (squad missing/closed, actor not an OWNER) fail the whole call.
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
| invitee_account_ids | array de string | obrigatório |
InviteDeclineRequest
``POST /v1/squads/{sqd_id}/invitations/decline`` — the invitee declines.
| Campo | Tipo | Detalhe |
|---|---|---|
| caller_account_id | string | obrigatório |
PayoutBlock
External-rail payout status on a Pix squad spend (B-SQ-07). Present only on Pix spends. ``end_to_end_id`` is assigned by the sponsor at dispatch time, so it is ``null`` in the 201 (``PROCESSING``) response and filled once the rail accepts.
| Campo | Tipo | Detalhe |
|---|---|---|
| end_to_end_id | string, opcional | |
| rail | string | Padrão "PIX" |
| recipient_name | string, opcional | |
| status | "PROCESSING" | "SETTLED" | "FAILED" | Padrão "PROCESSING" |
PixDestination
An external Pix payout target for a squad spend (B-SQ-07). Exactly one of ``recipient_account_id`` / ``pix_destination`` is supplied on :class:`SpendRequest`. ``key`` is the raw Pix key as typed; Core normalizes it (DICT lookup + identity-key normalization) — ``key_type`` is the DICT category.
| Campo | Tipo | Detalhe |
|---|---|---|
| key | string | obrigatório |
| key_type | "CPF" | "PHONE" | "EMAIL" | "EVP" | obrigatório |
RecurrenceBlock
The active recurrence config echoed on writes/reads (``null`` when disabled).
| Campo | Tipo | Detalhe |
|---|---|---|
| billing_day | integer | obrigatório |
| current_period | string | obrigatório |
| timezone | string | obrigatório |
RecurrenceRequest
``PUT /v1/squads/{sqd_id}/recurrence`` — OWNER enables/edits/disables monthly cycles. ``billing_day`` is the dia de fechamento (1–28; ``null`` disables recurrence); validated in the handler so a bad value surfaces as a discrete ``400 INVALID_BILLING_DAY`` rather than a generic Pydantic 422. ``timezone`` is the IANA zone the billing day is evaluated in (billing fires at 00:00 local).
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
| billing_day | integer, opcional | |
| timezone | string | Padrão "America/Sao_Paulo" |
RecurrenceResponse
200 body for ``PUT …/recurrence``. ``recurrence`` is ``null`` when the call disabled cycles (``billing_day: null``).
| Campo | Tipo | Detalhe |
|---|---|---|
| recurrence | RecurrenceBlock, opcional | |
| sqd_id | string | obrigatório |
| updated_at | string | obrigatório |
RecurringExpenseDeleteRequest
``DELETE /v1/squads/{sqd_id}/recurring-expenses/{rex_id}`` body — OWNER-only.
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
RecurringExpenseDeleteResponse
200 body for ``DELETE …/recurring-expenses/{rex_id}`` — future postings stop; already-posted expenses are unaffected.
| Campo | Tipo | Detalhe |
|---|---|---|
| deleted | boolean | Padrão true |
| rex_id | string | obrigatório |
| sqd_id | string | obrigatório |
RecurringExpensePatchRequest
``PATCH /v1/squads/{sqd_id}/recurring-expenses/{rex_id}`` — edit a conta. Partial update: only the fields present change (the route dumps with ``exclude_unset=True``). Future cycle posts use the new values; already-posted expenses are ordinary entries and stay.
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
| amount | SquadAmount, opcional | |
| description | string, opcional | |
| payer_account_id | string, opcional | |
| split | SplitSpec, opcional | |
| variable | boolean, opcional |
RecurringExpenseRequest
``POST /v1/squads/{sqd_id}/recurring-expenses`` — create a conta (bill template). ``amount`` is the fixed charge (centavos) for ``variable=False``, or an estimate for ``variable=True`` (the real value is set each cycle via ``/confirm``). ``payer_account_id`` is who pays the provider (the expense's creditor when it posts). ``split`` is the same sealed split as a contribution (EQUAL / SHARES / AMOUNTS).
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
| amount | SquadAmount | obrigatório |
| description | string | obrigatório |
| payer_account_id | string | obrigatório |
| split | SplitSpec | obrigatório |
| variable | boolean | Padrão false |
RecurringExpenseResponse
201 body for create (and 200 for PATCH) of a recurring-expense.
| Campo | Tipo | Detalhe |
|---|---|---|
| amount | SquadAmount | obrigatório |
| created_at | string | obrigatório |
| description | string | obrigatório |
| payer_account_id | string | obrigatório |
| rex_id | string | obrigatório |
| split | SplitSpec | obrigatório |
| sqd_id | string | obrigatório |
| state | string | Padrão "ACTIVE" |
| updated_at | string | obrigatório |
| variable | boolean | obrigatório |
RemoveMemberRequest
``DELETE /v1/squads/{sqd_id}/members/{member_account_id}`` (SQ-10).
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
RevokeInviteRequest
``DELETE /v1/squads/{sqd_id}/invitations/{invitee_account_id}`` — OWNER revokes.
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
SettleRequest
``POST /v1/squads/{sqd_id}/settle`` — per-debtor **self**-settle (SQ-13, amending SQ-17). The caller discharges the shares where THEY are the debtor, paying each creditor from their own BancoBRL custody; the matching share vQBRL burns. Witness set collapses to the caller — one API call can only ever move the caller's own funds (the SquadValidator's ``SettleShare`` enforces it). ``entry_seq`` optionally narrows settlement to a single expense; omitted means every OPEN share where the caller is the debtor.
| Campo | Tipo | Detalhe |
|---|---|---|
| caller_account_id | string | obrigatório |
| entry_seq | integer, opcional |
SpendApprovalPolicy
The spend-approval policy body. ``threshold_amount`` gates spends *above* it; ``approvals_required`` is the number of distinct approvers (the requester does not count); ``approvers`` selects the eligible set. Values are validated in the handler so a bad value surfaces as a discrete ``400 INVALID_THRESHOLD`` / ``INVALID_APPROVALS_REQUIRED`` / ``INVALID_APPROVERS`` rather than a generic Pydantic 422.
| Campo | Tipo | Detalhe |
|---|---|---|
| approvals_required | integer | obrigatório |
| approvers | string | Padrão "OWNERS" |
| threshold_amount | SquadAmount | obrigatório |
SpendRequest
``POST /v1/squads/{sqd_id}/spends`` — pay from squad funds (SQ-12, B-SQ-07). ``actor_account_id`` is the OWNER/SPENDER moving the funds. Exactly one destination: ``recipient_account_id`` (an existing account that receives QBRL at BancoBRL custody, must not be the squad itself) **or** ``pix_destination`` (an external Pix key — the pool's QBRL bridges to the deferred Pix rail). ``metadata`` is free-form and copied onto the spend obligation. The amount is centavos (1 QBRL = 1 centavo).
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
| amount | SquadAmount | obrigatório |
| metadata | object, opcional | |
| pix_destination | PixDestination, opcional | |
| recipient_account_id | string, opcional |
SpendRequestApprovalEntry
| Campo | Tipo | Detalhe |
|---|---|---|
| account_id | string | obrigatório |
| approved_at | string | obrigatório |
SpendRequestApproveRequest
Body for ``POST …/spend-requests/{spr_id}/approve``. The caller identity is injected by the BFF/gateway from the authenticated principal.
| Campo | Tipo | Detalhe |
|---|---|---|
| caller_account_id | string | obrigatório |
SpendRequestPendingResponse
The PENDING_APPROVAL body: 202 on a gated spend-create, 200 on a recorded (non-final) approval. The executed (final) approval instead returns a ``SquadSpendResponse`` (201).
| Campo | Tipo | Detalhe |
|---|---|---|
| amount | SquadAmount | obrigatório |
| approvals | array de SpendRequestApprovalEntry | |
| approvals_required | integer | obrigatório |
| expires_at | string | obrigatório |
| recipient_account_id | string | obrigatório |
| requested_by | string | obrigatório |
| spend_request_id | string | obrigatório |
| sqd_id | string | obrigatório |
| state | string | obrigatório |
SpendRequestRejectRequest
Body for ``POST …/spend-requests/{spr_id}/reject`` (optional human-readable reason).
| Campo | Tipo | Detalhe |
|---|---|---|
| caller_account_id | string | obrigatório |
| reason | string, opcional |
SpendRequestRejectResponse
200 body for ``POST …/spend-requests/{spr_id}/reject``.
| Campo | Tipo | Detalhe |
|---|---|---|
| amount | SquadAmount | obrigatório |
| approvals | array de SpendRequestApprovalEntry | |
| approvals_required | integer | obrigatório |
| reason | string, opcional | |
| recipient_account_id | string | obrigatório |
| rejected_by | string | obrigatório |
| requested_by | string | obrigatório |
| spend_request_id | string | obrigatório |
| sqd_id | string | obrigatório |
| state | string | obrigatório |
SplitSpec
Allocation for an ACCOUNTING contribution. ``entries`` maps member account id -> relative weight (SHARES) or exact cents (AMOUNTS); omitted/ignored for EQUAL.
| Campo | Tipo | Detalhe |
|---|---|---|
| entries | object, opcional | |
| kind | "EQUAL" | "SHARES" | "AMOUNTS" | obrigatório |
SquadAmount
| Campo | Tipo | Detalhe |
|---|---|---|
| currency | string | obrigatório |
| value | integer | obrigatórioAmount in centavos (1 QBRL = 1 centavo). |
SquadBatchInviteResponse
201 body for ``POST /v1/squads/{sqd_id}/invitations`` (batch, partial-success). No ``tx_id``: an invite is a projection-only consent record, not a Cardano tx. Each invitee's fate is in ``results``; ``summary`` is the per-status tally. A 201 here means the request was processed — inspect ``summary``/``results`` for what changed.
| Campo | Tipo | Detalhe |
|---|---|---|
| inviter_account_id | string | obrigatório |
| results | array de SquadInviteResultEntry | obrigatório |
| sqd_id | string | obrigatório |
| summary | SquadInviteSummary | obrigatório |
SquadCloseFinalBalance
The squad's residual pooled balance at close — always zero (the close precondition requires every Balance UTxO drained).
| Campo | Tipo | Detalhe |
|---|---|---|
| currency | string | Padrão "BRL" |
| value | integer | Padrão 0 |
SquadCloseResponse
201 body for ``POST /v1/squads/{sqd_id}/close`` (RFC-018 §5.1, SQ-14). The terminal lifecycle event: the tx consumes the OPEN Config UTxO and recreates it with ``state="CLOSED"``. After close every write referencing the Config fails the validator's ``configIsOpen`` check (SI-7); reads continue indefinitely. ``closed_at`` is the server timestamp; ``final_member_count`` is the preserved roster size; ``final_balance`` is always zero by precondition.
| Campo | Tipo | Detalhe |
|---|---|---|
| closed_at | string | obrigatório |
| closed_by | string | obrigatório |
| final_balance | SquadCloseFinalBalance | obrigatório |
| final_member_count | integer | obrigatório |
| sqd_id | string | obrigatório |
| state | string | Padrão "CLOSED" |
| tx_id | string | obrigatório |
SquadCreateRequest
``POST /v1/squads`` — the creator becomes the first OWNER member. ``name`` is the only required display field; everything else lives under the optional ``metadata`` object (description, emoji, image_url, location). ``invitee_account_ids`` is **optional**: omit it to create a bare squad, or pass a list to create + invite in one atomic call. Every invitee is validated *before* the irreversible create tx, so a single bad invitee fails the whole request with nothing created on-chain. Invitees enter the on-chain roster only when they accept.
| Campo | Tipo | Detalhe |
|---|---|---|
| creator_account_id | string | obrigatório |
| invitee_account_ids | array de string, opcional | |
| metadata | SquadMetadata, opcional | |
| name | string | obrigatório |
SquadDebtResolution
What member removal did to the leaver's open accounting debts. Every entry the leaver owed on is redistributed proportionally across that entry's remaining members (no write-offs; "creditor absorbs" is just the degenerate last-member case). ``entries_skipped`` carries any entry a transient error left untouched (``RESPLIT_FAILED``) — the member is still removed, retry re-runs them.
| Campo | Tipo | Detalhe |
|---|---|---|
| entries_redistributed | array de SquadEntryRedistribution | |
| entries_skipped | array de SquadResplitSkip | |
| reissue_tx_ids | array de string | |
| void_tx_ids | array de string | |
| vqbrl_burned | integer | Padrão 0 |
| vqbrl_minted | integer | Padrão 0 |
SquadEntrySplitOverrideResponse
200 body for the per-entry split override (RFC-018).
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
| entry_seq | integer | obrigatório |
| open_amount_cents | integer | obrigatório |
| shares | array de SquadShareEntry | |
| sqd_id | string | obrigatório |
| tx_id | string, opcional |
SquadFreezeRequest
``POST /v1/squads/{sqd_id}/freeze`` and ``.../unfreeze`` — an OWNER toggles the squad's reversible wind-down state. Off-chain only (no Cardano tx): while frozen, deposits/spends/accounting and all roster changes are rejected (422 SQUAD_FROZEN); settlement, close, decline-invite, and metadata edits still work. Freezing is a prerequisite for ``simplify-debts``.
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
SquadFreezeResponse
200 body for freeze/unfreeze. ``frozen`` is the resulting state; ``changed`` is false when the squad was already in that state (idempotent no-op). ``simplified`` is the sticky historical marker (true once the squad has ever been simplified) and is surfaced here for convenience — unfreeze never clears it.
| Campo | Tipo | Detalhe |
|---|---|---|
| changed | boolean | obrigatório |
| frozen | boolean | obrigatório |
| simplified | boolean | Padrão false |
| sqd_id | string | obrigatório |
| updated_at | string | obrigatório |
SquadGoalBlock
The server-computed goal state echoed on writes and reads (the ``goal`` block). ``funded_cents`` is the live pool balance (FUNDED in − spends − reclaims); ``progress`` is ``funded_cents / target_amount.value`` clamped to ``[0, 1]``; ``achieved_at`` is sticky — set the first moment the pool reaches the target and kept even if the balance later dips.
| Campo | Tipo | Detalhe |
|---|---|---|
| achieved_at | string, opcional | |
| funded_cents | integer | obrigatório |
| progress | number | obrigatório |
| target_amount | SquadAmount | obrigatório |
| target_date | string, opcional |
SquadGoalDeleteRequest
``DELETE /v1/squads/{sqd_id}/goal`` — an OWNER removes the goal. Only the actor is needed (there is no goal body to clear beyond the row attributes).
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
SquadGoalDeleteResponse
200 body for ``DELETE /v1/squads/{sqd_id}/goal`` — ``goal`` is always ``null``.
| Campo | Tipo | Detalhe |
|---|---|---|
| goal | SquadGoalBlock, opcional | |
| sqd_id | string | obrigatório |
SquadGoalRequest
``PUT /v1/squads/{sqd_id}/goal`` — an OWNER sets or edits the savings goal. Off-chain projection only (no Cardano tx) — the goal constrains nothing, it only measures. ``target_amount`` is the finish line (BRL, centavos); ``target_date`` is an optional ``YYYY-MM-DD`` deadline. Both are validated in the handler so a bad value surfaces as a discrete ``400 INVALID_GOAL_AMOUNT`` / ``INVALID_GOAL_DATE`` rather than a generic Pydantic 422.
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
| target_amount | SquadAmount | obrigatório |
| target_date | string, opcional |
SquadGoalResponse
200 body for ``PUT /v1/squads/{sqd_id}/goal``.
| Campo | Tipo | Detalhe |
|---|---|---|
| goal | SquadGoalBlock | obrigatório |
| sqd_id | string | obrigatório |
| updated_at | string | obrigatório |
SquadInviteAcceptResponse
201 body for ``POST /v1/squads/{sqd_id}/invitations/accept``. The accept runs the on-chain ChangeMembership, so it carries ``tx_id`` and the new roster. ``acted_by_owner_account_id`` is the current OWNER that custodially authored the add (the invitee is not an OWNER, so cannot sign it themselves). ``quota`` is the accepted member's cota count; ``retroactive`` reports how the open prior expenses were re-split to include them (RFC-018).
| Campo | Tipo | Detalhe |
|---|---|---|
| acted_by_owner_account_id | string | obrigatório |
| config_utxo_ref | string | obrigatório |
| invitee_account_id | string | obrigatório |
| invitee_pkh | string | obrigatório |
| joined_at | string | obrigatório |
| member_count | integer | obrigatório |
| members | array de SquadMemberRosterEntry | obrigatório |
| quota | integer | Padrão 1 |
| retroactive | SquadResplitReport | |
| role | string | obrigatório |
| sqd_id | string | obrigatório |
| tx_id | string | obrigatório |
SquadInviteActionResponse
200 body for revoke / decline — the invite's new terminal ``state``.
| Campo | Tipo | Detalhe |
|---|---|---|
| invitee_account_id | string | obrigatório |
| sqd_id | string | obrigatório |
| state | string | obrigatório |
SquadInviteResultEntry
One invitee's outcome in a batch-invite report. ``status`` is ``invited`` (a PENDING row was written), ``skipped`` (a benign no-op: self / already a member / already pending / duplicated in the request), or ``failed`` (the invitee account does not exist or is itself a SQUAD account). ``reason`` is the machine code (``OK``, ``CANNOT_INVITE_SELF``, ``ALREADY_A_MEMBER``, ``INVITE_ALREADY_PENDING``, ``DUPLICATE_IN_REQUEST``, ``ACCOUNT_NOT_FOUND``, ``SQUAD_AS_SQUAD_MEMBER_FORBIDDEN``). ``invitee_pkh``/``created_at`` are present only when the invitee resolved / was written.
| Campo | Tipo | Detalhe |
|---|---|---|
| created_at | string, opcional | |
| invitee_account_id | string | obrigatório |
| invitee_pkh | string, opcional | |
| reason | string | obrigatório |
| state | string, opcional | |
| status | string | obrigatório |
SquadInviteSummary
| Campo | Tipo | Detalhe |
|---|---|---|
| failed | integer | obrigatório |
| invited | integer | obrigatório |
| skipped | integer | obrigatório |
| total | integer | obrigatório |
SquadMemberQuotaResponse
200 body for the quota edit. ``retroactive`` reports the re-split of open EQUAL entries under the new quota.
| Campo | Tipo | Detalhe |
|---|---|---|
| member_account_id | string | obrigatório |
| member_pkh | string | obrigatório |
| quota | integer | obrigatório |
| retroactive | SquadResplitReport | |
| sqd_id | string | obrigatório |
SquadMemberRemoveResponse
200 body for ``DELETE /v1/squads/{sqd_id}/members/{member_account_id}``.
| Campo | Tipo | Detalhe |
|---|---|---|
| config_utxo_ref | string | obrigatório |
| debt_resolution | SquadDebtResolution | |
| member_count | integer | obrigatório |
| members | array de SquadMemberRosterEntry | obrigatório |
| removed_member_account_id | string | obrigatório |
| removed_member_pkh | string | obrigatório |
| sqd_id | string | obrigatório |
| tx_id | string | obrigatório |
SquadMemberRoleChangeResponse
200 body for ``PATCH /v1/squads/{sqd_id}/members/{member_account_id}/role``. ``changed`` is ``False`` (and ``tx_id`` ``None``) when the member already had the requested role — a no-op that ran no Cardano tx. Otherwise it carries the ChangeMembership ``tx_id`` and the post-change roster.
| Campo | Tipo | Detalhe |
|---|---|---|
| changed | boolean | obrigatório |
| config_utxo_ref | string, opcional | |
| member_account_id | string | obrigatório |
| member_count | integer | obrigatório |
| member_pkh | string | obrigatório |
| members | array de SquadMemberRosterEntry | obrigatório |
| role | string | obrigatório |
| sqd_id | string | obrigatório |
| tx_id | string, opcional |
SquadMemberRosterEntry
One entry of a member-mutation response roster. V1 stores members pkh-only (no pkh→account_id index; the join is the SQ-18 read layer's job — see ``shared/squad_view``), so the roster is keyed by ``member_pkh``. The account_id of the member touched by *this* request is echoed at the top level of the response instead.
| Campo | Tipo | Detalhe |
|---|---|---|
| member_pkh | string | obrigatório |
| role | string | obrigatório |
SquadMetadata
Optional, purely-cosmetic display metadata for a squad (off-chain only — never part of the on-chain Config datum). Every field is optional; on a PATCH an explicit ``null`` clears that field while an omitted field is left unchanged.
| Campo | Tipo | Detalhe |
|---|---|---|
| description | string, opcional | |
| emoji | string, opcional | |
| image_url | string, opcional | |
| location | SquadLocation, opcional | |
| template | string, opcional | |
| template_config | não declarado, opcional |
SquadResplitReport
What a retroactive re-split did across a squad's open EQUAL entries. ``entries_resplit`` are the entry_seqs re-issued under the new membership/quotas; ``entries_skipped`` are entries left untouched (already settled/voided, or a transient failure) — the owner can fix those via the per-entry split override.
| Campo | Tipo | Detalhe |
|---|---|---|
| entries_resplit | array de integer | |
| entries_skipped | array de SquadResplitSkip |
SquadRulesBlock
The ``rules`` block echoed on the write response and squad detail (``null`` when unset).
| Campo | Tipo | Detalhe |
|---|---|---|
| spend_approval | SpendApprovalPolicy | obrigatório |
SquadRulesDeleteRequest
``DELETE /v1/squads/{sqd_id}/rules`` — an OWNER removes the policy. Only the actor is needed.
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
SquadRulesDeleteResponse
200 body for ``DELETE /v1/squads/{sqd_id}/rules`` — ``rules`` is always ``null``.
| Campo | Tipo | Detalhe |
|---|---|---|
| rules | SquadRulesBlock, opcional | |
| sqd_id | string | obrigatório |
SquadRulesRequest
``PUT /v1/squads/{sqd_id}/rules`` — an OWNER sets/edits the spend-approval policy.
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
| spend_approval | SpendApprovalPolicy | obrigatório |
SquadRulesResponse
200 body for ``PUT /v1/squads/{sqd_id}/rules``.
| Campo | Tipo | Detalhe |
|---|---|---|
| rules | SquadRulesBlock | obrigatório |
| sqd_id | string | obrigatório |
| updated_at | string | obrigatório |
SquadSettleResponse
201 body for ``POST /v1/squads/{sqd_id}/settle`` (SQ-13 per-debtor self-settle). Withdraw-only success: when the caller owes nothing but had a squad deposit, the deposit is returned to their personal custody and the call succeeds with ``settled_shares == 0``, ``squad_funds_withdrawn_cents > 0``, and ``tx_id == withdrawal_tx_id`` (no ``SettleShare`` tx ran — the withdrawal is the only on-chain tx). A 404 ``ACCOUNTING_NOT_FOUND`` is returned only when the caller owed nothing AND had no deposit (nothing to settle).
| Campo | Tipo | Detalhe |
|---|---|---|
| caller_account_id | string | obrigatório |
| created_at | string | obrigatório |
| settled_shares | integer | obrigatório |
| sqd_id | string | obrigatório |
| squad_funds_withdrawn_cents | integer | Padrão 0 |
| state | string | Padrão "OPEN" |
| transfers | array de SquadSettleTransfer | |
| tx_id | string | obrigatório |
| vqbrl_burned | integer | obrigatório |
| withdrawal_tx_id | string, opcional |
SquadSettleTransfer
| Campo | Tipo | Detalhe |
|---|---|---|
| amount_cents | integer | obrigatório |
| creditor_pkh | string | obrigatório |
SquadSimplifyConsolidation
One synthetic net entry the simplification created: a single creditor owed by one or more debtors, replacing the gross shares that netted to it.
| Campo | Tipo | Detalhe |
|---|---|---|
| creditor_account_id | string, opcional | |
| creditor_pkh | string | obrigatório |
| debtors | array de SquadSimplifyDebtor | |
| entry_seq | integer | obrigatório |
| total_cents | integer | obrigatório |
SquadSimplifyRequest
``POST /v1/squads/{sqd_id}/simplify-debts`` — collapse the open accounting graph into the minimal set of net debts. OWNER-only: it void+reissues *every* member's shares, a squad-wide restructuring (unlike settle, which only ever moves the caller's own funds).
| Campo | Tipo | Detalhe |
|---|---|---|
| caller_account_id | string | obrigatório |
SquadSimplifyResponse
201 body for ``POST /v1/squads/{sqd_id}/simplify-debts``. ``no_op`` is true (with empty void/created lists and equal before/after counts) when the graph is already minimal — no on-chain work runs. Otherwise the open shares were voided and the minimal net set reissued: ``vqbrl_minted`` equals ``vqbrl_burned`` (total open debt is conserved; only the edge count shrinks).
| Campo | Tipo | Detalhe |
|---|---|---|
| consolidations | array de SquadSimplifyConsolidation | |
| created_at | string | obrigatório |
| created_entries | array de integer | |
| no_op | boolean | Padrão false |
| reissue_tx_ids | array de string | |
| sqd_id | string | obrigatório |
| state | string | Padrão "OPEN" |
| transfers_after_count | integer | obrigatório |
| transfers_before_count | integer | obrigatório |
| void_tx_ids | array de string | |
| voided_entries | array de integer | |
| vqbrl_burned | integer | Padrão 0 |
| vqbrl_minted | integer | Padrão 0 |
SquadSpendResponse
201 body for ``POST /v1/squads/{sqd_id}/spends`` (RFC-018 §5.1, SQ-12, B-SQ-07). ``consumed_balance_utxos`` are the Balance UTxO refs spent at the SquadValidator; ``residual_balance_utxo`` is the leftover Balance UTxO (``tx_hash#ix``) or ``null`` when the spend is exact. ``obligation_id`` is the logical ``obl_*`` row recording the spend (debtor = the squad). For an **internal** spend ``state`` is ``"OPEN"`` and ``recipient_account_id`` is set. For an **external Pix** spend ``recipient_account_id`` is ``null``, ``state`` is ``"PROCESSING"``, and ``payout`` carries the rail status. The amount is centavos (1 QBRL = 1 centavo).
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
| amount | SquadAmount | obrigatório |
| consumed_balance_utxos | array de string | obrigatório |
| created_at | string | obrigatório |
| event_seq | integer | obrigatório |
| obligation_id | string | obrigatório |
| payout | PayoutBlock, opcional | |
| recipient_account_id | string, opcional | |
| residual_balance_utxo | string, opcional | |
| sqd_id | string | obrigatório |
| state | string | Padrão "OPEN" |
| tx_id | string | obrigatório |
SquadUpdateRequest
``PATCH /v1/squads/{sqd_id}`` — an OWNER edits the squad's display fields. Partial update: only the fields present in the body change; an omitted field is left untouched, and an explicit ``null`` on an optional metadata field clears it (``name`` is never clearable). The route dumps this with ``exclude_unset=True`` so the handler can tell "omitted" from "set to null". This is an off-chain projection write only — no Cardano transaction is built.
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
| metadata | SquadMetadata, opcional | |
| name | string, opcional |
SquadUpdateResponse
200 body for ``PATCH /v1/squads/{sqd_id}`` — the squad's full current display metadata after the edit.
| Campo | Tipo | Detalhe |
|---|---|---|
| metadata | SquadMetadata | obrigatório |
| name | string | obrigatório |
| sqd_id | string | obrigatório |
| updated_at | string | obrigatório |
SquadVoidResponse
200 body for ``DELETE /v1/squads/{sqd_id}/contributions/{entry_seq}`` (SQ-13).
| Campo | Tipo | Detalhe |
|---|---|---|
| sqd_id | string | obrigatório |
| tx_id | string | obrigatório |
| voided_entry_seq | integer | obrigatório |
| voided_shares | integer | obrigatório |
| vqbrl_burned | integer | obrigatório |
UpdateMemberQuotaRequest
``PATCH /v1/squads/{sqd_id}/members/{member_account_id}/quota`` (RFC-018). ``actor_account_id`` is the caller: a member may change their own quota, and an OWNER may change anyone's. Blocked (409 QUOTA_CHANGE_LOCKED) once the squad has any settled/voided entry.
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |
| quota | integer | obrigatório |
ValidationError
| Campo | Tipo | Detalhe |
|---|---|---|
| ctx | object | |
| input | não declarado | |
| loc | array de string ou integer | obrigatório |
| msg | string | obrigatório |
| type | string | obrigatório |
VoidContributionRequest
``DELETE /v1/squads/{sqd_id}/contributions/{entry_seq}`` body (SQ-13). The creditor (original actor) burns the entry's still-unsettled shares.
| Campo | Tipo | Detalhe |
|---|---|---|
| actor_account_id | string | obrigatório |