Docs Sign in Start building

Import customers from a CSV file

customer.import

Creates customers for one Product from a CSV file of at most 1,000 rows with the columns kind, display_name and country, the fields customer.create takes for the legal entity. A dry run comes first and is the default: it judges every row and creates nothing. With commit true every row becomes a customer as customer.create makes one, with its entity pending verification and pending access to the Product, in one operation; a file with any refused row creates none. Both answer a verdict file with one row per data row. The file carries no money: an amount, balance or account column refuses it, since accounts open and money moves only through the Product's program.

POST /v1/customers/import

Principal api_key. Idempotency required. Environment either.

Input

FieldInTypeDescription
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.
productId requiredbodystringHyperscale product ID
csv requiredbodystringThe customers as CSV, at most 512 KiB of UTF-8 and 1,000 data rows. The header names kind (person or organization), display_name (1 to 200 characters) and country (ISO 3166-1 alpha-2, such as SA); the delimiter is a comma, a semicolon or a tab. Any other column, an amount or a balance among them, refuses the file.
commitbodybooleanFalse when omitted, a dry run: judge every row and create nothing. Send true to create the customers, which refuses the whole file when any row is refused.

Output

FieldTypeDescription
tenantId requiredstringOrganization tenant ID
productId requiredstringHyperscale product ID
dryRun requiredboolean
rowCount requiredinteger
acceptedCount requiredinteger
refusedCount requiredinteger
createdCount requiredinteger
contentType required"text/csv"
filename requiredstring
content requiredstringThe verdict file: one CSV row per data row with row, verdict (accepted, created or refused), reason and customer_id. It names a row by its number and carries none of its cells, since the receipt keeps this output and a customer's name is stored only sealed.
sha256 requiredstringSHA-256 of content's UTF-8 bytes
sizeBytes requiredinteger
rows requiredobject[]

Request sample

curl

curl --request POST 'https://hyperscale0.ai/v1/customers/import' \
  --header "Authorization: Bearer $HYPERSCALE_API_KEY" \
  --header 'X-Hyperscale-Environment: sandbox' \
  --header "Idempotency-Key: $(uuidgen)" \
  --header 'Content-Type: application/json' \
  --data-raw '{"productId":"prd_sandbox_example0001","csv":"x"}'

TypeScript SDK

import { createClient } from "@hyperscale0/sdk";

const hs = createClient({
  apiKey: process.env.HYPERSCALE_API_KEY,
  productId: process.env.HYPERSCALE_PRODUCT_ID,
});
const result = await hs.call("customer.import", {
  "productId": "prd_sandbox_example0001",
  "csv": "x"
});

CLI

hyperscale api call customer.import \
  --input '{"productId":"prd_sandbox_example0001","csv":"x"}'

Errors

CodeHTTPCause
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_product_capability403The Product was created without a capability required by 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.
operation_not_allowed403The credential authenticated, but the operation is outside the allowlist its Product's composition produced. The message names the operation and the capability that would admit it.
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.
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.
customer_status_forbidden403The customer's status is not `active`. Creating a customer access, opening an account owned by the customer, and moving money on the customer's Product accounts all need an active customer.
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.
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.
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.
key_revoked401The Product API key exists, but it was revoked. `details.revokedAt` holds the date.
operation_environment_invalid400The operation does not run in the requested environment, or the request environment does not match the credential's environment. The message names the operation and the environment it refused. Sandbox funding, the sandbox clock and sandbox platform firing are sandbox-only. Product promotion is live-only.
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.
product_context_forbidden400`account.create` received a Product for a role that is not Product-scoped. The Product comes from `productId`, or from the API key's Product when `productId` is absent.
product_context_mismatch400The request names a Product that does not own the resource it acts on. A transfer's `productId` differs from the source account's Product, or `sandbox.clock.advance` names a Product other than the API key's Product.
product_context_owner_mismatch400`account.create` named a Product owner (`owner.type` is `product`) whose `owner.id` differs from the account's Product.
product_context_required400The account role is Product-scoped (`customer_balance`, `customer_investment`, `product_pool`, `product_credit`, `product_revenue` and others), but the request or the stored account carries no Product.
product_not_found404No Product matches the `productId` in this tenant and environment, or a resource the request names belongs to a different Product than the API key's. A missing, foreign or ambiguous resource binding also reports this code.
product_scope_required400The API key carries no Product binding, so Hyperscale cannot decide which Product the request reads. On hosted MCP, the capability query did not match exactly one Product.
product_scope_unsupported400A Product API key requested a resource that has no Product-scoped read model, so Hyperscale cannot limit the read to the key's Product. The message names the resource.
product_status_forbidden403The Product is not active. Account operations need an `active` Product. Promotion refuses when the sandbox Product or its live counterpart is `disabled` or `closed`.
provider_credential_missing409A live Product calls a provider adapter that declares a live credential, and the calling tenant has no active credential of that name. The details name the adapter, the credential and its kind. No provider call was made.
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