Docs Sign in Start building

Fetch a day's bank statement and import it

bank_statement.fetch_and_import

Asks the bank that mirrors the account for one finished day's statement, as bank_account.read does in statement mode, and imports the document it answers in the same operation, as bank_statement.import does: camt.053 or MT940 when the bank sends one, else the bank's JSON statement. The answer is stored as a receipt either way. A refused read or a day with no booked line imports nothing. A person's fetch books a pool's bank charges as the import does; the boundary worker's scheduled daily fetch, bank_statement.daily_fetch, posts nothing and leaves a pool's statement that carries charges for a person to import. The same document fetched again returns the statement imported before. Callers: the account owner's CLI login, or an agent token with products:write whose grant spans every Product (`hyperscale agent setup --all-products`), or a personal access token with finance:write. A grant on some Products is refused: this reaches all of them.

POST /v1/bank-accounts/{accountId}/statement-import

Principal user_session. Idempotency required. Environment either.

Input

FieldInTypeDescription
accountId requiredpathstringHyperscale account ID
X-Hyperscale-Environmentheadersandbox | live
Idempotency-Key requiredheaderstring
X-Hyperscale-Rehearsalheader"true"`true` runs the request through admission and execution, keeps nothing, and answers OperationRehearsal with 200 in place of the operation's own output. Needs a signed-in caller. Identity operations, such as sign-in, sessions, team members and agent grants, refuse it with invalid_request.
tenantId requiredbodystringOrganization tenant ID
date requiredbodystringThe finished bank day whose statement to fetch.

Output

FieldTypeDescription
accountId requiredstringHyperscale account ID
date requiredstring
adapter requiredstringThe bank adapter that mirrors the account.
outcome requiredconfirmed | rejectedRejected when the bank refused the statement read.
providerCode requiredstring | null
reasonCode requiredstring | null
externalConfirmationId requiredstringThe receipt that stores the bank's answer.
format requiredcamt053 | csv | json | mt940 | mt942 | nullThe format of the bank's document; null when the bank refused or the day booked no line, and set on a pool statement the daily fetch left for a person, which it did not import.
statement requiredobject | nullThe import's answer, as bank_statement.import returns it; null when the bank refused, when the day booked no line, or when the daily fetch left a pool's statement with bank charges for a person.
chargesBooked requiredbooleanFalse on the scheduled daily fetch, which posts nothing.
deferredChargeLines requiredintegerThe bank-charge lines on a pool's statement that the scheduled daily fetch left for a person: it stores no such statement, so bank_statement.fetch_and_import or bank_statement.import of the same day books the charges. 0 otherwise.

Request sample

Only a signed-in person may call this: the CLI after hyperscale auth login, or curl with a personal access token (hyperscale_pat_...) with finance:write or an agent token with products:write. The agent's grant must span every Product the call reads. A Product key cannot, so the SDK, which signs in with a Product key or a customer session, has no sample for it.

curl

curl --request POST 'https://hyperscale0.ai/v1/bank-accounts/acct_sandbox_example0001/statement-import' \
  --header "Authorization: Bearer $HYPERSCALE_TOKEN" \
  --header 'X-Hyperscale-Environment: sandbox' \
  --header "Idempotency-Key: $(uuidgen)" \
  --header 'Content-Type: application/json' \
  --data-raw '{"tenantId":"ten_sandbox_example0001","date":"2026-01-01"}'

CLI

hyperscale api call bank_statement.fetch_and_import \
  --input '{"accountId":"acct_sandbox_example0001","tenantId":"ten_sandbox_example0001","date":"2026-01-01"}'

Errors

