Skip to main content
POST
/
v1
/
participants
/
{id}
/
balances
/
release
Release participant balance
curl --request POST \
  --url https://api.scrip.dev/v1/participants/{id}/balances/release \
  --header 'Content-Type: application/json' \
  --header 'X-API-Key: <api-key>' \
  --data '
{
  "asset_id": "550e8400-e29b-41d4-a716-446655440001",
  "description": "Hold for pending 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-hold",
  "lot_ids": [
    "550e8400-e29b-41d4-a716-446655440002"
  ],
  "reference_id": "auth_12345"
}
'
import requests

url = "https://api.scrip.dev/v1/participants/{id}/balances/release"

payload = {
"asset_id": "550e8400-e29b-41d4-a716-446655440001",
"description": "Hold for pending 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-hold",
"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: 'Hold for pending 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-hold',
lot_ids: ['550e8400-e29b-41d4-a716-446655440002'],
reference_id: 'auth_12345'
})
};

fetch('https://api.scrip.dev/v1/participants/{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/participants/{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' => 'Hold for pending 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-hold',
'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/participants/{id}/balances/release"

payload := strings.NewReader("{\n \"asset_id\": \"550e8400-e29b-41d4-a716-446655440001\",\n \"description\": \"Hold for pending 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-hold\",\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/participants/{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\": \"Hold for pending 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-hold\",\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/participants/{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\": \"Hold for pending 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-hold\",\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": "HOLD",
  "program_id": "550e8400-e29b-41d4-a716-446655440000",
  "reference_id": "auth_12345"
}
{
"code": "bad_request",
"details": {
"expected": "uuid",
"field": "asset_id",
"fields": [
{
"expected": "<unknown>",
"field": "amount",
"message": "This field is required",
"reason": "required",
"received": "-10.00"
}
],
"reason": "invalid",
"received": "not-a-uuid"
},
"message": "Invalid request parameters"
}
{
"code": "unauthorized",
"details": {
"expected": "uuid",
"field": "asset_id",
"fields": [
{
"expected": "<unknown>",
"field": "amount",
"message": "This field is required",
"reason": "required",
"received": "-10.00"
}
],
"reason": "invalid",
"received": "not-a-uuid"
},
"message": "Missing or invalid credentials"
}
{
"code": "forbidden",
"details": {
"expected": "uuid",
"field": "asset_id",
"fields": [
{
"expected": "<unknown>",
"field": "amount",
"message": "This field is required",
"reason": "required",
"received": "-10.00"
}
],
"reason": "invalid",
"received": "not-a-uuid"
},
"message": "Insufficient permissions for this action"
}
{
"code": "not_found",
"details": {
"expected": "uuid",
"field": "asset_id",
"fields": [
{
"expected": "<unknown>",
"field": "amount",
"message": "This field is required",
"reason": "required",
"received": "-10.00"
}
],
"reason": "invalid",
"received": "not-a-uuid"
},
"message": "Resource not found"
}
{
"code": "conflict",
"details": {
"expected": "uuid",
"field": "asset_id",
"fields": [
{
"expected": "<unknown>",
"field": "amount",
"message": "This field is required",
"reason": "required",
"received": "-10.00"
}
],
"reason": "invalid",
"received": "not-a-uuid"
},
"message": "Resource already exists or state conflict"
}
{
"code": "unsupported_media_type",
"details": {
"expected": "uuid",
"field": "asset_id",
"fields": [
{
"expected": "<unknown>",
"field": "amount",
"message": "This field is required",
"reason": "required",
"received": "-10.00"
}
],
"reason": "invalid",
"received": "not-a-uuid"
},
"message": "Content-Type must be application/json"
}
{
"code": "unprocessable",
"details": {
"expected": "uuid",
"field": "asset_id",
"fields": [
{
"expected": "<unknown>",
"field": "amount",
"message": "This field is required",
"reason": "required",
"received": "-10.00"
}
],
"reason": "invalid",
"received": "not-a-uuid"
},
"message": "Business rule violation"
}
{
"code": "internal_error",
"message": "An internal error occurred"
}
Moves funds from HELD back to AVAILABLE, making them spendable again. Use this to reverse authorization holds, clear fraud reviews, or complete approval workflows. 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 participant has multiple concurrent holds. The typical settlement pattern is to release the entire hold by reference (omit amount) and then debit the actual settlement amount separately. The settlement amount does not need to match the original hold.
amountreference_idBehavior
OmittedSetRelease all HELD lots matching the reference (recommended for settlement)
SetSetRelease up to amount from HELD lots matching the reference
SetOmittedRelease up to amount from any HELD lots (FIFO)
OmittedOmittedRelease all HELD lots for the asset
For usage patterns and examples, see the Balance Operations guide.

Authorizations

X-API-Key
string
header
required

API key passed in the X-API-Key header.

Headers

Idempotency-Key
string

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.

Maximum string length: 255

Path Parameters

id
string<uuid>
required

Participant ID

Body

application/json

Release operation details

asset_id
string<uuid>
required

Asset to operate on

Example:

"550e8400-e29b-41d4-a716-446655440001"

description
string
required

Reason for this operation

Required string length: 1 - 500
Example:

"Hold for pending order #123"

program_id
string<uuid>
required

Program this operation belongs to

Example:

"550e8400-e29b-41d4-a716-446655440000"

amount
string

Amount to process. Omit to process the full balance (SIMPLE) or all matching lots (LOT)

Example:

"100.00"

bucket
enum<string>

Which bucket to forfeit from. Required for forfeit; ignored for hold/release

Available options:
AVAILABLE,
HELD
Example:

"AVAILABLE"

earned_from
string<date-time>

Only process lots earned on or after this time (RFC 3339). LOT mode only.

Example:

"2024-01-01T00:00:00Z"

earned_to
string<date-time>

Only process lots earned on or before this time (RFC 3339). LOT mode only. Must be >= earned_from when both are provided.

Example:

"2024-12-31T23:59:59Z"

idempotency_key
string

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.

Required string length: 1 - 255
Example:

"order-123-hold"

lot_ids
string[]

Restrict to specific lots. LOT mode only

Example:
["550e8400-e29b-41d4-a716-446655440002"]
reference_id
string

Correlation ID linking holds to releases. LOT mode only. Hold stamps lots; release filters by reference.

Example:

"auth_12345"

Response

Release processed

amount_processed
string

Total amount processed

Example:

"100.00"

asset_id
string<uuid>

Asset ID

Example:

"550e8400-e29b-41d4-a716-446655440001"

balance
object

Balance after the operation

journal_entry_id
string<uuid>

Ledger journal entry created by this operation

Example:

"550e8400-e29b-41d4-a716-446655440003"

lots_processed
object[]

Individual lots affected. Only present for LOT mode assets

message
string

Confirmation message

Example:

"Processed 100.00"

operation
string

Operation performed

Example:

"HOLD"

program_id
string<uuid>

Program ID

Example:

"550e8400-e29b-41d4-a716-446655440000"

reference_id
string

Correlation ID linking this hold/release (if provided)

Example:

"auth_12345"