# Reopen a closed month

`company.close.reopen`

Sets the month's close aside, so the month is open again: a sandbox operation may post into it, and company.close.create closes it again as the next version. The set-aside close stays stored and readable by id; company.close.list shows the current one, and every set-aside version with includeSuperseded. The next close's evidence file names the file exported from this one as predecessor. Every current close of a later month is marked restsOnReopened with this month, since its totals may rest on the version set aside; list, retrieve and the month's evidence file show the mark. A later month closed again while this month stands reopened carries the mark on its new version from create; closed again after this month closes again, it stands clear. Only the company owner may ask for a reopen (company_owner_required), and a month with no close refuses with resource_not_found. The call answers approval_required with the approval pending: a second administrator who holds desk.settings.manage across every Product, not the owner, decides it with approval.decide, and the owner's own decision refuses approval_decider_refused. The approve runs this call again and only that run sets the close aside; the audit row reporting.company_close.reopened names the approval and the decider beside the reason. The approval lapses after 24 hours.

Callers: the account owner's own CLI login (`hyperscale auth login`). An agent token is refused.

`POST /v1/company-closes/reopen`

Principal `user_session`. 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. |
| `tenantId` required | body | `string` | Organization tenant ID |
| `period` required | body | `string` | The closed UTC month to reopen. |
| `reason` required | body | `string` | Why the month reopens. The audit row keeps it. |

## Output

| Field | Type | Description |
| --- | --- | --- |
| `tenantId` required | `string` | Organization tenant ID |
| `period` required | `string` | UTC calendar month in YYYY-MM form |
| `reportingArtifactId` required | `string` | The close the reopen set aside. |
| `version` required | `integer` | That close's version. |
| `digest` required | `string` | That close's document digest. |
| `reason` required | `string` |  |
| `reopenedBy` required | `string` | Your user id. |
| `approvalId` required | `string` | The approval a second administrator decided before the month reopened. |
| `decidedBy` required | `string` | The second administrator who approved the reopen. |
| `marked` required | `string[]` | The later months whose current close this reopen marked restsOnReopened, oldest first. A close an earlier reopen already marked keeps its mark. |

## Request sample

Only a signed-in person may call this: the founder's own CLI after hyperscale auth login. A Product key cannot, so the SDK, which signs in with a Product key or a customer session, has no sample for it.

### curl

```shell
curl --request POST 'https://hyperscale0.ai/v1/company-closes/reopen' \
  --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","period":"2026-01","reason":"Customer requested this lifecycle change."}'
```

### CLI

```shell
hyperscale api call company.close.reopen \
  --input '{"tenantId":"ten_sandbox_example0001","period":"2026-01","reason":"Customer requested this lifecycle change."}'
```

## Errors

| Code | HTTP | Cause |
| --- | --- | --- |
| `csrf_token_invalid` | 403 | A browser session mutation did not carry a current Hyperscale CSRF token. |
| `environment_mismatch` | 403 | The session was issued for sandbox or live and the request targets the other environment. |
| `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. |
| `method_not_allowed` | 405 | The route exists, but not for the request's HTTP method. |
| `missing_required_permission` | 403 | The signed-in member's current role does not grant the permission required for this operation. |
| `missing_required_scope` | 403 | The credential is valid but does not grant one or more operation scopes. |
| `not_found` | 404 | No Hyperscale route matched the requested path and method. |
| `oauth_client_not_admitted` | 403 | The bearer is an OAuth client token, and this operation does not admit the oauth2_client principal. |
| `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_mismatch` | 403 | The request mixed tenant-owned identifiers across tenant boundaries. |
| `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. |
| `upgrading` | 503 | The box is installing a release and replays its stored Cores on it first, for up to 300 seconds. Writes wait for the replay, so a release it refuses rolls back with nothing written. |
| `agent_token_expired` | 401 | The 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_replaced` | 401 | The 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. |
| `company_owner_required` | 403 | The full evidence file carries the names of the company's counterparties, a reopen sets a closed month aside, and a recipient receives every closed month. Your role in the company is not owner. Nothing was exported or changed. |
| `device_login_expired` | 401 | The 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_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. |
| `reporting_artifact_refused` | 422 | The capture could not be complete: an operation in the company is still unresolved, or the result passes the row limit. |
| `reporting_period_invalid` | 422 | The report period is not a pair of valid times, or it ends at or before it starts. |
| `session_expired` | 401 | The 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_required` | 401 | This 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_revoked` | 401 | The 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_forbidden` | 409 | The company is suspended or closed, so every credential bound to it is refused, reads included. `details.tenantId` names the company. |

[All operations](/docs/operations/index.md)

For agents: [OpenAPI document](https://hyperscale0.ai/openapi.json) · [MCP manifest](https://hyperscale0.ai/.well-known/mcp.json) · [HTTP API guide](https://hyperscale0.ai/docs/api.md) · [MCP guide](https://hyperscale0.ai/docs/mcp.md)
