# BNW CORE SERVICE ## Docs - Identity Mfa [Passkeys](https://core-service-docs.flw-bnw.dev/passkeys-2447624m0.md): ## API Docs - Card Vaulting [Create a card vault session](https://core-service-docs.flw-bnw.dev/create-a-card-vault-session-41292362e0.md): Securely tokenises a payment card and creates a short-lived vault session that can be used downstream to authorise payment operations without re-transmitting raw card data. The session is tied to the authenticated entity (derived from the bearer token) and expires 10 minutes after creation. Raw card fields are never stored — they are vaulted immediately and only the resulting vault reference is persisted. Supply a secret or public API key; JWT is not accepted on this endpoint. - Fee Lookups [Compute fees for a transaction](https://core-service-docs.flw-bnw.dev/compute-fees-for-a-transaction-41292363e0.md): Resolves and returns the applicable processing fee for a given transaction context. The service scores all configured fee rules against the provided currency, type, amount, and optional scoping fields (entity, account, system label, country, provider), then selects the most specific matching rule. If a card payment instrument is supplied, the card's BIN is used to resolve the issuer country, overriding any explicitly passed country value. The entity is always derived from the authenticated caller — it does not need to be supplied in the request body. - Intent Action Status Lookups [Look up the status of an intent action](https://core-service-docs.flw-bnw.dev/look-up-the-status-of-an-intent-action-41292364e0.md): Retrieves the current status of a payment intent action along with the status of its parent payment intent. You must supply either `intent_action_id` or `client_reference` (or both). This is useful for polling the outcome of an action without storing the internal identifier — pass the `client_reference` you supplied at action creation time and get the full status picture back. - Payment Intents [Create a payment intent](https://core-service-docs.flw-bnw.dev/create-a-payment-intent-41292365e0.md): Creates a new payment intent representing a customer's intent to pay a specific amount in a given currency. You may optionally include a first intent action inline (via `intent_action`) to kick off the payment flow immediately — for example, authorizing a card or logging an offline payment — without needing a separate intent-action request. - Payment Intents [Cancel a payment intent](https://core-service-docs.flw-bnw.dev/cancel-a-payment-intent-41292366e0.md): Cancels a payment intent, permanently stopping it from being processed. Only intents in a `pending` state can be cancelled — attempting to cancel an intent that has already been processed, failed, or previously cancelled will return an error. Supply a `status_reason` to record why the intent was cancelled; this reason is stored on the intent and returned in subsequent reads. - Payment Intents [List payment intents](https://core-service-docs.flw-bnw.dev/list-payment-intents-44488426e0.md): Retrieves a paginated list of payment intents belonging to the authenticated entity, newest first. Supports filtering by account, payment page, invoice, status (single or multiple), a created-date range, and a free-text search across the counterparty's name/email and the intent's client reference. Excludes intents in the internal `ongoing` state (reserved for rolling intents such as virtual cards) — these never appear in list results regardless of the filters supplied. - Payment Intents [Retrieve a payment intent](https://core-service-docs.flw-bnw.dev/retrieve-a-payment-intent-44488427e0.md): Fetch a single payment intent by its unique identifier, scoped to the authenticated entity. The response includes the intent's current state, the counterparty (if one was attached), the primary intent action (the action referenced by the intent, if any), and the full ordered history of every intent action ever taken against this intent — newest first. Use this to check on the status of a payment, inspect why it failed, or read back the customer and instrument details captured during authorization. - Intent Actions [Create an intent action](https://core-service-docs.flw-bnw.dev/create-an-intent-action-41314166e0.md): Attaches a new payment action to an existing payment intent that is still in a `pending` state. An intent action represents a single attempt to collect payment — for example, authorizing a card or logging an offline settlement. - Intent Actions [Advance an intent action to the next step](https://core-service-docs.flw-bnw.dev/advance-an-intent-action-to-the-next-step-41314167e0.md): Submits the data required to progress a pending intent action to the next processing step. Call this endpoint when a payment action is waiting for additional input — either `authorize` (to supply payment instrument details such as card PIN or billing address) or `validate` (to submit an OTP). The action must be in `pending` status and its `action_current_step` must match the expected step for the supplied `action` value. On success the action is re-dispatched to the payment provider, and if the provider deems it successful the parent payment intent is automatically finalized. - Intent Actions [Retrieve the authentication session for a pending redirect action](https://core-service-docs.flw-bnw.dev/retrieve-the-authentication-session-for-a-pending-redirect-action-41361741e0.md): Fetches the data required to render or complete a redirect-based authentication step for a payment intent action. This endpoint is called after a payment action has been dispatched and the provider has responded with a redirect (e.g. a 3DS challenge URL). It returns the amounts, fees, provider-specific redirect instructions, and the return URL to send the customer back to after they complete the authentication challenge. - Accounts [Create a new account](https://core-service-docs.flw-bnw.dev/create-a-new-account-41351402e0.md): Creates a financial account for the authenticated entity. The account is backed by a ledger entry in TigerBeetle and is assigned a unique Bank Account Number (BAN). The BAN is an internal identifier generated by this platform for reference and reconciliation only — it is not yet connected to any interbank transfer rail (e.g. NIP), so external banks cannot send money to it. The currency, type, and category are validated against platform-enabled values before creation. The entity_id is derived from the bearer token — you do not pass it in the body. The client_reference must be unique per entity; submitting a duplicate reference returns a validation error. - Accounts [List accounts](https://core-service-docs.flw-bnw.dev/list-accounts-41351403e0.md): Returns a paginated list of accounts belonging to the authenticated entity, ordered newest first. Use the optional query parameters to filter by status, type, category, label, or reference. Pagination is cursor-based: each response includes a cursor value that you pass in the next request to fetch the following page. When has_more is false, you have reached the end of the list. Balances for the page are fetched live from the ledger in a single batched lookup and returned as a breakdown object per account; an individual account's balance is null if its live balance could not be fetched. - Accounts [Close an account](https://core-service-docs.flw-bnw.dev/close-an-account-41351404e0.md): Closes an account belonging to the authenticated entity by setting its status to `closed`. This is a soft delete — the account record is preserved, not removed, and its status becomes terminal (a closed account cannot be reopened or modified further). The account must belong to the authenticated entity; the `entity_id` from the bearer token is automatically applied as a scoping condition, so callers cannot close accounts belonging to other entities. If the account has an associated ledger account, its live balance is checked first: closure is rejected if there is any non-zero available balance, pending credit, or pending debit, since funds must be cleared out before an account can be closed. - Accounts [Update an account](https://core-service-docs.flw-bnw.dev/update-an-account-41351405e0.md): Updates mutable fields on an existing account. Only name, description, client_label, and client_meta can be changed — currency, type, category, and other structural fields are immutable after creation. Only fields included in the request body are updated; omitted fields retain their current values. The account must belong to the authenticated entity. - Accounts [Retrieve an account](https://core-service-docs.flw-bnw.dev/retrieve-an-account-41351406e0.md): Fetches a single account by its unique identifier. The account must belong to the authenticated entity — the entity_id from the bearer token is automatically applied as a scoping condition, so callers cannot retrieve accounts belonging to other entities. Balance is fetched live from the ledger and returned as a breakdown object; if the ledger is temporarily unreachable, balance is returned as null rather than a stale cached figure. The account's `ban` is an internal identifier only — it is not yet routable from external banks. - Accounts [Retrieve an account's daily payout limit status](https://core-service-docs.flw-bnw.dev/retrieve-an-accounts-daily-payout-limit-status-44488408e0.md): Fetches the current daily transfer limit configuration and consumption for an account, scoped to the authenticated entity. The response includes the applicable limit value and where it was resolved from (account-level override vs entity-level default), how much has already been paid out successfully today (UTC calendar day), and the remaining headroom. For Nigerian entities whose KYC requirement set includes a proof-of-address field, the response also reports whether submitting proof of address unlocks a higher limit and the current submission status of that requirement. - API Keys [Create an API key](https://core-service-docs.flw-bnw.dev/create-an-api-key-41351407e0.md): Generates a new API key pair for the authenticated identity. On success, both the public key and the secret key are returned. The secret key is returned in plaintext exactly once and is never stored — you must save it immediately. Subsequent reads will not expose the secret. Each identity can have multiple API keys, but each must have a unique name within the same identity. The `identity_id`, `entity_id`, and `created_by` fields are all derived from the bearer token and cannot be set by the client. Optionally scope the key's permissions with `acl`, using recognised ACL permission names; unrecognised names are rejected. - API Keys [List API keys](https://core-service-docs.flw-bnw.dev/list-api-keys-41351408e0.md): Returns a cursor-paginated list of API keys belonging to the authenticated entity, ordered from newest to oldest. Optionally scope results to a single identity with `identity_id`, and further narrow with the optional `environment` and `status` filters. Fetch the next page by passing the `cursor` value from the previous response's `meta.pagination.cursor` field. The `secret_key` is never included in list results. - API Keys [Update an API key](https://core-service-docs.flw-bnw.dev/update-an-api-key-44325567e0.md): Updates the mutable fields of an existing API key — its `name`, `acl` permission map, and `config` constraints. All fields are optional; only the fields included in the request body are changed, everything else on the key is left untouched. The key's `environment`, `public_key`, and secret material can never be changed through this endpoint — use the rotate endpoint to replace the secret key. Renaming a key still enforces the same uniqueness rule as creation: an identity cannot have two active keys sharing a name. Protected sandbox master keys can never be edited through this endpoint and are rejected outright, regardless of ownership. - API Keys [Retrieve an API key](https://core-service-docs.flw-bnw.dev/retrieve-an-api-key-41351409e0.md): Fetches a single API key by its unique identifier, returning its full details including status, usage timestamps, and rotation history. The secret key is never returned — only the public key is exposed, except on sandbox servers where a `sandbox_meta.secret_key_plain` field is additionally included for keys that still have a persisted plaintext secret, to ease local testing. Use this endpoint to inspect key state (e.g. to check whether it has been revoked, when it was last used, or when the secret was last rotated). Only a key owned by the caller's identity or entity is returned; keys belonging to others resolve as not found. - API Keys [Revoke an API key](https://core-service-docs.flw-bnw.dev/revoke-an-api-key-41351410e0.md): Permanently revokes an API key, immediately preventing it from being used for authentication. Revocation is irreversible — a revoked key cannot be reactivated. If you need a new key for the same purpose, create a new one. The identity that makes this request is recorded as the `revoked_by` actor. Attempting to revoke an already-revoked key returns a 400 validation error. - API Keys [Rotate an API key's secret](https://core-service-docs.flw-bnw.dev/rotate-an-api-keys-secret-41351411e0.md): Generates a new key pair for an existing API key, immediately invalidating the previous secret. The public key is updated in place and the new secret key is returned in plaintext exactly once — save it immediately, as it cannot be retrieved again. The key's `id`, `name`, environment, and other metadata remain unchanged. The key must belong to the authenticated identity or its entity, must currently be `active`, and must not be the sandbox master key. Optionally set `overlap_seconds` to keep the previous secret valid for a grace period after rotation, useful for zero-downtime credential swaps. - App Setting Values [Delete an app setting value](https://core-service-docs.flw-bnw.dev/delete-an-app-setting-value-41351412e0.md): Permanently removes an app setting value record by its unique identifier. The record must belong to the authenticated entity. The caller must hold the appropriate ACL permission for the setting's component type: `can_set_setting_values` for entity-scoped values, or `can_set_account_setting_values` for account-scoped values. This action is irreversible — to restore a deleted value, it must be re-created via POST /app-setting-values. - App Setting Values [Retrieve an app setting value](https://core-service-docs.flw-bnw.dev/retrieve-an-app-setting-value-41351413e0.md): Fetches a single app setting value record by its unique identifier. The record must belong to the authenticated entity — entity_id from the bearer token is applied as a scope guard so callers cannot retrieve settings that belong to other entities. The response includes an augmented `component` object with the resolved name of the entity or account the value is scoped to. - App Setting Values [List app setting values](https://core-service-docs.flw-bnw.dev/list-app-setting-values-41351414e0.md): Returns a paginated list of app setting value records for the authenticated entity, ordered newest first. Results can be filtered by account scope and by a specific set of setting names. Each item includes a resolved `component` object with the display name of the entity or account the value is scoped to. Use the returned `cursor` to fetch the next page of results. - App Setting Values [Create or update an app setting value](https://core-service-docs.flw-bnw.dev/create-or-update-an-app-setting-value-41351415e0.md): Sets the value of a named app setting for an entity or one of its accounts. This operation is an upsert — if a value for the given setting name already exists on the target component, it is updated in place; otherwise a new record is created. The setting must exist in the system and must not be admin-only. The caller must have the appropriate ACL permission (`can_set_setting_values` for entity-scoped settings, `can_set_account_setting_values` for account-scoped settings). The type and shape of `value` are validated against the setting's configured constraints at write time. - Entities [Create an entity](https://core-service-docs.flw-bnw.dev/create-an-entity-41351432e0.md): Creates a new entity representing a business or individual under the authenticated identity. Each entity must have a unique `client_reference` per identity. You may optionally attach a `parent_id` to model hierarchical entity relationships — the parent entity must already exist and belong to the same identity. - Entities [List entities](https://core-service-docs.flw-bnw.dev/list-entities-41351433e0.md): Returns a paginated list of all entities the authenticated identity has access to. Results are ordered newest-first by creation date. Use the `cursor` returned in each response to fetch the next page; when `has_more` is `false` you have reached the end of the list. - Entities [Close an entity](https://core-service-docs.flw-bnw.dev/close-an-entity-41351434e0.md): Closes (soft-deletes) an entity by setting its `status` to `closed`. The record itself is not physically removed — this is an irreversible lifecycle transition, not a hard delete. The identity must have `can_delete_entity` or wildcard `*` ACL access to the entity. - Entities [Update an entity](https://core-service-docs.flw-bnw.dev/update-an-entity-41351435e0.md): Updates one or more mutable fields on an existing entity. Only the fields you include in the request body are changed — omitted fields retain their current values. The identity must have `can_edit_entity` or wildcard `*` ACL access to the entity. - Entities [Retrieve an entity](https://core-service-docs.flw-bnw.dev/retrieve-an-entity-41351436e0.md): Fetches a single entity by its unique identifier. The authenticated identity must have an active resource-access record for the entity — either a wildcard `*` permission or the specific `can_view_entity` ACL flag. Attempting to fetch an entity you do not have access to returns a `403`. - Entities [Set the selected entity](https://core-service-docs.flw-bnw.dev/set-the-selected-entity-41351437e0.md): Sets (or switches) the currently active entity for the authenticated identity. Only one entity can be selected at a time per identity — calling this endpoint again with a different `entity_id` replaces the previous selection. - Entities [Retrieve public metadata for the authenticated entity](https://core-service-docs.flw-bnw.dev/retrieve-public-metadata-for-the-authenticated-entity-41594371e0.md): Returns lightweight public-facing metadata for the entity that owns the public API key used to authenticate the request. This endpoint is designed for client-side or storefront integrations — for example, a hosted checkout page that needs the entity's display name, logo, and checkout configuration without exposing sensitive entity data. - Entities [Create an entity sandbox session](https://core-service-docs.flw-bnw.dev/create-an-entity-sandbox-session-44326535e0.md): Exchanges the caller's authenticated dashboard session for a login session on the sandbox server, scoped to the sandbox shadow of the given entity. The authenticated identity must have an active resource-access record for the entity — either a wildcard `*` permission or the specific `can_view_entity` ACL flag — and the resolved entity sandbox must have completed activation. By default the entity's default sandbox (`is_default: true`) is used; pass `sandbox_id` to target a specific, non-default sandbox belonging to the entity instead. Use the returned `session_token` to authenticate directly against `sandbox_base_url` (for example, embedding an iframe or redirecting the caller into the sandbox environment). - Entities [Retrieve one of your entities, including your membership](https://core-service-docs.flw-bnw.dev/retrieve-one-of-your-entities-including-your-membership-44488415e0.md): Fetches a single entity by its unique identifier and includes the authenticated identity's membership details for that entity (ownership status, role, and permissions). The authenticated identity must have an active resource-access record for the entity — either a wildcard `*` permission or the specific `can_view_entity` ACL flag. Attempting to fetch an entity you do not have access to returns a `403`. - Entities [List my entities](https://core-service-docs.flw-bnw.dev/list-my-entities-44488416e0.md): Returns a paginated list of all entities the authenticated identity has access to, the same set returned by `GET /entities`, but with an additional `membership` object on each entity describing the caller's own relationship to it (ownership, role, and permissions). - Counterparties [Create a counterparty](https://core-service-docs.flw-bnw.dev/create-a-counterparty-41675213e0.md): Creates a new counterparty under the authenticated entity. A counterparty represents an individual or business that your entity transacts with — for example, a customer, vendor, or recipient. - Counterparties [List counterparties](https://core-service-docs.flw-bnw.dev/list-counterparties-41675214e0.md): Returns a paginated list of counterparties belonging to the authenticated entity, sorted by creation date (newest first). - Counterparties [Update a counterparty](https://core-service-docs.flw-bnw.dev/update-a-counterparty-41675215e0.md): Partially updates an existing counterparty belonging to the authenticated entity. Only the fields you include in the request body are modified; omitted fields retain their current values. - Counterparties [Retrieve a counterparty](https://core-service-docs.flw-bnw.dev/retrieve-a-counterparty-41675216e0.md): Fetches a single counterparty by its unique identifier. The counterparty must belong to the authenticated entity — you cannot retrieve counterparties belonging to other entities. - Maker Checker Approver Groups [Create a maker-checker approver group](https://core-service-docs.flw-bnw.dev/create-a-maker-checker-approver-group-43483004e0.md): Creates a new approval group for the authenticated entity so maker-checker workflows can be routed to a defined set of approvers. The service derives the `entity_id` from the caller's active session and validates that the group name is unique for the same entity and workflow type. Each approver must be a valid identity, and duplicate approver identities or approval order numbers are rejected. When `is_default` is set to `true`, the new group becomes the default active group for that entity and type, and any existing default group is automatically demoted. - Maker Checker Approver Groups [List maker-checker approver groups](https://core-service-docs.flw-bnw.dev/list-maker-checker-approver-groups-43483005e0.md): Returns the maker-checker approver groups for the authenticated entity, ordered newest first. The service derives the entity from the caller's active session and does not accept a client-supplied entity_id. Use the optional query filters to narrow results by workflow type or status, and use the pagination cursor to move through larger result sets. - Maker Checker Approver Groups [Deactivate a maker-checker approver group](https://core-service-docs.flw-bnw.dev/deactivate-a-maker-checker-approver-group-43483006e0.md): Marks the specified maker-checker approver group as inactive for the current entity and clears the default flag. This disables the group from future approval flows without deleting the underlying record. - Maker Checker Approver Groups [Update a maker-checker approver group](https://core-service-docs.flw-bnw.dev/update-a-maker-checker-approver-group-43483007e0.md): Updates one or more editable attributes on an existing maker-checker approver group for the authenticated entity. Only the fields included in the request body are changed; omitted values keep their current values. The group must belong to the same entity as the bearer token, and the group's `entity_id` is derived server-side and cannot be supplied by the client. When `is_default` is set to `true`, the group becomes the default for its entity and type and any other active default group for the same entity/type is automatically demoted. - Maker Checker Approver Groups [Retrieve a maker-checker approver group](https://core-service-docs.flw-bnw.dev/retrieve-a-maker-checker-approver-group-43483008e0.md): Fetches a single maker-checker approver group by its unique identifier for the authenticated entity. The lookup is automatically scoped by the entity_id derived from the caller's session, so users can only read groups that belong to their current entity. - Bulk Payout Intent Actions [Create bulk payout intent actions](https://core-service-docs.flw-bnw.dev/create-bulk-payout-intent-actions-43494181e0.md): Creates a batch of payout intent actions for a `bulk` type payout intent that is in the `pending` state. Unlike the single payout intent actions endpoint, this accepts an array of `items`, each describing one disbursement leg of the batch. - Bulk Payout Intent Actions [Retrieve a bulk payout intent action batch](https://core-service-docs.flw-bnw.dev/retrieve-a-bulk-payout-intent-action-batch-43494182e0.md): Fetches a single bulk payout intent action batch by its unique identifier. A bulk payout intent action batch represents a group of individual payout intent actions submitted together against a bulk payout intent, along with the per-item validation and queuing outcome for each submission. The batch must belong to the authenticated entity — the entity_id from the bearer token is automatically applied as a scoping condition, so callers cannot retrieve batches belonging to other entities. - Bulk Payout Intent Actions [Preview bulk payout intent actions](https://core-service-docs.flw-bnw.dev/preview-bulk-payout-intent-actions-44488414e0.md): Performs a dry-run validation of a batch of payout intent action items against a `bulk` type payout intent that is in the `pending` state, without creating or persisting anything. Use this to surface per-item problems (bad shape, unresolvable bank account) to a caller before they submit the same `items` array to the `POST /bulk-payout-intent-actions` endpoint. - Payout Intent Action Retries [Retry a failed payout intent action](https://core-service-docs.flw-bnw.dev/retry-a-failed-payout-intent-action-43494183e0.md): Creates a new action to retry a `payout_intent_id` whose most recent action failed. The parent payout intent must currently be in the `failed` status and must have no `pending` or `processing` action outstanding, otherwise the request fails with a `400` error. - Payout Intent Actions [Create a payout intent action](https://core-service-docs.flw-bnw.dev/create-a-payout-intent-action-43494184e0.md): Creates the action that actually moves funds for a `single` type payout intent that is in the `pending` state. This is a one-to-one operation for single intents: once an action exists for a payout intent, subsequent attempts fail with a `400` error instructing you to use the retry endpoint instead. Bulk intents must use the bulk payout intent actions endpoint instead of this one. - Payout Intent Actions [List payout intent actions](https://core-service-docs.flw-bnw.dev/list-payout-intent-actions-43494185e0.md): Returns a paginated list of payout intent actions belonging to the authenticated entity, ordered newest first. A payout intent action represents a concrete disbursement attempt (a single payout or cash-offline collection) carried out against a payout intent, including the resolved counterparty, fee, and provider used. Use the optional query parameters to filter by parent payout intent, counterparty, or status. Pagination is cursor-based: pass the cursor value from the previous response's meta.pagination.cursor field to fetch the next page. When has_more is false, you have reached the end of the list. - Payout Intent Actions [Retrieve a payout intent action](https://core-service-docs.flw-bnw.dev/retrieve-a-payout-intent-action-43494186e0.md): Fetches a single payout intent action by its unique identifier. A payout intent action represents a concrete attempt to disburse funds against a payout intent (e.g. a payout to a bank account, or an offline cash payout). The action must belong to the authenticated entity — the entity_id from the bearer token is automatically applied as a scoping condition, so callers cannot retrieve actions belonging to other entities. - Payout Intents [Create a payout intent](https://core-service-docs.flw-bnw.dev/create-a-payout-intent-43494187e0.md): Creates a new payout intent representing an instruction to disburse funds from one of your accounts. The intent is created in a `pending` state, or `pending-approval` when the entity has a default maker-checker approver group configured for payouts — in that case, the intent must be fully approved before it can be actioned. Once created, you attach a payout intent action (via the intent actions API) to actually move the funds. - Payout Intents [List payout intents](https://core-service-docs.flw-bnw.dev/list-payout-intents-43494188e0.md): Returns a paginated list of payout intents belonging to the authenticated entity, ordered newest first. A payout intent represents a request to move funds out of one of your accounts, optionally routed through a maker-checker approval workflow before it is dispatched. Use the optional query parameters to filter by status or source account. Pagination is cursor-based: pass the cursor value from the previous response's meta.pagination.cursor field to fetch the next page. When has_more is false, you have reached the end of the list. - Payout Intents [Retrieve a payout intent](https://core-service-docs.flw-bnw.dev/retrieve-a-payout-intent-43494189e0.md): Fetches a single payout intent by its unique identifier. The payout intent must belong to the authenticated entity — the entity_id from the bearer token is automatically applied as a scoping condition, so callers cannot retrieve payout intents belonging to other entities. - Payout Intents [Edit a payout intent](https://core-service-docs.flw-bnw.dev/edit-a-payout-intent-43494190e0.md): Updates mutable fields on an existing payout intent, such as its `reason`, `supporting_documents`, `client_meta`, and `client_reference`. Only intents in a `new` or `pending` state can be edited — once a payout intent action has been created for the intent (i.e. it has moved past these states), attempting to edit it returns an error. Fields omitted from the request body are left unchanged; only fields explicitly supplied are updated. - Payout Intents [Cancel a payout intent's active schedule](https://core-service-docs.flw-bnw.dev/cancel-a-payout-intents-active-schedule-44356347e0.md): Cancels the active schedule on a scheduled or recurring payout intent, stopping any further automatic occurrences from being dispatched. The intent's `status` transitions to `cancelled` and `next_run_at` is cleared. This only applies to payout intents currently in the `scheduled` or `recurring` state — intents in any other state (including those whose schedule has already run to completion or been previously cancelled) cannot be cancelled through this endpoint. Cancellation is race-safe: the scheduling worker re-checks the intent's status immediately before firing or re-arming the next occurrence, so a cancellation that lands concurrently with a scheduled run will still prevent any further occurrences. - Payout Intents [Edit a payout intent's active schedule](https://core-service-docs.flw-bnw.dev/edit-a-payout-intents-active-schedule-44488428e0.md): Updates the schedule configuration of a payout intent that is currently `scheduled`, `recurring`, or `paused`. Use this to change the disbursed `amount`, the debit `account_id`, the timing of the next occurrence (`next_run_at`), or the recurrence cadence (`interval_ms`/`cron`) of a recurring schedule. Fields omitted from the request body are left unchanged; only fields explicitly supplied are updated. `interval_ms` and `cron` are only applicable to `recurring` schedules and are mutually exclusive — supplying one clears the other. Changing `next_run_at`, `interval_ms`, or `cron` re-arms the underlying scheduling job against the new timing; if the intent is currently `paused`, the job is disarmed but not re-armed until the schedule is resumed. If the intent also has an `action_template`, any updated `amount` or `account_id` is mirrored onto the template's own `amount`/`account_id` fields (when those fields are present on the template) so future auto-dispatched occurrences reflect the change. - Payout Intents [Cancel a payout intent](https://core-service-docs.flw-bnw.dev/cancel-a-payout-intent-44488429e0.md): Cancels a payout intent outright, before any payout intent action has been created against it. The intent must belong to the authenticated entity — the entity_id from the bearer token is automatically applied as a scoping condition, so callers cannot cancel payout intents belonging to other entities. Only intents in the `new` or `pending` state can be cancelled through this endpoint; once an action has been created (or the intent has moved past those states for any other reason) it can no longer be cancelled here. The transition is race-safe: it is applied as an atomic, status-guarded update, so a cancellation that lands concurrently with a `POST /payout-intent-actions` request for the same intent cannot succeed against an intent an action has just been created for. This endpoint is unrelated to `DELETE /payout-intent-schedules/{id}`, which cancels an active recurring/scheduled intent's schedule rather than the intent itself. - Virtual Cards [Create a virtual card](https://core-service-docs.flw-bnw.dev/create-a-virtual-card-43536027e0.md): Issues a new self-contained virtual card funded from one of your accounts. The card is created `active` immediately, or `pending-approval` when the entity has a default maker-checker approver group configured for card creation — in that case, no funds are moved and no card is issued by the provider until the request is fully approved. - Virtual Cards [List virtual cards](https://core-service-docs.flw-bnw.dev/list-virtual-cards-43536028e0.md): Returns a paginated list of virtual cards belonging to the authenticated entity, ordered newest first. A virtual card is a card-issuing instrument funded from one of your accounts, which can be created directly or gated behind a maker-checker approval workflow. Use the optional query parameters to filter by status, funding account, currency, or your own client reference. Pagination is cursor-based: pass the cursor value from the previous response's meta.pagination.cursor field to fetch the next page. When has_more is false, you have reached the end of the list. - Virtual Cards [Update a virtual card](https://core-service-docs.flw-bnw.dev/update-a-virtual-card-43536029e0.md): Updates mutable fields on an existing virtual card belonging to the authenticated entity: description, client_meta, and status. Only fields included in the request body are changed — omitted fields retain their current values. Structural fields (currency, account_id, cardholder, billing_address, masked_pan, expiry, type, card_brand) cannot be changed after creation. Setting status to frozen suspends the card for new authorizations; setting it back to active re-enables it. A card that is still pending-approval (awaiting maker-checker sign-off on its creation) cannot have its status changed via this endpoint until that approval completes. - Virtual Cards [Retrieve a virtual card](https://core-service-docs.flw-bnw.dev/retrieve-a-virtual-card-43536030e0.md): Fetches a single virtual card by its unique identifier. The card must belong to the authenticated entity — the entity_id from the bearer token is automatically applied as a scoping condition, so callers cannot retrieve virtual cards belonging to other entities. Returns the card's masked PAN, expiry, cardholder details, cached balance, and current lifecycle status. The full, unmasked card number is never returned by this endpoint. - Maker Checker Action Decisions [Record a decision on a maker-checker action](https://core-service-docs.flw-bnw.dev/record-a-decision-on-a-maker-checker-action-43537543e0.md): Records the authenticated identity's approval, rejection, or send-back for a pending maker-checker action, identified by its `reference_id` and `type` within the caller's entity. The `entity_id` and `identity_id` are derived from the authenticated session, not the request body. The service enforces strict approval-order sequencing: a decision is only accepted from the identity whose `approval_order` matches the next unrecorded step in the action's approver list, and only while the action's overall status is still `pending`. Rejecting or sending back an action immediately moves its status to `rejected` or `sent_back` respectively and requires a `status_reason`. Approving records the identity's approval and, once every configured approver has approved, automatically advances the action's status to `approved`. Once the action leaves `pending`, a background job is queued to carry out any downstream side effects associated with that outcome. - Maker Checker Actions [Retrieve a maker-checker action's status](https://core-service-docs.flw-bnw.dev/retrieve-a-maker-checker-actions-status-43537544e0.md): Fetches the current status and approval progress of a maker-checker action for a given resource. A maker-checker action guards a sensitive operation (such as a payout, account transfer, card creation, voucher creation, or team invite) behind one or more approvers before it is allowed to proceed. Use this endpoint to check whether an action is still `pending`, has been `approved`, or has been `rejected`, and to see who has approvers assigned and who has already made a decision. - Maker Checker Actions [List maker-checker actions](https://core-service-docs.flw-bnw.dev/list-maker-checker-actions-44488424e0.md): Returns the maker-checker actions belonging to the authenticated identity's entity, ordered newest first. A maker-checker action guards a sensitive operation (such as a payout, card creation, voucher creation, or team invite) behind one or more approvers before it is allowed to proceed. The `entity_id` and `identity_id` used for scoping and per-record flags are both derived from the authenticated session and are not accepted as query parameters. - Maker Checker Actions [Withdraw a maker-checker action](https://core-service-docs.flw-bnw.dev/withdraw-a-maker-checker-action-44488425e0.md): Cancels a pending maker-checker action before any approver has finished deciding on it, taking it out of the approval queue entirely. Only the identity that originally requested the action (the `requester_identity_id` on the record) may withdraw it, and only while it is still `pending` — once an action has moved to `approved`, `rejected`, or has already been withdrawn, this endpoint will reject the request. - Payment Pages [Create a payment page](https://core-service-docs.flw-bnw.dev/create-a-payment-page-43600223e0.md): Creates a hosted payment page that customers can visit to make a payment without you building a custom checkout UI. Creating a page also creates a backing payment intent (visible as `payment_intent_id` on the response) that tracks the money movement, and a stats record that tracks how many payments have been made against the page. - Payment Pages [List payment pages](https://core-service-docs.flw-bnw.dev/list-payment-pages-43600224e0.md): Returns a paginated list of payment pages belonging to the authenticated entity, ordered newest first. A payment page is a hosted, shareable checkout that collects payment against an underlying payment intent, and can be configured for single or repeated use, a fixed or dynamic amount, and custom additional fields. Use the optional query parameters to filter by status. Pagination is cursor-based: pass the cursor value from the previous response's meta.pagination.cursor field to fetch the next page. When has_more is false, you have reached the end of the list. - Payment Pages [Delete a payment page](https://core-service-docs.flw-bnw.dev/delete-a-payment-page-43600225e0.md): Permanently removes a payment page belonging to the authenticated entity. The page is first marked as deleted (its status field is set to deleted and updated is refreshed) and its resulting state is returned, after which the underlying record is soft-deleted from storage. Once deleted, the page's public slug becomes unavailable and any subsequent payment attempts against it will fail. This action cannot be undone — there is no endpoint to restore a deleted payment page. The entity_id is derived from the bearer token, so you can only delete payment pages owned by your own entity. - Payment Pages [Edit a payment page](https://core-service-docs.flw-bnw.dev/edit-a-payment-page-43600226e0.md): Updates one or more fields of an existing payment page belonging to the authenticated entity. Only the fields supplied in the request body are changed — any field omitted keeps its current value. The `configuration` object is merged field-by-field with the page's existing configuration rather than replaced wholesale, so you can update a single nested setting (e.g. `configuration.thank_you_note`) without resending the entire configuration. If `configuration.additional_fields` is supplied, it fully replaces the existing additional fields list. If the update changes `configuration.max_payments_allowed`, the page's payment statistics record is updated to reflect the new cap. Returns the full, up-to-date payment page on success. - Payment Pages [Retrieve a payment page](https://core-service-docs.flw-bnw.dev/retrieve-a-payment-page-43600227e0.md): Fetch a single payment page owned by the authenticated entity, by its unique identifier. Returns the page's configuration (amount settings, single-use/multi-use limits, thank-you note, additional collected fields) along with lightweight usage stats (`total_payments` and `max_allowed_total_payments`). The page must belong to the authenticated entity — pages belonging to other entities are reported as not found. - Payment Pages [Retrieve a published payment page by slug](https://core-service-docs.flw-bnw.dev/retrieve-a-published-payment-page-by-slug-43600228e0.md): Fetches the public-facing details of a payment page using its unique, human-readable slug. This endpoint is unauthenticated and intended to power the checkout UI a payer sees when they visit a shareable payment page link — it only ever returns pages that are currently `published` and not expired, and never exposes internal fields like `entity_id` or `account_id`. - Invoices [Create an invoice](https://core-service-docs.flw-bnw.dev/create-an-invoice-43797148e0.md): Creates a new invoice in `draft` status for the authenticated entity, billed against one of its active accounts. You supply the line items, any applicable charges (taxes, fees, discounts), and optional payment tranches; the server computes each line item's amount, resolves charge and tranche amounts (percentage or flat), and derives `total_amount`, `total_deductible_charges`, and `total_additional_charges`. The invoice is not sent to the recipient by this call — it only creates the draft record. - Invoices [List invoices](https://core-service-docs.flw-bnw.dev/list-invoices-43797149e0.md): Returns a paginated list of invoices belonging to the authenticated entity, ordered newest first. Use the optional query parameters to filter by status, payment_status, or account_id. Pagination is cursor-based: each response includes a meta.pagination.cursor value that you pass as the cursor query parameter on the next request to fetch the following page. When meta.pagination.has_more is false, you have reached the end of the list. - Invoices [Retrieve an invoice](https://core-service-docs.flw-bnw.dev/retrieve-an-invoice-43797150e0.md): Fetches a single invoice by its unique identifier, including its recipient details, line items, applicable charges, payment tranches, and computed totals. The invoice must belong to the authenticated entity — the entity_id from the bearer token is automatically applied as a scoping condition, so callers cannot retrieve invoices belonging to other entities. - Invoices [Edit an invoice](https://core-service-docs.flw-bnw.dev/edit-an-invoice-43797151e0.md): Updates an existing invoice belonging to the authenticated entity. This endpoint supports two mutually exclusive kinds of edit in a single request: (1) a **content edit** — changing `description`, `due_date`, `recipient`, `line_items`, `applicable_charges`, `tranches`, `client_meta`, or `customisation_meta` — which is only allowed while the invoice is still in `draft` status, or (2) a **status transition** — changing `status` to a value allowed from the invoice's current status. A single request cannot combine a `status` change with any content field; doing so returns a `400` error. When `line_items`, `applicable_charges`, or `tranches` are supplied, all monetary totals (`total_amount`, `total_deductible_charges`, `total_additional_charges`) and per-item `amount`/`resolved_amount` values are recomputed server-side from scratch — you cannot set these derived amounts directly. Transitioning `status` to `issued` also stamps `issued_at` with the current time. Transitioning to `void` or `cancelled` is blocked once any payment has been received on the invoice (`payment_status` is no longer `unpaid`). - Invoices [Retrieve an invoice as a PDF](https://core-service-docs.flw-bnw.dev/retrieve-an-invoice-as-a-pdf-44488419e0.md): Generates and returns a PDF rendering of an invoice, base64-encoded for transport in the JSON response body. The invoice must belong to the authenticated entity — the entity_id from the bearer token is automatically applied as a scoping condition, so callers cannot generate PDFs for invoices belonging to other entities. The PDF is rendered fresh on every call from the invoice's current data (recipient, line items, charges, and totals), so it always reflects the latest state of the invoice. - Invoices [Download a public invoice as a PDF](https://core-service-docs.flw-bnw.dev/download-a-public-invoice-as-a-pdf-44488420e0.md): Fetches an invoice by its public invoice_number and renders it as a downloadable PDF, base64-encoded in the response body. This endpoint is intentionally unauthenticated — it is the link shared directly with the invoice recipient (for example, embedded in an email or payment page), so no Authorization header is required. Only invoices in an issued or sent status are publicly visible; draft, void, and cancelled invoices always return a 404, whether or not the invoice_number exists, so as not to leak invoice existence or lifecycle state to unauthenticated callers. The first time this endpoint is called for a given invoice, the invoice's viewed_at timestamp is set as a side effect; subsequent calls do not change it. - Invoices [Retrieve a public invoice by invoice number](https://core-service-docs.flw-bnw.dev/retrieve-a-public-invoice-by-invoice-number-44488421e0.md): Fetches an invoice by its invoice_number for display on a public, unauthenticated invoice page (e.g. a hosted payment link shared with the invoice recipient). Only invoices in the issued or sent status are visible through this endpoint — invoices that are still a draft, or that have been voided or cancelled, are treated as not found so their existence and contents are never exposed to the public. Each successful call also marks the invoice as viewed for the first time (setting viewed_at), which downstream analytics and reminder logic rely on; subsequent views of the same invoice do not update viewed_at again. The response embeds a minimal entity object (name and logo) so the invoice page can be branded without a separate authenticated lookup. - Invoices [Send a reminder for an invoice](https://core-service-docs.flw-bnw.dev/send-a-reminder-for-an-invoice-44488422e0.md): Re-sends the invoice email to its recipient as a payment reminder, including a freshly rendered PDF attachment. Only invoices currently in the sent status, and not yet fully paid or overpaid, are eligible. Each successful reminder updates the invoice's last_sent_at timestamp, which also enforces a cooldown window (configurable via INVOICE_SEND_COOLDOWN_MS, default 60 seconds) between consecutive sends or reminders on the same invoice. The invoice must belong to the authenticated entity — the entity_id from the bearer token is automatically applied as a scoping condition, so callers cannot remind invoices belonging to other entities. - Invoices [Send or resend an invoice](https://core-service-docs.flw-bnw.dev/send-or-resend-an-invoice-44488423e0.md): Delivers an invoice to its recipient by email, attaching a rendered PDF of the invoice. This single endpoint covers both the first send and any subsequent resends/reminders: the first successful call on an `issued` invoice transitions it to `sent` status and records `last_sent_at`; subsequent calls while the invoice is already `sent` simply re-deliver the email and refresh `last_sent_at` without changing `status`. - Entity Data [Retrieve the data submission checklist for an entity](https://core-service-docs.flw-bnw.dev/retrieve-the-data-submission-checklist-for-an-entity-44126757e0.md): Fetches a comprehensive checklist of data requirements for an entity, showing which fields are required, the submission status of each, and any validation feedback. Use this to display a form or workflow UI for collecting and reviewing entity data. The entity is determined from the authenticated identity's context — you cannot retrieve a checklist for a different entity. - Entity Data [Submit entity data for KYC requirements](https://core-service-docs.flw-bnw.dev/submit-entity-data-for-kyc-requirements-44126758e0.md): Submits field data for an entity to fulfill KYC requirements. Each submitted field is validated against the requirement set for the entity's category and country. Fields may be approved, marked as pending review, or rejected based on validation rules. The entity ID is extracted from the authentication token and cannot be overridden. - Entity Data [List entity data](https://core-service-docs.flw-bnw.dev/list-entity-data-44126759e0.md): Returns a paginated list of all data fields and values collected for the authenticated entity. Results are ordered newest-first by update date. Use the cursor returned in each response to fetch the next page; when has_more is false you have reached the end of the list. - Entity Data [Review and decide on entity data submission](https://core-service-docs.flw-bnw.dev/review-and-decide-on-entity-data-submission-44126760e0.md): Approve or reject a pending entity data submission. Only identity users with the can_review_entity_data permission (or * wildcard) on the entity can review its data. After a decision is made, the entity's kyc_status is recalculated based on whether all required fields are now approved. Entity data records can only be reviewed once — attempting to review an already-decided record will fail. - Unified Verifs [Proxy a DELETE request to the Verification API](https://core-service-docs.flw-bnw.dev/proxy-a-delete-request-to-the-verification-api-44131436e0.md): Forwards an authenticated DELETE request to the Flutterwave Verification API (`https://api.verification.flutterwave.com`) on behalf of the caller, so clients never need the internal Verification API secret key. - Unified Verifs [Proxy a GET request to the Verification API](https://core-service-docs.flw-bnw.dev/proxy-a-get-request-to-the-verification-api-44131437e0.md): Forwards a GET request through core-service to the Flutterwave Verification API (https://api.verification.flutterwave.com), injecting the internal Verification API secret key server-side so callers never see or supply it themselves. Only downstream paths starting with `v1/verifications` or `v1/banks` are permitted; any other path is rejected before an upstream call is ever made. All query parameters on the request are forwarded verbatim to the corresponding Verification API route. A best-effort, PII-free audit record (caller identity, HTTP method, downstream path, upstream status code, outcome, duration) is persisted for every attempted call, including rejected and failed ones; audit persistence failures never block the response. When the downstream call reaches the Verification API, the response HTTP status code and JSON body are relayed back verbatim — including the Verification API's own 4xx/5xx errors, which are not treated as failures of this proxy endpoint. Because the response body is whatever the Verification API returns for the requested path, its exact shape cannot be documented generically here; it varies per downstream route and is not validated or transformed by core-service. - Unified Verifs [Proxy a PATCH request to the Verification API](https://core-service-docs.flw-bnw.dev/proxy-a-patch-request-to-the-verification-api-44131438e0.md): Forwards a PATCH request to the underlying Verification API (`https://api.verification.flutterwave.com`) on behalf of the authenticated caller, injecting the internal Verification API secret key server-side so callers never see or supply it themselves. - Unified Verifs [Forward a POST request to the Verification API](https://core-service-docs.flw-bnw.dev/forward-a-post-request-to-the-verification-api-44131439e0.md): Proxies a POST request through to Flutterwave's Verification API (https://api.verification.flutterwave.com), on behalf of the authenticated caller. The path segment(s) after `/unified-verifs/` (the `downstreamPath`) select which Verification API route is called; the request body and query string you send are forwarded to that route verbatim, and the Verification API's response — status code and body — is relayed back to you unchanged. Only downstream paths starting with `v1/verifications` or `v1/banks` are permitted; any other path is rejected before any upstream call is made. The Verification API's own internal secret key is injected server-side and is never exposed to callers. Every attempted call (including rejected ones) is recorded in a best-effort, PII-free audit log keyed off the caller's identity from the bearer token; audit logging failures never block the response. - Identity Session [List identity sessions](https://core-service-docs.flw-bnw.dev/list-identity-sessions-44325569e0.md): Returns a paginated list of sessions belonging to a given identity, ordered newest first. A session is created whenever an identity successfully authenticates and represents an active, terminated, or pending-MFA login on a device. Use the optional query parameters to filter by session status. Pagination is cursor-based: each response includes a cursor value that you pass in the next request to fetch the following page. When has_more is false, you have reached the end of the list. - Identity Session [Complete the MFA step of a pending login session](https://core-service-docs.flw-bnw.dev/complete-the-mfa-step-of-a-pending-login-session-44325570e0.md): Finishes the multi-factor authentication step of the login flow. Call this after the login endpoint returns a session with `mfa_required: true` (and a `session_token` in `pending-mfa` status), once the identity has satisfied one of their active login MFA methods. - Identity Session [Request a login MFA challenge or one-time-passcode](https://core-service-docs.flw-bnw.dev/request-a-login-mfa-challenge-or-one-time-passcode-44325571e0.md): Advances a pending multi-factor authentication (MFA) login session by dispatching the next verification challenge for one of the identity's active MFA methods. Call this after a login attempt returns a session in the `pending-mfa` state, so the user can obtain what they need to complete verification. Two mutually exclusive dispatch modes are supported, selected by which optional field is supplied: passing `type: "passkey"` generates and returns WebAuthn authentication (assertion) options scoped to the identity's active passkeys, while passing `identity_mfa_id` (referencing an active `email-mobile` MFA method) emails a 6-digit one-time passcode to the address on file. Exactly one of `identity_mfa_id` or `type` must be supplied. This endpoint is unauthenticated by design: it is called before the user holds any bearer token, and access is instead gated by possession of the short-lived `session_token` issued at login. Email OTP dispatch is rate-limited per MFA method to prevent notification abuse: if a code was already sent within the cooldown window, the request is rejected until the window elapses. - Identity Sessions [Terminate all active sessions for an identity](https://core-service-docs.flw-bnw.dev/terminate-all-active-sessions-for-an-identity-44325572e0.md): Marks every currently active session belonging to the given identity as `terminated`. This is useful for security actions such as "log out everywhere", forcing re-authentication after a password change, or an administrator revoking access for a compromised identity. - Identity Sessions [Terminate an identity session](https://core-service-docs.flw-bnw.dev/terminate-an-identity-session-44325573e0.md): Ends an active identity session, immediately invalidating it so it can no longer be used to authenticate requests. This is typically used to implement "log out" or to forcibly revoke a specific session (for example, one shown in a "active sessions" list). The operation is idempotent in the sense that it only succeeds against a session currently in the `active` state — attempting to terminate a session that has already been terminated returns a `400` error rather than silently succeeding again. - Entity Sandboxes [Create an additional named entity sandbox](https://core-service-docs.flw-bnw.dev/create-an-additional-named-entity-sandbox-44325574e0.md): Provisions an additional, user-named shadow entity on the sandbox server for a live entity that already has its default sandbox set up. Use this when you want more than one isolated sandbox environment for the same entity — for example to model separate test scenarios side by side. - Entity Sandboxes [Delete an entity sandbox](https://core-service-docs.flw-bnw.dev/delete-an-entity-sandbox-44488417e0.md): Removes a shadow entity sandbox. The endpoint first proxies a `DELETE /entities/:id` call to the sandbox server (authenticated with the owning identity's sandbox master key) to remove the remote shadow entity, then soft-deletes the local `entity-sandbox` bookkeeping record. - Entity Sandboxes [Rename an entity sandbox](https://core-service-docs.flw-bnw.dev/rename-an-entity-sandbox-44488418e0.md): Updates the display name (`name`) of an existing shadow entity sandbox. This is a pure metadata edit against the entity-sandbox record — it never contacts the sandbox server, so it can be performed regardless of the sandbox's current `activation_status` (including while a sandbox is still provisioning) and regardless of whether the sandbox is the entity's `is_default` one. - Identity Mfa [Enroll a new MFA method for the authenticated identity](https://core-service-docs.flw-bnw.dev/enroll-a-new-mfa-method-for-the-authenticated-identity-44325575e0.md): Begin enrollment of a multi-factor authentication method (`email-mobile`, `authenticator`, `secure-pin`, or `passkey`) for the authenticated identity. The identity is always taken from the authenticated session's JWT — it can never be supplied in the request body. Uniqueness is enforced per `identity_id` + `type` + a type-specific medium reference: for `email-mobile`, `authenticator`, and `secure-pin` the medium reference is the `type` itself, so an identity may only ever have one record of each of those types (enrolling one twice returns `409`); for `passkey` the medium reference is `device_id`, so an identity may register multiple passkeys, one per distinct device, and only re-registering the same `device_id` returns `409`. Behavior, starting `status`, and `contexts` (where the method is enforced) differ by `type`: `email-mobile`, `authenticator`, and `passkey` start in `pending` status, are scoped to the `login` context, and must be verified/activated through the corresponding verification flow before they are enforced on login. `secure-pin` starts immediately in `active` status (no separate activation step) and is scoped to the `payout` context, used to authorize payouts rather than logins. For `email-mobile`, `email` is required and a one-time verification code is immediately emailed to that address (expires in 5 minutes); the response's `provisioning` field is `null`. For `authenticator`, the service generates a new TOTP secret, builds an `otpauth://` provisioning URI, and renders it as a QR code — these are returned once in the `provisioning` field of this response only and are never retrievable again, so the client must capture and display them immediately (e.g. for the user to scan with an authenticator app or manually enter the secret). For `passkey`, `device_id` is required (`device_name` is an optional display label); the service returns a WebAuthn `PublicKeyCredentialCreationOptions` object once in the `provisioning` field, which the client must pass directly into `navigator.credentials.create()` to complete registration with the browser/authenticator — the accompanying `challenge` expires after 5 minutes. For `secure-pin`, `pin` (a 6-digit code) and exactly 2 distinct `security_questions` (with answers) are required; the PIN is rejected as weak if it is all one digit or a sequential run (e.g. `111111`, `123456`, `654321`), and a fresh set of 10 one-time backup codes is generated and returned once in the `backup_codes` field — these plaintext codes are never retrievable again, so the client must capture and display them immediately. - Identity Mfa [List MFA methods for the authenticated identity](https://core-service-docs.flw-bnw.dev/list-mfa-methods-for-the-authenticated-identity-44325576e0.md): Returns a cursor-paginated list of multi-factor authentication (MFA) methods configured for the currently authenticated identity, ordered from newest to oldest. An identity has at most one record for each singleton type (`email-mobile`, `authenticator`, `secure-pin`), but may have multiple `passkey` records — one per registered device. The `identity_id` is always derived from the bearer token — you cannot list MFA methods belonging to another identity. Fetch the next page by passing the `cursor` value from the previous response's `meta.pagination.cursor` field. Sensitive fields such as the encrypted TOTP secret, PIN hash, security question answer hashes, backup code hashes, and the WebAuthn credential public key/challenge are never included in the response; only a `has_backup_codes` flag, (for `secure-pin` methods) the security question codes, and (for `passkey` methods) non-sensitive device metadata are exposed instead. - Identity Mfa [Retrieve an identity MFA method](https://core-service-docs.flw-bnw.dev/retrieve-an-identity-mfa-method-44325577e0.md): Fetch a single multi-factor authentication method belonging to the authenticated identity by its unique identifier. Use this to check the current status of an MFA method (for example, whether it is `pending`, `active`, `inactive`, or `pending-deactivation`) before deciding whether to prompt the user to complete setup, re-verify, or remove it. The `identity_id` used to scope the lookup is always taken from the bearer token, so the method must belong to the authenticated identity — methods belonging to other identities are never returned, and a mismatch is indistinguishable from a non-existent record (both return `404`). Sensitive fields such as the encrypted TOTP secret, the secure-pin hash, and backup code/answer hashes are never included in the response; for `secure-pin` methods only the security question codes (not the answers) are exposed, a `has_backup_codes` flag replaces the raw backup codes, and for `passkey` methods only non-secret device metadata (`device_id`, `device_name`, `device_type`) is exposed — the WebAuthn credential id, public key, signature counter, and pending registration challenge are never returned. - Identity Mfa [Advance or transition the state of an existing MFA method](https://core-service-docs.flw-bnw.dev/advance-or-transition-the-state-of-an-existing-mfa-method-44325578e0.md): Drives an identity MFA method through its lifecycle: verifying a pending enrollment/deactivation code, verifying a passkey registration, changing or resetting a secure-pin PIN, initiating deactivation, disabling a `secure-pin` or `passkey` method, or reactivating an inactive method. The identity is always taken from the authenticated session's JWT and cross-checked against the record's `identity_id` — a `404` is returned if the `id` does not belong to the caller. Exactly one of the following transitions is applied per request, determined by the record's current `status`/`type` combined with the fields supplied in the body; any other combination returns a `400`: - Auth [Log in with email and password](https://core-service-docs.flw-bnw.dev/log-in-with-email-and-password-44342435e0.md): Authenticates an identity using an email address and password. On success this creates either a fully active session or a pending-MFA session, depending on whether the identity has any active multi-factor authentication methods enrolled. - Auth [Register a new identity](https://core-service-docs.flw-bnw.dev/register-a-new-identity-44342436e0.md): Creates a new user identity along with an email/password authentication credential. This is the entry point for self-service sign-up. - Auth [Request an email verification link](https://core-service-docs.flw-bnw.dev/request-an-email-verification-link-44342437e0.md): Generates a new single-use `identity-confirmation` token for the specified auth method record and queues an email containing that token for delivery to the auth method's associated email address. Use this to re-send the verification email when the original link expired, was lost, or never arrived. - Auth [Verify an email address](https://core-service-docs.flw-bnw.dev/verify-an-email-address-44342438e0.md): Confirms ownership of an email address by consuming the single-use `identity-confirmation` token that was emailed to the user (typically after signup, or after requesting a re-send via `POST /auth/email-verifications`). On success, the identity's email-password auth method is permanently marked as verified so the identity can log in with that credential. - Auth [Request a password reset](https://core-service-docs.flw-bnw.dev/request-a-password-reset-44342439e0.md): Initiates the password-reset flow for an email/password identity. This endpoint is public — it is called before the caller has any session or API credentials, so no `Authorization` header is required or checked. On success, a single-use password-reset token is generated and an email containing it is queued for delivery to the account's registered address; the raw token itself is never returned in the API response. The response is intentionally minimal (`{ "pending": true }`) and does not confirm or deny account existence in its message text, though note that an unregistered email currently causes this endpoint to return a distinct `404` rather than the same `200` — treat this as a known enumeration surface rather than an intended contract. - Auth [Complete a password reset with a one-time token](https://core-service-docs.flw-bnw.dev/complete-a-password-reset-with-a-one-time-token-44342440e0.md): Consumes a single-use `password-reset` token (previously emailed via `POST /password-resets`) and sets a new password for the identity it belongs to. The token is marked as used as part of this call, so it cannot be replayed. As a security measure, every active session belonging to the identity is terminated immediately after the password is changed, forcing re-authentication everywhere. This endpoint is intentionally unauthenticated — the token itself proves the caller controls the associated email inbox. - Auth [Change the authenticated identity's password](https://core-service-docs.flw-bnw.dev/change-the-authenticated-identitys-password-44488409e0.md): Changes the password on the `email-password` auth method belonging to the currently authenticated identity. The caller must prove they still control the account by supplying the `current_password`; it is verified against the stored hash before the `new_password` is accepted. To guard against brute-forcing the current password, failed verification attempts are tracked per auth method and the endpoint locks out further attempts (see the `429` response) once a threshold is exceeded within a rolling window. As a security measure, every one of the identity's active sessions is terminated immediately after the password is changed, forcing re-authentication everywhere (including the session used to make this request). - Auth [Confirm a pending email address change](https://core-service-docs.flw-bnw.dev/confirm-a-pending-email-address-change-44488410e0.md): Completes a self-service email address change for the currently authenticated identity by consuming the one-time `email-change-otp` code that was sent to the new email address when the change was requested. On success, the identity's `email-password` auth method is updated to the new address and marked verified, and the identity's `primary_email` is updated to match. - Auth [Request a change of the authenticated identity's email address](https://core-service-docs.flw-bnw.dev/request-a-change-of-the-authenticated-identitys-email-address-44488411e0.md): Starts the email-change flow for the identity's `email-password` auth method. The caller must already be authenticated with a JWT — the identity to update is taken from the authenticated session (`identity_id`), not from the request body. - Auth [Resend an identity-confirmation email](https://core-service-docs.flw-bnw.dev/resend-an-identity-confirmation-email-44363457e0.md): Re-sends the email verification code for a registered `email-password` auth method that has not yet been verified. Use this when the original confirmation email sent at registration expired, was lost, or never arrived. - Auth [Confirm a phone number change for the current identity](https://core-service-docs.flw-bnw.dev/confirm-a-phone-number-change-for-the-current-identity-44488412e0.md): Completes the phone number change flow started by `POST /current-identity-phone`. Consumes the single-use, 6-digit `phone-change-otp` code that was sent by SMS to the requested new phone number and, on success, promotes that number from `pending_auth_id` to the identity's active, verified phone auth method. - Auth [Request a phone number change for the current identity](https://core-service-docs.flw-bnw.dev/request-a-phone-number-change-for-the-current-identity-44488413e0.md): Starts the process of changing the phone number attached to the authenticated identity. Generates a single-use, 6-digit `phone-change-otp` code, stores the requested number as `pending_auth_id` on the identity's phone auth method record, and queues an SMS containing the code to the new phone number. - Virtual Card Actions [Perform an action on a virtual card](https://core-service-docs.flw-bnw.dev/perform-an-action-on-a-virtual-card-44355887e0.md): Applies a lifecycle action — `freeze`, `unfreeze`, or `terminate` — to one of your virtual cards. The action is recorded immediately as a `pending` `VirtualCardAction` and queued for asynchronous processing with the card-issuing provider; the card's `status` is optimistically updated in the same transaction (e.g. `active` → `frozen` for `freeze`, `frozen` → `active` for `unfreeze`, or `active`/`frozen` → `terminated` for `terminate`). - ACLs [List all ACL definitions](https://core-service-docs.flw-bnw.dev/list-all-acl-definitions-44363458e0.md): Returns the full catalogue of ACL (Access Control List) permission definitions known to the system. Each entry describes a single grantable permission — its machine name, the feature group it belongs to, a human-readable display name, and a description of what it allows. This is a static reference list (not paginated) intended for building permission-management UIs, such as populating the set of permissions an ACL group or API key can be granted. - Account Transfers [Create an account transfer](https://core-service-docs.flw-bnw.dev/create-an-account-transfer-44488430e0.md): Moves funds between two accounts belonging to the same entity. A same-currency transfer is priced using the standard fee schedule for the source account; a cross-currency transfer must supply a `quote_id` obtained beforehand from the currency conversion quotes API, which is consumed (single-use) by this call and pins the exchange rate, destination amount, and fee for the transfer. - Account Transfers [List account transfers](https://core-service-docs.flw-bnw.dev/list-account-transfers-44488431e0.md): Returns a paginated list of account transfers belonging to the authenticated entity, ordered newest first. An account transfer moves funds between two accounts owned by the same entity, optionally converting currency along the way. Use the optional account_id query parameter to filter transfers where the given account was either the source or the destination. Pagination is cursor-based: each response includes a meta.pagination.cursor value that you pass as the cursor query parameter on the next request to fetch the following page. When meta.pagination.has_more is false, you have reached the end of the list. - Account Transfers [Retrieve an account transfer](https://core-service-docs.flw-bnw.dev/retrieve-an-account-transfer-44488432e0.md): Fetches a single account transfer by its unique identifier. The transfer must belong to the authenticated entity — the entity_id from the bearer token is automatically applied as a scoping condition, so callers cannot retrieve account transfers belonging to other entities. Use this to check the current status, applied fees, and exchange rate of a transfer you previously created. - ACL Roles [List all ACL roles](https://core-service-docs.flw-bnw.dev/list-all-acl-roles-44488433e0.md): Returns the full catalogue of predefined ACL (Access Control List) roles available in the system. Each role is a named bundle of permissions (e.g. `administrator`, `finance`, `operations`, `developer`, `view-only`) that can be assigned to an entity member or used to scope an ACL group. This is a static reference list (not paginated) intended for building role-management UIs, such as populating a role picker when inviting or editing an entity member. It does not return the underlying permission set for each role — only the role's identifying and descriptive metadata. - Counterparty Instruments [Add a bank account to a counterparty](https://core-service-docs.flw-bnw.dev/add-a-bank-account-to-a-counterparty-44488434e0.md): Attaches a Nigerian bank account instrument to an existing counterparty under the authenticated entity. The account holder name (`account_name`) is never supplied by the caller — it is resolved server-side by looking up `account_number` and `bank_code` against the issuing bank via Flutterwave's account resolution service, so the request will fail if the account cannot be verified. - Counterparty Instruments [List counterparty instruments](https://core-service-docs.flw-bnw.dev/list-counterparty-instruments-44488435e0.md): Returns a paginated list of bank account instruments saved for counterparties belonging to the authenticated entity, sorted by creation date (newest first). - Counterparty Instruments [Remove a counterparty's bank account](https://core-service-docs.flw-bnw.dev/remove-a-counterpartys-bank-account-44488436e0.md): Permanently removes a saved bank account (counterparty instrument) belonging to the authenticated entity. Once removed, the instrument can no longer be used as a payout destination for the counterparty it was linked to, and this action cannot be undone. - Currency Conversion Quotes [Create a currency conversion quote](https://core-service-docs.flw-bnw.dev/create-a-currency-conversion-quote-44488437e0.md): Locks in an exchange rate and fee for converting an amount from one currency to another, for use in a subsequent conversion or payout flow. The quote resolves a live rate from Flutterwave, computes the applicable processing fee for your entity, and persists the result as an active quote that expires a short time after creation. The entity is always derived from the authenticated caller — it does not need to be supplied in the request body. Both currencies must be enabled on the platform: from_currency must be outflow-enabled and to_currency must be inflow-enabled, otherwise the request is rejected. - Entity Access [Change a team member's role on an entity](https://core-service-docs.flw-bnw.dev/change-a-team-members-role-on-an-entity-44488438e0.md): Update the role assigned to an existing entity access (team membership) record, replacing its permission set with the ACLs associated with the new role. Only identities with the can_change_entity_member_role permission (granted via the * wildcard or that specific ACL) on the entity may perform this action. The entity owner's access record cannot be modified through this endpoint. - Entity Access [Remove a member's access to an entity](https://core-service-docs.flw-bnw.dev/remove-a-members-access-to-an-entity-44488439e0.md): Permanently revokes a granted identity's access to an entity by deleting the corresponding entity-access record. Once removed, the identity that held this access record can no longer act on the entity under the permissions it granted, and this action cannot be undone. - Entity Access [List an entity's team members](https://core-service-docs.flw-bnw.dev/list-an-entitys-team-members-44488440e0.md): Returns the members (identities) that have been granted access to a given entity, including the entity's owner. Each item reports the member's identity details, whether they are the entity's owner, and their assigned role. - Entity Access Invites [Accept an entity access invitation](https://core-service-docs.flw-bnw.dev/accept-an-entity-access-invitation-44488441e0.md): Accepts a pending invitation to access an entity using the invitation token sent to the invitee's email address. On success, this grants the authenticated identity resource access to the entity with the role specified in the invitation, and marks the invitation as accepted. The identity is resolved from the authenticated session's token, not from the request body. The invitation's email must match the primary email of the authenticated identity, the invitation must still be pending and not expired, and the identity must not already have access to the entity, otherwise the request fails. - Entity Access Invites [Invite a new member to an entity](https://core-service-docs.flw-bnw.dev/invite-a-new-member-to-an-entity-44488442e0.md): Creates a pending invitation for someone to join an entity (business) with a specific role. The inviting identity must already have the can_invite_entity_member permission on the entity, granted via their assigned role. On success, an email notification carrying an accept-invite link is queued for delivery to the invitee; it is not sent synchronously. The invitation expires 24 hours after creation if not accepted. Only one pending invitation may exist per entity/email combination at a time, and an email that already has access to the entity cannot be re-invited. - Entity Access Invites [List entity access invites](https://core-service-docs.flw-bnw.dev/list-entity-access-invites-44488443e0.md): Returns a paginated list of pending and historical member invitations for an entity, sorted by creation date (newest first). - Entity Access Invites [Revoke an entity access invite](https://core-service-docs.flw-bnw.dev/revoke-an-entity-access-invite-44488444e0.md): Revokes a pending invitation to join an entity, preventing the invited email address from using it to accept access. The authenticated identity must have `can_invite_entity_member` or wildcard `*` ACL access on the entity that the invitation belongs to. - Entity Ownership Transfers [Transfer ownership of an entity](https://core-service-docs.flw-bnw.dev/transfer-ownership-of-an-entity-44488445e0.md): Transfers ownership of an entity from the authenticated identity to another identity that already has resource access to that entity. The authenticated identity must currently be the entity's owner; the new owner is identified by the id of their existing identity-resource-access record on the entity (not by their identity id), and they must not already be the owner. On success, the previous owner is demoted to the administrator role (retaining full administrative access) and the new owner's access record is promoted to owner with unrestricted permissions. Both updates happen atomically within a single database transaction — if either update fails, neither is applied. - Identity [Update the authenticated identity's name](https://core-service-docs.flw-bnw.dev/update-the-authenticated-identitys-name-44488446e0.md): Update the display name of the identity belonging to the caller of the request. The identity is never taken from a path or query parameter — it is always resolved from `identity_id` on the verified JWT, so a caller can only ever update their own identity. Only the `name` field is editable through this endpoint; any other property sent in the request body is ignored. The full, updated identity record is returned in the response. - Identity [Retrieve the authenticated identity](https://core-service-docs.flw-bnw.dev/retrieve-the-authenticated-identity-44488447e0.md): Fetch the identity record belonging to the caller of the request. The identity is never taken from a path or query parameter — it is always resolved from `identity_id` on the verified JWT, so a caller can only ever retrieve their own identity, never another identity's record by guessing an id. Use this to display account/profile details in a dashboard or to confirm the current lifecycle `status` of the signed-in identity. - Money Action Confirmations [Confirm a money-moving action with PIN (and, where required, an authenticator code)](https://core-service-docs.flw-bnw.dev/confirm-a-money-moving-action-with-pin-and-where-required-an-authenticator-code-44488448e0.md): Mint a single-use, short-lived confirmation that authorizes the authenticated identity to perform a specific money-moving action (e.g. approving a payout, deciding a maker-checker action, issuing a card). The `identity_id` and `entity_id` are always taken from the authenticated JWT session — they can never be supplied in the request body, even if included. The confirmation's required factor tier (`pin_only` or `pin_and_authenticator`) is resolved server-side per `action_type`, starting from a platform default and optionally overridden to something stricter (never weaker) at the entity level. A valid, active `secure-pin` MFA method is always required; when the resolved tier is `pin_and_authenticator`, an active `authenticator` MFA method and a valid `authenticator_code` are also required. Each PIN/authenticator verification is rate-limited independently — repeated failed attempts against the same MFA method within a rolling window return a `429` and block further attempts until the window clears. On success, the returned confirmation is valid for a fixed TTL (5 minutes by default, configurable via `MONEY_ACTION_CONFIRMATION_TTL_MS`) and can be consumed exactly once by including its `id` as `money_action_confirmation_id` on the action it was created for (e.g. `POST /payout-intents`, `PATCH /maker-checker-action-decisions/:id`). Passing `reference_id` binds the confirmation to a specific existing resource (e.g. a `payout_intent_id`) so it can only be consumed against that resource; omit it for actions that don't yet have a resource id at confirmation time (e.g. `payout`, `card_issuance`). - Payout Intent Action Returns [Record a payout intent action as returned](https://core-service-docs.flw-bnw.dev/record-a-payout-intent-action-as-returned-44488449e0.md): Marks a previously successful payout intent action as `returned` when the disbursed funds bounce back (e.g. an invalid destination bank account rejects the transfer). Only an action currently in the `successful` status is eligible; attempting this on an action in any other status fails with a `400` error. - Payout Intent Action Status Logs [List a payout intent action's status history](https://core-service-docs.flw-bnw.dev/list-a-payout-intent-actions-status-history-44488450e0.md): Returns a paginated, chronological (oldest first) timeline of status transitions recorded for a single payout intent action. Every time the action's status changes (for example when it moves from pending to processing, or is later returned), a status log entry is appended capturing the new status, an optional reason, and a snapshot of provider/system context at that step. Use this to audit or display the full lifecycle of a disbursement attempt. Pagination is cursor-based: pass the cursor value from the previous response's meta.pagination.cursor field to fetch the next page. When has_more is false, you have reached the end of the list. - Payout Intent Schedule Actions [Apply an action to a payout intent's schedule](https://core-service-docs.flw-bnw.dev/apply-an-action-to-a-payout-intents-schedule-44488451e0.md): Applies a `pause`, `resume`, or `skip-next` action to the active schedule on a `single` type payout intent, and returns the full, current representation of the intent afterward. The `entity_id` is always resolved from the authenticated caller and cannot be supplied in the request body. - Sandbox [Credit test money into an entity's sandbox wallet](https://core-service-docs.flw-bnw.dev/credit-test-money-into-an-entitys-sandbox-wallet-44488452e0.md): Live-server-facing endpoint that credits test money into the shadow (sandbox) version of one of your entities, so you can simulate having funds available without a real inflow. This endpoint resolves the target shadow entity from your entity_id (and optional sandbox_id), then proxies a single call to the sandbox server's test-money funding primitive using your identity's sandbox master key. No funding state is persisted on the live server — the sandbox server is the source of truth for the resulting balance, and the response body returned here is passed through verbatim from that call. - Sandbox [Reset a shadow entity's sandbox](https://core-service-docs.flw-bnw.dev/reset-a-shadow-entitys-sandbox-44488453e0.md): Deletes and re-provisions a fresh copy of a shadow entity on the sandbox server, while keeping the same dashboard card (`_id`, `name`, `is_default` are preserved). Use this when a sandbox entity has drifted or you simply want a clean slate for testing. - Sandbox [Get or create the sandbox identity for the authenticated identity](https://core-service-docs.flw-bnw.dev/get-or-create-the-sandbox-identity-for-the-authenticated-identity-44488454e0.md): Ensures the currently authenticated identity has a linked sandbox identity and master sandbox API key pair, creating them if they do not already exist. - Sandbox [Provision a sandbox identity and master API key](https://core-service-docs.flw-bnw.dev/provision-a-sandbox-identity-and-master-api-key-44488455e0.md): Creates a shadow sandbox identity, a dummy password-based auth credential, and a sandbox master API key pair on behalf of a real (live) identity that just registered on the live server. This endpoint is called server-to-server by the live server's own provisioning job immediately after a live identity is created — it is not called directly by end users or client applications. - Sandbox [Exchange the sandbox master API key for a login session](https://core-service-docs.flw-bnw.dev/exchange-the-sandbox-master-api-key-for-a-login-session-44488456e0.md): Creates a normal identity login session from the sandbox master API key, letting integrators simulate a logged-in user without going through the full authentication flow. This endpoint only works on a server running in sandbox mode, and only when the request is authenticated with the sandbox's designated master secret API key — any other secret key is rejected. The request takes no body; the caller's identity, IP address, and user agent are all derived server-side from the authenticated request context. The returned session behaves exactly like a session created via the normal login endpoint and can be used to sign subsequent JWT-authenticated requests. - Sandbox [Fund an entity's test wallet with sandbox test money](https://core-service-docs.flw-bnw.dev/fund-an-entitys-test-wallet-with-sandbox-test-money-44488457e0.md): Credits an entity's sandbox test wallet in a given currency, so you can simulate having funds available without a real inflow. This endpoint only exists on sandbox servers — it always fails with a 500 error on the live server. The caller's secret API key carries no entity_id of its own (the sandbox master key is shared across entities), so entity_id is supplied in the request body and ownership is verified explicitly: the authenticated identity must have can_edit_entity (or wildcard) access on the target entity. On first use for a given currency, a dedicated 'Sandbox Test Wallet' account is created for the entity if one does not already exist (identified by the client_reference sandbox-test-wallet-{currency}); on subsequent calls the existing wallet is reused and simply credited again. The credit itself is posted as a ledger transfer from an internal SandboxTestMoneyFaucet account, which must be pre-configured on the enabled currency's system metadata — if it isn't, the request fails with a 500 error rather than partially crediting the wallet. Supplying client_reference makes the funding idempotent per entity: retrying with the same client_reference after a successful funding returns a 409 conflict instead of double-crediting the wallet. - Transactions [Retrieve a transaction](https://core-service-docs.flw-bnw.dev/retrieve-a-transaction-44488458e0.md): Fetches a single ledger transaction by its unique identifier. The transaction must belong to the authenticated entity — the entity_id from the bearer token is automatically applied as a scoping condition, so callers cannot retrieve transactions belonging to other entities. - Transactions [List transactions](https://core-service-docs.flw-bnw.dev/list-transactions-44488459e0.md): Returns a paginated list of ledger transactions belonging to the authenticated entity, ordered newest first. A transaction is the immutable ledger record created whenever money moves in or out of one of your accounts — for example a settled payment, a disbursed payout, a sandbox test-money credit, or an internal account transfer. Use the optional query parameters to filter by account, direction, business type, status, originating intent, free-text search, or a creation date range. Pagination is cursor-based: pass the cursor value from the previous response's meta.pagination.cursor field as the cursor query parameter to fetch the next page. When has_more is false, you have reached the end of the list. - Virtual Card Activity [List a virtual card's activity](https://core-service-docs.flw-bnw.dev/list-a-virtual-cards-activity-44488460e0.md): Returns a combined, paginated feed of activity for a single virtual card: successful transactions made on the card (funding, spend, refunds) interleaved with declined authorization attempts, ordered newest first by id. Use this to build a single activity/timeline view for a card instead of querying transactions and declines separately. Each entry carries an entry_type field ('transaction' or 'decline') that tells you which shape to expect. Pagination is cursor-based: pass the meta.pagination.cursor value from a response as the cursor query parameter to fetch the next page; meta.pagination.has_more is false once you've reached the end. - Virtual Card Sessions [Create a virtual card viewing session](https://core-service-docs.flw-bnw.dev/create-a-virtual-card-viewing-session-44488461e0.md): Issues a short-lived session token that grants temporary access to view a virtual card's sensitive details (e.g. full card number, CVV) through a dedicated viewing flow, without repeatedly exposing that data through the main card endpoints. The session expires 10 minutes after creation. Creation fails if the card is `pending-approval` or `terminated`. - Virtual Card Topups [Top up a virtual card](https://core-service-docs.flw-bnw.dev/top-up-a-virtual-card-44488462e0.md): Moves funds from the funding account backing a virtual card into that card's balance. The transfer is posted to the ledger synchronously — the account is debited, the card's `cached_balance` is incremented by `amount`, and a `successful` transaction record is created and returned — all within a single atomic operation. If the funding account does not have sufficient available balance to cover `amount`, the entire operation is rolled back and a `400` error is returned. - Virtual Card Transaction Callbacks [Handle an inbound virtual card transaction callback](https://core-service-docs.flw-bnw.dev/handle-an-inbound-virtual-card-transaction-callback-44488463e0.md): Receives a purchase/authorization callback from a card processor for a virtual card and decides whether to approve or decline it, then settles the outcome on the ledger. - Virtual Card Withdrawals [Withdraw funds from a virtual card](https://core-service-docs.flw-bnw.dev/withdraw-funds-from-a-virtual-card-44488464e0.md): Moves funds off a virtual card's balance and back onto the funding account backing it, posting a ledger transfer from the platform's card float account to that account and decrementing the card's cached balance by the withdrawn amount. A `successful` payout-intent-action and transaction record are created synchronously as part of the same operation — this endpoint has no `pending` or `pending-approval` outcome. ## Schemas - [ErrorResponse](https://core-service-docs.flw-bnw.dev/errorresponse-16885986d0.md): - [SuccessResponse](https://core-service-docs.flw-bnw.dev/successresponse-16885987d0.md): - [AccountBalance](https://core-service-docs.flw-bnw.dev/accountbalance-18003540d0.md): - [Account](https://core-service-docs.flw-bnw.dev/account-18003541d0.md):