CodeHTTPCause
agent_cap_exceeded202A capped agent's call would move more than its grant allows per operation, per rolling day or per rolling 30 days.
agent_reason_required400An agent sent a change without saying why, or the reason is shorter than 8 or longer than 280 characters.
agent_result_already_delivered409A caller already claimed this approval's one-time result.
approval_rejected403A person rejected the call or returned it to the maker, so it never runs.
approval_required202The call waits for decisions: an agent's call over its grant waits on its delegator, and a program action under `requires approval` waits on distinct people other than the maker.
csrf_token_invalid403A browser session mutation did not carry a current Hyperscale CSRF token.
environment_mismatch403The session was issued for sandbox or live and the request targets the other environment.
idempotency_conflict409The request reused an Idempotency-Key for a different logical mutation.
idempotency_required400The operation is a mutation and Hyperscale requires a replay key before executing it.
internal_error500Hyperscale hit an unexpected server-side condition and hid internal implementation details from this audience.
invalid_request400The request does not match the API reference.
method_not_allowed405The route exists, but not for the request's HTTP method.
missing_required_permission403The signed-in member's current role does not grant the permission required for this operation.
missing_required_scope403The credential is valid but does not grant one or more operation scopes.
not_found404No Hyperscale route matched the requested path and method.
oauth_client_not_admitted403The bearer is an OAuth client token, and this operation does not admit the oauth2_client principal.
product_access_suspended403The Product is disabled or closed, so its credentials are suspended in every environment.
product_activation_required403The live Product or required live capability is not active yet.
rate_limited429The credential sent more than its limit in the current 60-second window: 600 requests per API key or session, 1,200 per IP address. Every response carries `x-ratelimit-limit`, `x-ratelimit-remaining` and `x-ratelimit-reset` (Unix seconds).
request_body_too_large413The JSON request body exceeded Hyperscale's accepted payload size.
resource_not_found404The requested resource does not exist in the credential's visible scope.
state_conflict409The operation conflicts with the current durable state of the resource.
state_constraint_failed422The request is syntactically valid but violates a business-state constraint.
tenant_mismatch403The request mixed tenant-owned identifiers across tenant boundaries.
tenant_not_found404The credential resolved to a tenant Hyperscale cannot find.
unauthorized403The request did not include a valid Hyperscale bearer credential for this environment.
account_not_found404No account with the id this request names exists in the caller's tenant and environment. The id comes from `accountId`, `destinationAccountId` or `entityAccountId`, depending on the operation.
agent_token_expired401The agent token is real, but its grant ended. A grant lasts 30 days, or 7 days unused. `details.expiresAt` holds the date in ISO 8601 and `details.agentName` names the agent.
agent_token_replaced401The account owner ran `hyperscale agent setup` again for this agent, which replaced this token with a newer one. `details.agentName` names the agent and `details.replacedAt` holds the date.
bank_statement_invalid422The document is over 512 KiB of UTF-8, or is not a camt.053 statement with one Stmt and booked entries, or not a CSV whose header names date, amount and currency with one well-formed row per line. Nothing was stored.
company_period_closed409The company already closed this period in this environment. A period closes once and the close never changes. In sandbox a money operation dated by its Product clock inside a closed month refuses too, so the close's VAT return and journal stay whole; `details.period` names the month.
cross_tenant_transfer_forbidden409An account on this transfer belongs to another tenant, or it has no tenant and is not a platform account. `details.accountId` names it. No intent or ledger effect was created.
currency_mismatch400The currency on the request does not match the settlement currency of the account or transfer it targets. Hyperscale never converts between currencies, so the two must be identical.
device_login_expired401The bearer is the account owner's own device login from `hyperscale auth login`, not an agent token. Its access token lasts an hour and the CLI refreshes it; the login itself ends after 30 days, or 7 days unused. `details.expiresAt` holds when it ended in ISO 8601.
external_confirmation_conflict409This tenant and environment already recorded the provider reference in `details.provider` and `details.providerReference` against a different operation, resource or body. A provider observation that does not match its boundary instruction, or an instruction that changed during recovery, also raises this code.
instrument_instance_not_found404No record of this instrument matches the `instanceId` in this Product, company and environment. `details.instrumentId` and `details.instrumentInstanceId` name what was looked up.
insufficient_balance409The source (debit) account's available balance is below the transfer amount, so the ledger refused the transfer. No money moved. The transfer was not created and its charge/transfer rows are recorded as failed.
invalid_credentials401Hyperscale could not accept the account or credential request. Signup, login, and bearer authentication use one 401 for every case they reject, so the response exposes no credential-specific reason or registered-email verdict. The single exception is a key that is real but homed in the other environment: because the presented secret already matched a stored key, the message names the mismatch instead of leaving a working credential looking unknown. A bearer that matched nothing gets text that fits its prefix (an agent token, a refresh token, a personal access token, a session or no Hyperscale token at all), which says only what the caller sent, never whether a credential like it exists.
ledger_transfer_rejected409The ledger refused the transfer for a reason other than insufficient balance. No money moved. `details` carries `transferId`, the debit-side `accountId`, `amount` and `currency`. The ledger's own reason stays in the server log.
ledger_unavailable503The ledger could not be reached, did not answer in time, or returned incomplete evidence for the accounts this request reads. `details.reason` is `request_timeout` when the call timed out.
operation_not_finalized409The operation in `details.operationId` has started but has no final receipt. It is still running, or its outcome is unknown after a failure past the point where it may have committed. `details.error` carries the underlying failure when there is one.
provider_egress_failed502The call to the bank or provider failed in transit, or the bank has no adapter or no final answer for the read. Nothing was imported, and a money hold stays held until the same key runs again.
session_expired401The session behind this request has ended. A console session ends 30 days after sign-in, or after 12 hours with no request. An admin or customer session ends 24 hours after sign-in, or after 15 minutes with no request. A personal access token ends at the `expiresAt` set when it was created.
session_required401This operation needs a person signed in through the browser or the `hyperscale` CLI. A Product API key cannot call it. The request carried no session, or its token matched no live session.
session_revoked401The session or personal access token behind this request was ended before its expiry. Sign-out, `user.session.revoke`, a password reset, a role change, removal from the team, user suspension and `personal_access_token.revoke` all end sessions.
tenant_status_forbidden409The company is suspended or closed, so every credential bound to it is refused, reads included. `details.tenantId` names the company.

All operations