curl --request POST \
--url https://api.scrip.dev/v1/groups/{id}/balances/release \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"asset_id": "550e8400-e29b-41d4-a716-446655440001",
"description": "Order #123",
"program_id": "550e8400-e29b-41d4-a716-446655440000",
"amount": "100.00",
"bucket": "AVAILABLE",
"earned_from": "2024-01-01T00:00:00Z",
"earned_to": "2024-12-31T23:59:59Z",
"idempotency_key": "order-123",
"lot_ids": [
"550e8400-e29b-41d4-a716-446655440002"
],
"reference_id": "auth_12345"
}
'import requests
url = "https://api.scrip.dev/v1/groups/{id}/balances/release"
payload = {
"asset_id": "550e8400-e29b-41d4-a716-446655440001",
"description": "Order #123",
"program_id": "550e8400-e29b-41d4-a716-446655440000",
"amount": "100.00",
"bucket": "AVAILABLE",
"earned_from": "2024-01-01T00:00:00Z",
"earned_to": "2024-12-31T23:59:59Z",
"idempotency_key": "order-123",
"lot_ids": ["550e8400-e29b-41d4-a716-446655440002"],
"reference_id": "auth_12345"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
asset_id: '550e8400-e29b-41d4-a716-446655440001',
description: 'Order #123',
program_id: '550e8400-e29b-41d4-a716-446655440000',
amount: '100.00',
bucket: 'AVAILABLE',
earned_from: '2024-01-01T00:00:00Z',
earned_to: '2024-12-31T23:59:59Z',
idempotency_key: 'order-123',
lot_ids: ['550e8400-e29b-41d4-a716-446655440002'],
reference_id: 'auth_12345'
})
};
fetch('https://api.scrip.dev/v1/groups/{id}/balances/release', 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.scrip.dev/v1/groups/{id}/balances/release",
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([
'asset_id' => '550e8400-e29b-41d4-a716-446655440001',
'description' => 'Order #123',
'program_id' => '550e8400-e29b-41d4-a716-446655440000',
'amount' => '100.00',
'bucket' => 'AVAILABLE',
'earned_from' => '2024-01-01T00:00:00Z',
'earned_to' => '2024-12-31T23:59:59Z',
'idempotency_key' => 'order-123',
'lot_ids' => [
'550e8400-e29b-41d4-a716-446655440002'
],
'reference_id' => 'auth_12345'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$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.scrip.dev/v1/groups/{id}/balances/release"
payload := strings.NewReader("{\n \"asset_id\": \"550e8400-e29b-41d4-a716-446655440001\",\n \"description\": \"Order #123\",\n \"program_id\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"amount\": \"100.00\",\n \"bucket\": \"AVAILABLE\",\n \"earned_from\": \"2024-01-01T00:00:00Z\",\n \"earned_to\": \"2024-12-31T23:59:59Z\",\n \"idempotency_key\": \"order-123\",\n \"lot_ids\": [\n \"550e8400-e29b-41d4-a716-446655440002\"\n ],\n \"reference_id\": \"auth_12345\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
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.scrip.dev/v1/groups/{id}/balances/release")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"asset_id\": \"550e8400-e29b-41d4-a716-446655440001\",\n \"description\": \"Order #123\",\n \"program_id\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"amount\": \"100.00\",\n \"bucket\": \"AVAILABLE\",\n \"earned_from\": \"2024-01-01T00:00:00Z\",\n \"earned_to\": \"2024-12-31T23:59:59Z\",\n \"idempotency_key\": \"order-123\",\n \"lot_ids\": [\n \"550e8400-e29b-41d4-a716-446655440002\"\n ],\n \"reference_id\": \"auth_12345\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.scrip.dev/v1/groups/{id}/balances/release")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"asset_id\": \"550e8400-e29b-41d4-a716-446655440001\",\n \"description\": \"Order #123\",\n \"program_id\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"amount\": \"100.00\",\n \"bucket\": \"AVAILABLE\",\n \"earned_from\": \"2024-01-01T00:00:00Z\",\n \"earned_to\": \"2024-12-31T23:59:59Z\",\n \"idempotency_key\": \"order-123\",\n \"lot_ids\": [\n \"550e8400-e29b-41d4-a716-446655440002\"\n ],\n \"reference_id\": \"auth_12345\"\n}"
response = http.request(request)
puts response.read_body{
"amount_processed": "100.00",
"asset_id": "550e8400-e29b-41d4-a716-446655440001",
"balance": {
"available": "1400.00",
"deferred": "0.00",
"held": "200.00"
},
"journal_entry_id": "550e8400-e29b-41d4-a716-446655440003",
"lots_processed": [
{
"amount": "50.00",
"id": "550e8400-e29b-41d4-a716-446655440002"
}
],
"message": "Processed 100.00",
"operation": "<string>",
"program_id": "550e8400-e29b-41d4-a716-446655440000",
"reference_id": "auth_12345"
}{
"code": "bad_request",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Invalid request parameters"
}{
"code": "unauthorized",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Missing or invalid credentials"
}{
"code": "not_found",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Resource not found"
}{
"code": "conflict",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Resource already exists or state conflict"
}{
"code": "unsupported_media_type",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Content-Type must be application/json"
}{
"code": "unprocessable",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Business rule violation"
}{
"code": "internal_error",
"message": "An internal error occurred"
}Release group balance
Moves group balance from HELD to AVAILABLE. Allowed on archived assets so existing reservations can be unwound.
curl --request POST \
--url https://api.scrip.dev/v1/groups/{id}/balances/release \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"asset_id": "550e8400-e29b-41d4-a716-446655440001",
"description": "Order #123",
"program_id": "550e8400-e29b-41d4-a716-446655440000",
"amount": "100.00",
"bucket": "AVAILABLE",
"earned_from": "2024-01-01T00:00:00Z",
"earned_to": "2024-12-31T23:59:59Z",
"idempotency_key": "order-123",
"lot_ids": [
"550e8400-e29b-41d4-a716-446655440002"
],
"reference_id": "auth_12345"
}
'import requests
url = "https://api.scrip.dev/v1/groups/{id}/balances/release"
payload = {
"asset_id": "550e8400-e29b-41d4-a716-446655440001",
"description": "Order #123",
"program_id": "550e8400-e29b-41d4-a716-446655440000",
"amount": "100.00",
"bucket": "AVAILABLE",
"earned_from": "2024-01-01T00:00:00Z",
"earned_to": "2024-12-31T23:59:59Z",
"idempotency_key": "order-123",
"lot_ids": ["550e8400-e29b-41d4-a716-446655440002"],
"reference_id": "auth_12345"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
asset_id: '550e8400-e29b-41d4-a716-446655440001',
description: 'Order #123',
program_id: '550e8400-e29b-41d4-a716-446655440000',
amount: '100.00',
bucket: 'AVAILABLE',
earned_from: '2024-01-01T00:00:00Z',
earned_to: '2024-12-31T23:59:59Z',
idempotency_key: 'order-123',
lot_ids: ['550e8400-e29b-41d4-a716-446655440002'],
reference_id: 'auth_12345'
})
};
fetch('https://api.scrip.dev/v1/groups/{id}/balances/release', 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.scrip.dev/v1/groups/{id}/balances/release",
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([
'asset_id' => '550e8400-e29b-41d4-a716-446655440001',
'description' => 'Order #123',
'program_id' => '550e8400-e29b-41d4-a716-446655440000',
'amount' => '100.00',
'bucket' => 'AVAILABLE',
'earned_from' => '2024-01-01T00:00:00Z',
'earned_to' => '2024-12-31T23:59:59Z',
'idempotency_key' => 'order-123',
'lot_ids' => [
'550e8400-e29b-41d4-a716-446655440002'
],
'reference_id' => 'auth_12345'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$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.scrip.dev/v1/groups/{id}/balances/release"
payload := strings.NewReader("{\n \"asset_id\": \"550e8400-e29b-41d4-a716-446655440001\",\n \"description\": \"Order #123\",\n \"program_id\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"amount\": \"100.00\",\n \"bucket\": \"AVAILABLE\",\n \"earned_from\": \"2024-01-01T00:00:00Z\",\n \"earned_to\": \"2024-12-31T23:59:59Z\",\n \"idempotency_key\": \"order-123\",\n \"lot_ids\": [\n \"550e8400-e29b-41d4-a716-446655440002\"\n ],\n \"reference_id\": \"auth_12345\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
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.scrip.dev/v1/groups/{id}/balances/release")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"asset_id\": \"550e8400-e29b-41d4-a716-446655440001\",\n \"description\": \"Order #123\",\n \"program_id\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"amount\": \"100.00\",\n \"bucket\": \"AVAILABLE\",\n \"earned_from\": \"2024-01-01T00:00:00Z\",\n \"earned_to\": \"2024-12-31T23:59:59Z\",\n \"idempotency_key\": \"order-123\",\n \"lot_ids\": [\n \"550e8400-e29b-41d4-a716-446655440002\"\n ],\n \"reference_id\": \"auth_12345\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.scrip.dev/v1/groups/{id}/balances/release")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"asset_id\": \"550e8400-e29b-41d4-a716-446655440001\",\n \"description\": \"Order #123\",\n \"program_id\": \"550e8400-e29b-41d4-a716-446655440000\",\n \"amount\": \"100.00\",\n \"bucket\": \"AVAILABLE\",\n \"earned_from\": \"2024-01-01T00:00:00Z\",\n \"earned_to\": \"2024-12-31T23:59:59Z\",\n \"idempotency_key\": \"order-123\",\n \"lot_ids\": [\n \"550e8400-e29b-41d4-a716-446655440002\"\n ],\n \"reference_id\": \"auth_12345\"\n}"
response = http.request(request)
puts response.read_body{
"amount_processed": "100.00",
"asset_id": "550e8400-e29b-41d4-a716-446655440001",
"balance": {
"available": "1400.00",
"deferred": "0.00",
"held": "200.00"
},
"journal_entry_id": "550e8400-e29b-41d4-a716-446655440003",
"lots_processed": [
{
"amount": "50.00",
"id": "550e8400-e29b-41d4-a716-446655440002"
}
],
"message": "Processed 100.00",
"operation": "<string>",
"program_id": "550e8400-e29b-41d4-a716-446655440000",
"reference_id": "auth_12345"
}{
"code": "bad_request",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Invalid request parameters"
}{
"code": "unauthorized",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Missing or invalid credentials"
}{
"code": "not_found",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Resource not found"
}{
"code": "conflict",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Resource already exists or state conflict"
}{
"code": "unsupported_media_type",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Content-Type must be application/json"
}{
"code": "unprocessable",
"details": {
"expected": "<string>",
"field": "<string>",
"fields": [
{
"expected": "<unknown>",
"field": "<string>",
"message": "This field is required",
"reason": "required",
"received": "<string>"
}
],
"reason": "invalid",
"received": "<string>"
},
"message": "Business rule violation"
}{
"code": "internal_error",
"message": "An internal error occurred"
}HELD back to AVAILABLE for a group, making them spendable again. Use this to reverse authorization holds or complete approval workflows on a shared wallet.
The operation is program-scoped: program_id is required in the body along with asset_id and a description. If amount is omitted, all held funds for the specified asset are released. For LOT mode assets, you can narrow the scope with lot_ids, earned_from, earned_to, or reference_id to target specific lots.
Release by reference_id
When reference_id is provided, only lots stamped with that reference during a previous hold are targeted. This enables precise release of specific holds when a group has multiple concurrent holds.
amount | reference_id | Behavior |
|---|---|---|
| Omitted | Set | Release all HELD lots matching the reference |
| Set | Set | Release up to amount from HELD lots matching the reference |
| Set | Omitted | Release up to amount from any HELD lots (FIFO) |
| Omitted | Omitted | Release all HELD lots for the asset |
Authorizations
API key passed in the X-API-Key header.
Headers
Idempotency key (1-255 printable ASCII chars). Equivalent to the idempotency_key body field; if both are provided they must match. Replays with the same key and identical parameters return the original result; the same key with different parameters returns 409 idempotency_conflict.
255Path Parameters
Group ID
Body
Release parameters
Asset to operate on
"550e8400-e29b-41d4-a716-446655440001"
Reason for this operation
1 - 500"Order #123"
Program this operation belongs to
"550e8400-e29b-41d4-a716-446655440000"
Amount to process. Omit to process the full balance (SIMPLE) or all matching lots (LOT)
"100.00"
Which bucket to forfeit from. Required for forfeit; ignored for hold/release
AVAILABLE, HELD "AVAILABLE"
Only process lots earned on or after this time (RFC 3339). LOT mode only.
"2024-01-01T00:00:00Z"
Only process lots earned on or before this time (RFC 3339). LOT mode only. Must be >= earned_from when both are provided.
"2024-12-31T23:59:59Z"
Client-provided key to dedupe retries. May also be supplied via the Idempotency-Key HTTP header; when both are present they must match. Identical operations with the same key return the original result; a reused key with different payload returns 409 idempotency_conflict.
1 - 255"order-123"
Restrict to specific lots. LOT mode only
["550e8400-e29b-41d4-a716-446655440002"]
Correlation ID linking holds to releases. LOT mode only. Hold stamps lots; release filters by reference.
"auth_12345"
Response
Balance released
Total amount processed
"100.00"
Asset ID
"550e8400-e29b-41d4-a716-446655440001"
Balance after the operation
Show child attributes
Show child attributes
Ledger journal entry created by this operation
"550e8400-e29b-41d4-a716-446655440003"
Individual lots affected. Only present for LOT mode assets
Show child attributes
Show child attributes
Confirmation message
"Processed 100.00"
Operation performed, matching the endpoint called: HOLD, RELEASE, FORFEIT, or VOID_HOLD
Program ID
"550e8400-e29b-41d4-a716-446655440000"
Correlation ID linking this hold/release (if provided)
"auth_12345"