curl --request POST \
--url https://api.arcuserp.com/v1/periods/{id}/reopen \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"reason": "Q1 inventory recon required reposting of adjusting JE for COGS reclass.",
"acknowledge_old_period": false,
"sod_override_authorized_by": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
'import requests
url = "https://api.arcuserp.com/v1/periods/{id}/reopen"
payload = {
"reason": "Q1 inventory recon required reposting of adjusting JE for COGS reclass.",
"acknowledge_old_period": False,
"sod_override_authorized_by": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
reason: 'Q1 inventory recon required reposting of adjusting JE for COGS reclass.',
acknowledge_old_period: false,
sod_override_authorized_by: '3c90c3cc-0d44-4b50-8888-8dd25736052a'
})
};
fetch('https://api.arcuserp.com/v1/periods/{id}/reopen', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.arcuserp.com/v1/periods/{id}/reopen",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'reason' => 'Q1 inventory recon required reposting of adjusting JE for COGS reclass.',
'acknowledge_old_period' => false,
'sod_override_authorized_by' => '3c90c3cc-0d44-4b50-8888-8dd25736052a'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.arcuserp.com/v1/periods/{id}/reopen"
payload := strings.NewReader("{\n \"reason\": \"Q1 inventory recon required reposting of adjusting JE for COGS reclass.\",\n \"acknowledge_old_period\": false,\n \"sod_override_authorized_by\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.arcuserp.com/v1/periods/{id}/reopen")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"reason\": \"Q1 inventory recon required reposting of adjusting JE for COGS reclass.\",\n \"acknowledge_old_period\": false,\n \"sod_override_authorized_by\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.arcuserp.com/v1/periods/{id}/reopen")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"reason\": \"Q1 inventory recon required reposting of adjusting JE for COGS reclass.\",\n \"acknowledge_old_period\": false,\n \"sod_override_authorized_by\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"entity_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"period_name": "<string>",
"start_date": "2023-12-25",
"end_date": "2023-12-25",
"status": "open",
"closed_by": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"closed_at": "2023-11-07T05:31:56Z",
"close_requested_by": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"close_requested_at": "2023-11-07T05:31:56Z",
"close_approved_by": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"close_approved_at": "2023-11-07T05:31:56Z",
"reopen_reason": "<string>",
"reopened_by": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reopened_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}Reopen a closed accounting period
Reopens a closed accounting period so journal entries can again post with dates inside it, requiring a reason of 10 to 500 characters and, for a period that ended more than 180 days ago, acknowledge_old_period: true. Requires accounting:close_period scope; the caller cannot be the user who requested or approved the original close.
curl --request POST \
--url https://api.arcuserp.com/v1/periods/{id}/reopen \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"reason": "Q1 inventory recon required reposting of adjusting JE for COGS reclass.",
"acknowledge_old_period": false,
"sod_override_authorized_by": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
'import requests
url = "https://api.arcuserp.com/v1/periods/{id}/reopen"
payload = {
"reason": "Q1 inventory recon required reposting of adjusting JE for COGS reclass.",
"acknowledge_old_period": False,
"sod_override_authorized_by": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
reason: 'Q1 inventory recon required reposting of adjusting JE for COGS reclass.',
acknowledge_old_period: false,
sod_override_authorized_by: '3c90c3cc-0d44-4b50-8888-8dd25736052a'
})
};
fetch('https://api.arcuserp.com/v1/periods/{id}/reopen', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.arcuserp.com/v1/periods/{id}/reopen",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'reason' => 'Q1 inventory recon required reposting of adjusting JE for COGS reclass.',
'acknowledge_old_period' => false,
'sod_override_authorized_by' => '3c90c3cc-0d44-4b50-8888-8dd25736052a'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.arcuserp.com/v1/periods/{id}/reopen"
payload := strings.NewReader("{\n \"reason\": \"Q1 inventory recon required reposting of adjusting JE for COGS reclass.\",\n \"acknowledge_old_period\": false,\n \"sod_override_authorized_by\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.arcuserp.com/v1/periods/{id}/reopen")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"reason\": \"Q1 inventory recon required reposting of adjusting JE for COGS reclass.\",\n \"acknowledge_old_period\": false,\n \"sod_override_authorized_by\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.arcuserp.com/v1/periods/{id}/reopen")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"reason\": \"Q1 inventory recon required reposting of adjusting JE for COGS reclass.\",\n \"acknowledge_old_period\": false,\n \"sod_override_authorized_by\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"entity_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"period_name": "<string>",
"start_date": "2023-12-25",
"end_date": "2023-12-25",
"status": "open",
"closed_by": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"closed_at": "2023-11-07T05:31:56Z",
"close_requested_by": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"close_requested_at": "2023-11-07T05:31:56Z",
"close_approved_by": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"close_approved_at": "2023-11-07T05:31:56Z",
"reopen_reason": "<string>",
"reopened_by": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"reopened_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": "expand[0]",
"required": "accounts:read",
"request_id": "req_abc123"
}Authorizations
API key issued per entity via Settings > Developers > API Keys.
Each key carries scopes (e.g. orders:read, products:write).
Bearer token format: Authorization: Bearer ark_live_ent_Test keys use ark_test_ent_. Both are issued per entity
via Settings > Developers > API Keys.
Path Parameters
Body
Operator-supplied justification (SOX-grade audit trail; required). 10-500 chars.
10 - 500"Q1 inventory recon required reposting of adjusting JE for COGS reclass."
Required true when the period ended more than 180 days ago. Defaults false.
The user id of the person who AUTHORIZED an override of guard 5 (Segregation of Duties). Supply it when the caller is the same human who requested or approved the original close and no second party is available. The ACTING user is unchanged and every audit row still names the human who performed the reopen; this field names who authorized it. Validated FAIL-CLOSED against a live ACTIVE membership on THIS entity carrying accounting.close_period, so a viewer cannot authorize and a member of another entity cannot (Layer 1); anything unresolvable is a refusal, never a silent downgrade to "no override". The authorizer MAY be the acting user, which is deliberate: a single-owner entity has no second party to offer, and a guard that can only be satisfied by naming someone who authorized nothing would force a false audit row. Every use writes a PERIOD_REOPEN_SOD_OVERRIDDEN activity row beside the ordinary PERIOD_REOPENED one and stamps the override into the persisted reopen_reason. Omit it and the 403 sod_self_reopen_forbidden envelope is byte-identical to the one shipped before this field existed, so no existing caller changes.
Response
Period reopened
An accounting period. Closed periods refuse new journal entry postings (Rule A3). Year-end closing entries that roll revenue and expense activity into retained earnings are posted via a separate explicit endpoint (POST /v1/accounting_periods/{id}/close-fiscal-year). The monthly-period close does NOT by itself post a retained-earnings rollover JE. Verified against live dev RDS accounting.accounting_periods.
Human-readable name (e.g. 'January 2025')
open, close_requested, closed NEW-GAP-REOPEN-PERIOD-ENTITY-ISOLATION-SOD-REASON-AUDIT (2026-05-15): operator-supplied justification from the most recent reopen. 10-500 chars when set. Cleared on next close.
User who most recently reopened this period.
Was this page helpful?

