For AI agents: a documentation index is available at https://developers.jarsave.com/llms.txt, this page as Markdown at https://developers.jarsave.com/test-helpers.md, and the OpenAPI description at https://developers.jarsave.com/openapi.json.
The sandbox flow
SandboxIn the sandbox, the test helpers play the parent, so you or your AI assistant can run the whole flow from code: make a link code, create the link, confirm it, then send items. They work with a sandbox key only; a live key gets 400.
The dashboard's Make a test link code and Confirm as parent buttons do the same.
Sandbox flow
# 1. A code, as a parent makes it in JarSave
POST /v1/test_helpers/link_codes
# 2. The link, with that code
POST /v1/links
# 3. The parent confirms it
POST /v1/test_helpers/links/:id/confirm
# 4. Items arrive
POST /v1/links/:id/certificatesMake a link code
POST /v1/test_helpers/link_codes
Makes a one-time link code for a test student, as a parent does in JarSave. It works once, for 24 hours.
Returns
A link code object with the code to create a link with and its expires_at.
Request
curl -X POST https://api.jarsave.com/v1/test_helpers/link_codes \
-H "Authorization: Bearer $JARSAVE_SECRET_KEY" \
-H "JarSave-Version: 2026-10-29"use Illuminate\Support\Facades\Http;
// config/services.php: 'jarsave' => ['key' => env('JARSAVE_SECRET_KEY')]
$response = Http::withToken(config('services.jarsave.key'))
->withHeaders(['JarSave-Version' => '2026-10-29'])
->post('https://api.jarsave.com/v1/test_helpers/link_codes');const response = await fetch("https://api.jarsave.com/v1/test_helpers/link_codes", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.JARSAVE_SECRET_KEY}`,
"JarSave-Version": "2026-10-29",
},
});
const result = await response.json();import os
import requests
response = requests.post(
"https://api.jarsave.com/v1/test_helpers/link_codes",
headers={
"Authorization": f"Bearer {os.environ['JARSAVE_SECRET_KEY']}",
"JarSave-Version": "2026-10-29",
},
timeout=30,
)
result = response.json()Response
{
"object": "link_code",
"code": "K7PM-Q2XD",
"expires_at": "2026-11-21T15:04:11+07:00"
}Confirm a link
POST /v1/test_helpers/links/:id/confirm
Confirms a pending sandbox link as the parent does, so the items you send to it are accepted. Confirming an active link again changes nothing.
Returns
The link object, with status active. A revoked link returns 410.
Request
curl -X POST https://api.jarsave.com/v1/test_helpers/links/lnk_8Gm2QxT4/confirm \
-H "Authorization: Bearer $JARSAVE_SECRET_KEY" \
-H "JarSave-Version: 2026-10-29"use Illuminate\Support\Facades\Http;
// config/services.php: 'jarsave' => ['key' => env('JARSAVE_SECRET_KEY')]
$response = Http::withToken(config('services.jarsave.key'))
->withHeaders(['JarSave-Version' => '2026-10-29'])
->post('https://api.jarsave.com/v1/test_helpers/links/lnk_8Gm2QxT4/confirm');const response = await fetch("https://api.jarsave.com/v1/test_helpers/links/lnk_8Gm2QxT4/confirm", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.JARSAVE_SECRET_KEY}`,
"JarSave-Version": "2026-10-29",
},
});
const result = await response.json();import os
import requests
response = requests.post(
"https://api.jarsave.com/v1/test_helpers/links/lnk_8Gm2QxT4/confirm",
headers={
"Authorization": f"Bearer {os.environ['JARSAVE_SECRET_KEY']}",
"JarSave-Version": "2026-10-29",
},
timeout=30,
)
result = response.json()