Authentication and keys
ScriptHaul accounts are verified email addresses. Codes last 10 minutes; five wrong attempts lock that code for 15 minutes. Addresses are normalized before uniqueness checks.
Bearer only
Send keys only in the Authorization header.
Authorization: Bearer sh_live_…
Keys in api_key, key, token, or similar query parameters are rejected. ScriptHaul stores only a peppered SHA-256 key hash and a 12-character display prefix.
List and create keys
curl https://api.scripthaul.com/v1/keys \
-H "Authorization: Bearer $SCRIPTHAUL_API_KEY"
curl https://api.scripthaul.com/v1/keys \
-X POST \
-H "Authorization: Bearer $SCRIPTHAUL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Production","daily_credit_cap":250}'
Free accounts may hold 2 live keys; paid accounts may hold 5. daily_credit_cap is an optional customer-controlled kill switch.
Revoke or rotate
curl https://api.scripthaul.com/v1/keys/KEY_ID \
-X DELETE \
-H "Authorization: Bearer $SCRIPTHAUL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"grace_period_hours":0}'
curl https://api.scripthaul.com/v1/keys/KEY_ID/rotate \
-X POST \
-H "Authorization: Bearer $SCRIPTHAUL_API_KEY" \
-H "Content-Type: application/json" \
-d '{}'
Rotation creates a new key and gives the old key a 24-hour grace period. Immediate revocation uses 0; scheduled revocation uses 24. Authentication lookups are memoized for up to 30 seconds, so an immediately revoked key may continue to authenticate for at most that documented cache window.
Dashboard sessions
The dashboard uses an HttpOnly, Secure, SameSite=Strict cookie. It is accepted only on dashboard-safe account, key, usage, job-read, and checkout routes. It never authenticates transcript delivery or MCP calls. Cookie-authenticated mutations require X-ScriptHaul-Dashboard: 1.
List keys in four languages
These requests keep the credential in the header. Maintained runnable versions are in the examples directory.
curl https://api.scripthaul.com/v1/keys \
-H "Authorization: Bearer $SCRIPTHAUL_API_KEY"
import os, urllib.request
request = urllib.request.Request("https://api.scripthaul.com/v1/keys")
request.add_header("Authorization", f"Bearer {os.environ['SCRIPTHAUL_API_KEY']}")
print(urllib.request.urlopen(request).read().decode())
const response = await fetch("https://api.scripthaul.com/v1/keys", {
headers: { Authorization: `Bearer ${process.env.SCRIPTHAUL_API_KEY}` },
});
console.log(await response.json());
req, _ := http.NewRequest("GET", "https://api.scripthaul.com/v1/keys", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("SCRIPTHAUL_API_KEY"))
response, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer response.Body.Close()
io.Copy(os.Stdout, response.Body)