Log in an end customer to a product
customer.login
Verifies an end customer's password against the company's own customer credentials and mints a session bound to the named Product. The lookup is by email within the company, so the same address at two companies is two unrelated customers by design. A customer with no enrollment in that Product cannot sign in to it, and a suspended or closed enrollment is refused; a pending one succeeds, because completing verification is something the customer does while signed in. The session token is a one-time secret surfaced only in this response, never in receipts or replays.
POST /v1/customer-identity/login
Principal public. Idempotency required. Environment either.
Input
| Field | In | Type | Description |
|---|---|---|---|
X-Hyperscale-Environment | header | sandbox | live | |
Idempotency-Key required | header | string | |
X-Hyperscale-Rehearsal | header | "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 required | body | string | The Product to sign in to. One credential spans the company; each session is minted for exactly one of its Products. |
email required | body | string | |
password required | body | string |
Request sample
curl --request POST 'https://hyperscale0.ai/v1/customer-identity/login' \
--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_riyadhresale01","email":"[email protected]","password":"correct-horse-battery"}'Errors
| Code | HTTP | Cause |
|---|---|---|
idempotency_conflict | 409 | The request reused an Idempotency-Key for a different logical mutation. |
idempotency_required | 400 | The operation is a mutation and Hyperscale requires a replay key before executing it. |
internal_error | 500 | Hyperscale hit an unexpected server-side condition and hid internal implementation details from this audience. |
invalid_request | 400 | The request does not match the API reference. |
not_found | 404 | No Hyperscale route matched the requested path and method. |
product_access_suspended | 403 | The Product is disabled or closed, so its credentials are suspended in every environment. |
product_activation_required | 403 | The live Product or required live capability is not active yet. |
rate_limited | 429 | The 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_large | 413 | The JSON request body exceeded Hyperscale's accepted payload size. |
resource_not_found | 404 | The requested resource does not exist in the credential's visible scope. |
state_conflict | 409 | The operation conflicts with the current durable state of the resource. |
state_constraint_failed | 422 | The request is syntactically valid but violates a business-state constraint. |
tenant_not_found | 404 | The credential resolved to a tenant Hyperscale cannot find. |
unauthorized | 403 | The request did not include a valid Hyperscale bearer credential for this environment. |
customer_access_required | 403 | The customer has no usable access to this Product. Moving money on a customer's Product account needs an `active` access. `customer.login` needs an access to exist. When an access exists but is not active, `details.customerAccessId` names it. |
customer_access_status_forbidden | 409 | The access is `suspended` or `closed`. Activation refuses both, and `customer.login` refuses both. On a login refusal `details.status` holds the status. |
customer_not_found | 404 | No customer with this `customerId` exists in the caller's company and environment. |
instrument_instance_not_found | 404 | No record of this instrument matches the `instanceId` in this Product, company and environment. `details.instrumentId` and `details.instrumentInstanceId` name what was looked up. |
invalid_credentials | 401 | Hyperscale 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. |
operation_not_finalized | 409 | The 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_not_found | 404 | No 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. |
tenant_status_forbidden | 409 | The company is suspended or closed, so every credential bound to it is refused, reads included. `details.tenantId` names the company. |