Version 1.0.0
Droomwork REMIT AUTHORITY RAIL
Statutory remittance to Nigerian authorities, with proof of every payment.
https://sandbox.droomwork.ioDroomwork-Api-Key: dw_test_… or Authorization: Bearer dw_test_…REMIT files what your payroll says is owed with each authority and keeps the receipt for you.
What you should know before you start
You don't need RUN to use this. Send instruction sets from Droomwork payroll or from your own, by API or by file. The shape is the same either way, and so is everything that follows.
Intake is two steps. You submit, we validate and return a report, and nothing is committed until you accept. A discrepancy blocks acceptance until you resolve it or override it with a reason code. A figure filed wrongly is one you have to unwind with an authority.
One approval, many legs. A remittance executes one leg per authority, and each leg runs on its own. One authority being down never blocks the others, so a Federal Inland Revenue Service outage does not delay your pension filings.
A leg is complete when its receipt is vaulted. A receipt whose parsed amount, period or authority disagrees with the leg is quarantined, not accepted.
Every authority presents the same contract. Some file by direct API, some by portal automation, some by assisted manual filing. The request, the states, the webhooks and the evidence class are identical across all three. Tier is something you can read, never something you code against.
Getting started
Get a sandbox key from the developer portal. Submit an instruction set. Accept it. Create a remittance from it, approve it, then execute it.
Every operation below has two samples: Direct HTTP, with nothing but your language's own client, and Client library, with ours. Same request, same answer; the switch above each sample picks one and remembers it. Which should I use?
/v1/remittance/instruction_sets#Check what you submitted and where it stands
remittance.instruction_sets.list
This is where you look up the months you have already submitted. Every record on the page is a whole set, its state and its validation report included, so one call fills a submissions screen without a read for each row.
You get a page of sets, each with the month it covers, the state it is in, the figures it holds and the report of every line that was flagged.
Take an id from the page and carry it as instruction_set_id, to GET /v1/remittance/instruction_sets/{instruction_set_id}/totals for what the month comes to, or to POST /v1/remittance/instruction_sets/{instruction_set_id}/accept while the set is still waiting on your decision.
Query parameters
limit
integer
optionalHow many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.
starting_after
string
optionalThe id of the last record on the previous page of this same list. Leave it out to get the first page; when a page comes back with has_more true, send its last record's id here to get the page after it.
status
string
optionalReturn only sets in this state: received on submission, validating while every line is checked, pending_acceptance once the report is back, accepted or rejected once you decide. Leave it out to get every state.
receivedvalidatingpending_acceptanceacceptedrejectedperiod
string
optionalReturn only sets for this month, as YYYY-MM, such as 2026-09. Leave it out to get every period.
Returns
A page of instruction sets, each with created_at where there is one, to order your own rows by.
object
always "list"
requiredAlways list. Tells you which kind of record you are looking at, so one handler can read any response.
data
array of IngestedInstructionSet
requiredThe records on this page, in the order the list promises. Empty when nothing matched.
13 fields of IngestedInstructionSet
id
string
requiredThe set's identifier, starting remit_authority_rail_instruction_, as listed at GET /v1/remittance/instruction_sets. It never changes; pass it as instruction_set_id to retrieve, accept, reject or remit the set.
object
always "ingested_instruction_set"
requiredAlways ingested_instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
status
string
requiredNothing is committed until accepted.
receivedvalidatingpending_acceptanceacceptedrejectedsource
string
requiredWhere the set came from. Droomwork payroll or your own, by API or by file. Everything downstream behaves identically whichever it was.
runexternal_apiexternal_fileperiod
string
requiredThe month the set covers, as YYYY-MM, such as 2026-09. Filter the list by it with the period query.
run_id
string · nullable
optionalThe Droomwork payroll run the set came from, by its id from POST /v1/payroll/runs or GET /v1/payroll/runs, starting run_enterprise_. Present when source is run; null when the set came from your own payroll.
instructions
InstructionSet
optionalWhat is owed to whom for one run. This shape is owned jointly by RUN and REMIT. RUN row 19 emits it and REMIT row 1 ingests it, from RUN and from external payroll alike. It lives here rather than in either module document so the two cannot drift, which is the failure that would otherwise surface at M3 with RUN already accepted and paid. Totals reconcile to run totals to the kobo, because they sum payslip lines rather than recompute from an aggregate. This is the object REMIT ingests.
11 fields of InstructionSet
id
string
requiredThe instruction set's identifier, which never changes: read it at GET /v1/payroll/runs/{run_id}/instruction_set when Droomwork ran the payroll, and send the set on unchanged to POST /v1/remittance/instruction_sets. Quote it when you ask about the set.
object
always "instruction_set"
requiredAlways instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
run_id
string
requiredThe payroll run this set is owed for, by its id from POST /v1/payroll/runs, which starts with run_enterprise_. The set's totals reconcile to that run's totals to the kobo.
period
string
optionalThe pay period the amounts are owed for, as year and month, for example 2026-09.
paye
array of object
requiredGrouped by the State IRS of the employee's residence, not the employer's location.
5 fields
authority_id
string
requiredThe State Internal Revenue Service this PAYE is owed to, by its id from GET /v1/remittance/authorities, which starts with remit_authority_rail_obligation_. Use it wherever a call names the authority.
jurisdiction
string
requiredThe State Internal Revenue Service this line is grouped under, named in full, for example Rivers State Internal Revenue Service. Read it to label the line; authority_id names the authority in a call.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
payee_count
integer
optionalHow many employees this line's PAYE covers. Optional; when it is present, check it against your own headcount for that state.
reconciliation_reference
string
requiredThe reference that identifies this line when you reconcile it, for example paye-2026-09-rivers. Keep it with your own records so you can trace the line later.
pension
array of object
requiredGrouped by administrator and retirement savings account number.
6 fields
administrator_id
string
requiredThe Pension Fund Administrator these contributions are owed to, by its id from GET /v1/remittance/authorities with kind=pension_administrator, which starts with remit_authority_rail_obligation_. Use it wherever a call names the administrator.
administrator_name
string
optionalThe administrator's name in full, so you can label the line without a second call. Optional; administrator_id is what names the administrator in a call.
employee_amount
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
employer_amount
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
reconciliation_reference
string
requiredThe reference that identifies this line when you reconcile it. Keep it with your own records so you can trace the line later.
levies
array of object
requiredNHF, NSITF, ITF and NHIA totals, each with a reconciliation reference.
3 fields
code
string
requiredWhich levy this line is for: nhf the National Housing Fund, nsitf the Nigeria Social Insurance Trust Fund, itf the Industrial Training Fund, nhia the National Health Insurance Authority. One line per levy.
nhfnsitfitfnhiaamount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
reconciliation_reference
string
requiredThe reference that identifies this levy line when you reconcile it. Keep it with your own records so you can trace the line later.
totals
object
requiredThe set's grand total, which its lines sum to. From a Droomwork run it reconciles to the run's totals to the kobo.
1 field
total
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
validation_report
ValidationReport
requiredThe result of checking a submission before anything is committed. Names every failing entry rather than stopping at the first, so one submission tells you everything to fix. The same shape wherever the platform ingests, validates and reports, which is every bulk intake in every module.
4 fields of ValidationReport
entry_count
integer · minimum 0
requiredHow many entries the submission held: every row in the file or line in the instruction set, whether it passed or not.
error_count
integer · minimum 0
requiredHow many entries failed with an error. Each is named in entries with its position and why, so one submission tells you everything to fix.
warning_count
integer · minimum 0
requiredHow many entries passed with a warning, each named in entries. A warning does not fail the entry; it points at something to confirm before you go ahead.
entries
array of object
optionalOne item per error or warning found, with the row or line it sits on, its severity, a code and what was wrong. Empty or absent when every entry passed clean.
4 fields
index
integer · minimum 1
requiredThe row in a file, or the line in an instruction set.
severity
string
requirederror means the entry failed and must be fixed. warning means it passed, but points at something you should confirm before you go ahead.
errorwarningcode
string
requiredWhy the entry was flagged, as a code you can branch on. detail says the same in words and may change; the code does not.
detail
string
requiredWhat was wrong with the entry, in plain words. Show it beside the row; it may change, so branch on code.
jurisdiction_pack
object
optionalThe jurisdiction pack the set is pinned to, by identifier and version. Every line was recomputed against it, so its rules are the ones the validation report reflects.
2 fields
pack_id
string
optionalWhich jurisdiction pack the set is pinned to, such as ng-paye. We publish the packs and you never send this; with version, it names exactly which rules every line was checked against, and it stays with the set so you can show which rules applied.
version
string
optionalThe pack version the set was checked against, such as 2026.08.1. It's pinned, so a later pack release doesn't change what this set was judged by.
accepted_by
string · nullable
optionalWho accepted the set: the actor that called accept. null until the set is accepted.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
has_more
boolean
requiredtrue when there are more records after this page. Pass the last record's id as starting_after to get the next page.
Other responses
Errors it can return
# query parameters: limit (optional), starting_after (optional), status (optional), period (optional)
curl -X GET "https://sandbox.droomwork.io/v1/remittance/instruction_sets?limit=25&status=received&period=2026-09" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
// query parameters: limit (optional), starting_after (optional), status (optional), period (optional)
const result = await api.remittanceInstructionSetsList({ limit: 25, status: 'received', period: '2026-09' });// query parameters: limit (optional), starting_after (optional), status (optional), period (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/remittance/instruction_sets?limit=25&status=received&period=2026-09', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
# query parameters: limit (optional), starting_after (optional), status (optional), period (optional)
result = api.remittance_instruction_sets_list(limit=25, status='received', period='2026-09')import os
import requests
# query parameters: limit (optional), starting_after (optional), status (optional), period (optional)
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/instruction_sets?limit=25&status=received&period=2026-09',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
# query parameters: limit (optional), starting_after (optional), status (optional), period (optional)
$result = $api->remittanceInstructionSetsList(limit: 25, status: 'received', period: '2026-09');<?php
// query parameters: limit (optional), starting_after (optional), status (optional), period (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/instruction_sets?limit=25&status=received&period=2026-09');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
import com.droomwork.sdk.model.*;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
// query parameters: limit (optional), starting_after (optional), status (optional), period (optional)
var result = api.remittanceInstructionSetsList(25, null, RemitInstructionSetStatus.fromValue("received"), "2026-09");// query parameters: limit (optional), starting_after (optional), status (optional), period (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/instruction_sets?limit=25&status=received&period=2026-09"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
// query parameters: limit (optional), starting_after (optional), status (optional), period (optional)
var result = api.RemittanceInstructionSetsList(limit: 25, status: RemitInstructionSetStatus.Received, period: "2026-09");// query parameters: limit (optional), starting_after (optional), status (optional), period (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/instruction_sets?limit=25&status=received&period=2026-09");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
// query parameters: limit (optional), starting_after (optional), status (optional), period (optional)
result, _, err := client.REMITAPI.RemittanceInstructionSetsList(ctx).Limit(25).Status(droomwork.RemitInstructionSetStatus("received")).Period("2026-09").Execute()// query parameters: limit (optional), starting_after (optional), status (optional), period (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/instruction_sets?limit=25&status=received&period=2026-09", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"object": "list",
"data": [
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "ingested_instruction_set",
"livemode": false,
"mocked": true,
"status": "received",
"source": "run",
"period": "2026-09",
"validation_report": {
"entry_count": 0,
"error_count": 0,
"warning_count": 0,
"entries": [
{
"index": 1,
"severity": "error",
"code": "invalid_money_amount",
"detail": "The payee has no verified destination, so this line cannot be paid."
}
]
},
"run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"instructions": {
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "instruction_set",
"livemode": false,
"mocked": true,
"run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"paye": [
{
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"jurisdiction": "Rivers State Internal Revenue Service",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers",
"payee_count": 1
}
],
"pension": [
{
"administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers",
"administrator_name": "example",
"employee_amount": {
"amount": 4200000,
"currency": "NGN"
},
"employer_amount": {
"amount": 5400000,
"currency": "NGN"
}
}
],
"levies": [
{
"code": "nhf",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers"
}
],
"totals": {
"total": {
"amount": 57900000,
"currency": "NGN"
}
},
"period": "2026-09",
"created_at": "2026-09-01T09:00:00Z"
},
"jurisdiction_pack": {
"pack_id": "ng-paye",
"version": "2026.08.1"
},
"accepted_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"created_at": "2026-09-01T09:00:00Z"
}
],
"has_more": true
}
/v1/remittance/instruction_sets#Submit the month's figures for checking
remittance.instruction_sets.create
Filing a month starts here. Every line is recomputed against the jurisdiction pack the set is pinned to, and the report that comes back names each line it flagged, so your product can put a whole month's problems in front of somebody at once.
You send the period and the figures: PAYE grouped by the employee's State IRS, pension by administrator, levies by code. You get back the stored set, with an id starting remit_authority_rail_instruction_ and its validation report.
Nothing has to exist first, including a Droomwork payroll run.
The field to get right is run_id. Send it when these figures came from a Droomwork payroll run, and leave it out when they came from your own system.
Carry the id forward as instruction_set_id. Nothing is committed until you accept the set at POST /v1/remittance/instruction_sets/{instruction_set_id}/accept.
Headers
Idempotency-Key
string
requiredA key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.
Body
period
string
requiredThe month the figures cover, as YYYY-MM, such as 2026-09. What you owe for it is recorded against this period once you accept.
run_id
string
optionalThe Droomwork payroll run these figures come from, by its id from POST /v1/payroll/runs or GET /v1/payroll/runs, starting run_enterprise_. Omit it when the set comes from your own payroll system.
instructions
InstructionSet
requiredWhat is owed to whom for one run. This shape is owned jointly by RUN and REMIT. RUN row 19 emits it and REMIT row 1 ingests it, from RUN and from external payroll alike. It lives here rather than in either module document so the two cannot drift, which is the failure that would otherwise surface at M3 with RUN already accepted and paid. Totals reconcile to run totals to the kobo, because they sum payslip lines rather than recompute from an aggregate. This is the object REMIT ingests.
11 fields of InstructionSet
id
string
requiredThe instruction set's identifier, which never changes: read it at GET /v1/payroll/runs/{run_id}/instruction_set when Droomwork ran the payroll, and send the set on unchanged to POST /v1/remittance/instruction_sets. Quote it when you ask about the set.
object
always "instruction_set"
requiredAlways instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
run_id
string
requiredThe payroll run this set is owed for, by its id from POST /v1/payroll/runs, which starts with run_enterprise_. The set's totals reconcile to that run's totals to the kobo.
period
string
optionalThe pay period the amounts are owed for, as year and month, for example 2026-09.
paye
array of object
requiredGrouped by the State IRS of the employee's residence, not the employer's location.
5 fields
authority_id
string
requiredThe State Internal Revenue Service this PAYE is owed to, by its id from GET /v1/remittance/authorities, which starts with remit_authority_rail_obligation_. Use it wherever a call names the authority.
jurisdiction
string
requiredThe State Internal Revenue Service this line is grouped under, named in full, for example Rivers State Internal Revenue Service. Read it to label the line; authority_id names the authority in a call.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
payee_count
integer
optionalHow many employees this line's PAYE covers. Optional; when it is present, check it against your own headcount for that state.
reconciliation_reference
string
requiredThe reference that identifies this line when you reconcile it, for example paye-2026-09-rivers. Keep it with your own records so you can trace the line later.
pension
array of object
requiredGrouped by administrator and retirement savings account number.
6 fields
administrator_id
string
requiredThe Pension Fund Administrator these contributions are owed to, by its id from GET /v1/remittance/authorities with kind=pension_administrator, which starts with remit_authority_rail_obligation_. Use it wherever a call names the administrator.
administrator_name
string
optionalThe administrator's name in full, so you can label the line without a second call. Optional; administrator_id is what names the administrator in a call.
employee_amount
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
employer_amount
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
reconciliation_reference
string
requiredThe reference that identifies this line when you reconcile it. Keep it with your own records so you can trace the line later.
levies
array of object
requiredNHF, NSITF, ITF and NHIA totals, each with a reconciliation reference.
3 fields
code
string
requiredWhich levy this line is for: nhf the National Housing Fund, nsitf the Nigeria Social Insurance Trust Fund, itf the Industrial Training Fund, nhia the National Health Insurance Authority. One line per levy.
nhfnsitfitfnhiaamount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
reconciliation_reference
string
requiredThe reference that identifies this levy line when you reconcile it. Keep it with your own records so you can trace the line later.
totals
object
requiredThe set's grand total, which its lines sum to. From a Droomwork run it reconciles to the run's totals to the kobo.
1 field
total
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
Returns
The ingested set, with created_at where there is one, to keep beside your own record.
id
string
requiredThe set's identifier, starting remit_authority_rail_instruction_, as listed at GET /v1/remittance/instruction_sets. It never changes; pass it as instruction_set_id to retrieve, accept, reject or remit the set.
object
always "ingested_instruction_set"
requiredAlways ingested_instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
status
string
requiredNothing is committed until accepted.
receivedvalidatingpending_acceptanceacceptedrejectedsource
string
requiredWhere the set came from. Droomwork payroll or your own, by API or by file. Everything downstream behaves identically whichever it was.
runexternal_apiexternal_fileperiod
string
requiredThe month the set covers, as YYYY-MM, such as 2026-09. Filter the list by it with the period query.
run_id
string · nullable
optionalThe Droomwork payroll run the set came from, by its id from POST /v1/payroll/runs or GET /v1/payroll/runs, starting run_enterprise_. Present when source is run; null when the set came from your own payroll.
instructions
InstructionSet
optionalWhat is owed to whom for one run. This shape is owned jointly by RUN and REMIT. RUN row 19 emits it and REMIT row 1 ingests it, from RUN and from external payroll alike. It lives here rather than in either module document so the two cannot drift, which is the failure that would otherwise surface at M3 with RUN already accepted and paid. Totals reconcile to run totals to the kobo, because they sum payslip lines rather than recompute from an aggregate. This is the object REMIT ingests.
11 fields of InstructionSet
id
string
requiredThe instruction set's identifier, which never changes: read it at GET /v1/payroll/runs/{run_id}/instruction_set when Droomwork ran the payroll, and send the set on unchanged to POST /v1/remittance/instruction_sets. Quote it when you ask about the set.
object
always "instruction_set"
requiredAlways instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
run_id
string
requiredThe payroll run this set is owed for, by its id from POST /v1/payroll/runs, which starts with run_enterprise_. The set's totals reconcile to that run's totals to the kobo.
period
string
optionalThe pay period the amounts are owed for, as year and month, for example 2026-09.
paye
array of object
requiredGrouped by the State IRS of the employee's residence, not the employer's location.
5 fields
authority_id
string
requiredThe State Internal Revenue Service this PAYE is owed to, by its id from GET /v1/remittance/authorities, which starts with remit_authority_rail_obligation_. Use it wherever a call names the authority.
jurisdiction
string
requiredThe State Internal Revenue Service this line is grouped under, named in full, for example Rivers State Internal Revenue Service. Read it to label the line; authority_id names the authority in a call.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
payee_count
integer
optionalHow many employees this line's PAYE covers. Optional; when it is present, check it against your own headcount for that state.
reconciliation_reference
string
requiredThe reference that identifies this line when you reconcile it, for example paye-2026-09-rivers. Keep it with your own records so you can trace the line later.
pension
array of object
requiredGrouped by administrator and retirement savings account number.
6 fields
administrator_id
string
requiredThe Pension Fund Administrator these contributions are owed to, by its id from GET /v1/remittance/authorities with kind=pension_administrator, which starts with remit_authority_rail_obligation_. Use it wherever a call names the administrator.
administrator_name
string
optionalThe administrator's name in full, so you can label the line without a second call. Optional; administrator_id is what names the administrator in a call.
employee_amount
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
employer_amount
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
reconciliation_reference
string
requiredThe reference that identifies this line when you reconcile it. Keep it with your own records so you can trace the line later.
levies
array of object
requiredNHF, NSITF, ITF and NHIA totals, each with a reconciliation reference.
3 fields
code
string
requiredWhich levy this line is for: nhf the National Housing Fund, nsitf the Nigeria Social Insurance Trust Fund, itf the Industrial Training Fund, nhia the National Health Insurance Authority. One line per levy.
nhfnsitfitfnhiaamount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
reconciliation_reference
string
requiredThe reference that identifies this levy line when you reconcile it. Keep it with your own records so you can trace the line later.
totals
object
requiredThe set's grand total, which its lines sum to. From a Droomwork run it reconciles to the run's totals to the kobo.
1 field
total
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
validation_report
ValidationReport
requiredThe result of checking a submission before anything is committed. Names every failing entry rather than stopping at the first, so one submission tells you everything to fix. The same shape wherever the platform ingests, validates and reports, which is every bulk intake in every module.
4 fields of ValidationReport
entry_count
integer · minimum 0
requiredHow many entries the submission held: every row in the file or line in the instruction set, whether it passed or not.
error_count
integer · minimum 0
requiredHow many entries failed with an error. Each is named in entries with its position and why, so one submission tells you everything to fix.
warning_count
integer · minimum 0
requiredHow many entries passed with a warning, each named in entries. A warning does not fail the entry; it points at something to confirm before you go ahead.
entries
array of object
optionalOne item per error or warning found, with the row or line it sits on, its severity, a code and what was wrong. Empty or absent when every entry passed clean.
4 fields
index
integer · minimum 1
requiredThe row in a file, or the line in an instruction set.
severity
string
requirederror means the entry failed and must be fixed. warning means it passed, but points at something you should confirm before you go ahead.
errorwarningcode
string
requiredWhy the entry was flagged, as a code you can branch on. detail says the same in words and may change; the code does not.
detail
string
requiredWhat was wrong with the entry, in plain words. Show it beside the row; it may change, so branch on code.
jurisdiction_pack
object
optionalThe jurisdiction pack the set is pinned to, by identifier and version. Every line was recomputed against it, so its rules are the ones the validation report reflects.
2 fields
pack_id
string
optionalWhich jurisdiction pack the set is pinned to, such as ng-paye. We publish the packs and you never send this; with version, it names exactly which rules every line was checked against, and it stays with the set so you can show which rules applied.
version
string
optionalThe pack version the set was checked against, such as 2026.08.1. It's pinned, so a later pack release doesn't change what this set was judged by.
accepted_by
string · nullable
optionalWho accepted the set: the actor that called accept. null until the set is accepted.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
Other responses
Errors it can return
curl -X POST "https://sandbox.droomwork.io/v1/remittance/instruction_sets" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"period":"2026-09","instructions":{"id":"remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","object":"instruction_set","livemode":false,"mocked":true,"run_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","paye":[{"authority_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","jurisdiction":"Rivers State Internal Revenue Service","amount":{"amount":7500000,"currency":"NGN"},"reconciliation_reference":"paye-2026-09-rivers","payee_count":1}],"pension":[{"administrator_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","amount":{"amount":7500000,"currency":"NGN"},"reconciliation_reference":"paye-2026-09-rivers","administrator_name":"example","employee_amount":{"amount":4200000,"currency":"NGN"},"employer_amount":{"amount":5400000,"currency":"NGN"}}],"levies":[{"code":"nhf","amount":{"amount":7500000,"currency":"NGN"},"reconciliation_reference":"paye-2026-09-rivers"}],"totals":{"total":{"amount":57900000,"currency":"NGN"}},"period":"2026-09","created_at":"2026-09-01T09:00:00Z"},"run_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"}'import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceInstructionSetsCreate({
idempotencyKey: crypto.randomUUID(),
remitInstructionSetCreateRequest: {"period":"2026-09","instructions":{"id":"remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","object":"instruction_set","livemode":false,"mocked":true,"runId":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","paye":[{"authorityId":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","jurisdiction":"Rivers State Internal Revenue Service","amount":{"amount":7500000,"currency":"NGN"},"reconciliationReference":"paye-2026-09-rivers","payeeCount":1}],"pension":[{"administratorId":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","amount":{"amount":7500000,"currency":"NGN"},"reconciliationReference":"paye-2026-09-rivers","administratorName":"example","employeeAmount":{"amount":4200000,"currency":"NGN"},"employerAmount":{"amount":5400000,"currency":"NGN"}}],"levies":[{"code":"nhf","amount":{"amount":7500000,"currency":"NGN"},"reconciliationReference":"paye-2026-09-rivers"}],"totals":{"total":{"amount":57900000,"currency":"NGN"}},"period":"2026-09","createdAt":"2026-09-01T09:00:00Z"},"runId":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"},
});const response = await fetch('https://sandbox.droomwork.io/v1/remittance/instruction_sets', {
method: 'POST',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
"period": "2026-09",
"instructions": {
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "instruction_set",
"livemode": false,
"mocked": true,
"run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"paye": [
{
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"jurisdiction": "Rivers State Internal Revenue Service",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers",
"payee_count": 1
}
],
"pension": [
{
"administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers",
"administrator_name": "example",
"employee_amount": {
"amount": 4200000,
"currency": "NGN"
},
"employer_amount": {
"amount": 5400000,
"currency": "NGN"
}
}
],
"levies": [
{
"code": "nhf",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers"
}
],
"totals": {
"total": {
"amount": 57900000,
"currency": "NGN"
}
},
"period": "2026-09",
"created_at": "2026-09-01T09:00:00Z"
},
"run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}),
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_instruction_sets_create(body={"period": "2026-09", "instructions": {"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "object": "instruction_set", "livemode": False, "mocked": True, "run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "paye": [{"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "jurisdiction": "Rivers State Internal Revenue Service", "amount": {"amount": 7500000, "currency": "NGN"}, "reconciliation_reference": "paye-2026-09-rivers", "payee_count": 1}], "pension": [{"administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "amount": {"amount": 7500000, "currency": "NGN"}, "reconciliation_reference": "paye-2026-09-rivers", "administrator_name": "example", "employee_amount": {"amount": 4200000, "currency": "NGN"}, "employer_amount": {"amount": 5400000, "currency": "NGN"}}], "levies": [{"code": "nhf", "amount": {"amount": 7500000, "currency": "NGN"}, "reconciliation_reference": "paye-2026-09-rivers"}], "totals": {"total": {"amount": 57900000, "currency": "NGN"}}, "period": "2026-09", "created_at": "2026-09-01T09:00:00Z"}, "run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"})import os
import uuid
import requests
response = requests.request(
'POST',
'https://sandbox.droomwork.io/v1/remittance/instruction_sets',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
'Idempotency-Key': str(uuid.uuid4()),
},
json={"period": "2026-09", "instructions": {"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "object": "instruction_set", "livemode": False, "mocked": True, "run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "paye": [{"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "jurisdiction": "Rivers State Internal Revenue Service", "amount": {"amount": 7500000, "currency": "NGN"}, "reconciliation_reference": "paye-2026-09-rivers", "payee_count": 1}], "pension": [{"administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "amount": {"amount": 7500000, "currency": "NGN"}, "reconciliation_reference": "paye-2026-09-rivers", "administrator_name": "example", "employee_amount": {"amount": 4200000, "currency": "NGN"}, "employer_amount": {"amount": 5400000, "currency": "NGN"}}], "levies": [{"code": "nhf", "amount": {"amount": 7500000, "currency": "NGN"}, "reconciliation_reference": "paye-2026-09-rivers"}], "totals": {"total": {"amount": 57900000, "currency": "NGN"}}, "period": "2026-09", "created_at": "2026-09-01T09:00:00Z"}, "run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceInstructionSetsCreate($idempotencyKey, json_decode('{"period":"2026-09","instructions":{"id":"remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","object":"instruction_set","livemode":false,"mocked":true,"run_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","paye":[{"authority_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","jurisdiction":"Rivers State Internal Revenue Service","amount":{"amount":7500000,"currency":"NGN"},"reconciliation_reference":"paye-2026-09-rivers","payee_count":1}],"pension":[{"administrator_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","amount":{"amount":7500000,"currency":"NGN"},"reconciliation_reference":"paye-2026-09-rivers","administrator_name":"example","employee_amount":{"amount":4200000,"currency":"NGN"},"employer_amount":{"amount":5400000,"currency":"NGN"}}],"levies":[{"code":"nhf","amount":{"amount":7500000,"currency":"NGN"},"reconciliation_reference":"paye-2026-09-rivers"}],"totals":{"total":{"amount":57900000,"currency":"NGN"}},"period":"2026-09","created_at":"2026-09-01T09:00:00Z"},"run_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"}', true));<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/instruction_sets');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
'Content-Type: application/json',
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
],
CURLOPT_POSTFIELDS => '{"period":"2026-09","instructions":{"id":"remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","object":"instruction_set","livemode":false,"mocked":true,"run_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","paye":[{"authority_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","jurisdiction":"Rivers State Internal Revenue Service","amount":{"amount":7500000,"currency":"NGN"},"reconciliation_reference":"paye-2026-09-rivers","payee_count":1}],"pension":[{"administrator_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","amount":{"amount":7500000,"currency":"NGN"},"reconciliation_reference":"paye-2026-09-rivers","administrator_name":"example","employee_amount":{"amount":4200000,"currency":"NGN"},"employer_amount":{"amount":5400000,"currency":"NGN"}}],"levies":[{"code":"nhf","amount":{"amount":7500000,"currency":"NGN"},"reconciliation_reference":"paye-2026-09-rivers"}],"totals":{"total":{"amount":57900000,"currency":"NGN"}},"period":"2026-09","created_at":"2026-09-01T09:00:00Z"},"run_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"}',
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceInstructionSetsCreate(idempotencyKey, body);var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/instruction_sets"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.header("Content-Type", "application/json")
.header("Idempotency-Key", UUID.randomUUID().toString())
.method("POST", HttpRequest.BodyPublishers.ofString("""
{
"period": "2026-09",
"instructions": {
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "instruction_set",
"livemode": false,
"mocked": true,
"run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"paye": [
{
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"jurisdiction": "Rivers State Internal Revenue Service",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers",
"payee_count": 1
}
],
"pension": [
{
"administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers",
"administrator_name": "example",
"employee_amount": {
"amount": 4200000,
"currency": "NGN"
},
"employer_amount": {
"amount": 5400000,
"currency": "NGN"
}
}
],
"levies": [
{
"code": "nhf",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers"
}
],
"totals": {
"total": {
"amount": 57900000,
"currency": "NGN"
}
},
"period": "2026-09",
"created_at": "2026-09-01T09:00:00Z"
},
"run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}
"""))
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceInstructionSetsCreate(idempotencyKey, body);using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/remittance/instruction_sets");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent("""
{
"period": "2026-09",
"instructions": {
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "instruction_set",
"livemode": false,
"mocked": true,
"run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"paye": [
{
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"jurisdiction": "Rivers State Internal Revenue Service",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers",
"payee_count": 1
}
],
"pension": [
{
"administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers",
"administrator_name": "example",
"employee_amount": {
"amount": 4200000,
"currency": "NGN"
},
"employer_amount": {
"amount": 5400000,
"currency": "NGN"
}
}
],
"levies": [
{
"code": "nhf",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers"
}
],
"totals": {
"total": {
"amount": 57900000,
"currency": "NGN"
}
},
"period": "2026-09",
"created_at": "2026-09-01T09:00:00Z"
},
"run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}
""", Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceInstructionSetsCreate(ctx).IdempotencyKey(key).RemitInstructionSetCreateRequest(body).Execute()body := strings.NewReader(`{
"period": "2026-09",
"instructions": {
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "instruction_set",
"livemode": false,
"mocked": true,
"run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"paye": [
{
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"jurisdiction": "Rivers State Internal Revenue Service",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers",
"payee_count": 1
}
],
"pension": [
{
"administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers",
"administrator_name": "example",
"employee_amount": {
"amount": 4200000,
"currency": "NGN"
},
"employer_amount": {
"amount": 5400000,
"currency": "NGN"
}
}
],
"levies": [
{
"code": "nhf",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers"
}
],
"totals": {
"total": {
"amount": 57900000,
"currency": "NGN"
}
},
"period": "2026-09",
"created_at": "2026-09-01T09:00:00Z"
},
"run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}`)
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/remittance/instruction_sets", body)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "ingested_instruction_set",
"livemode": false,
"mocked": true,
"status": "received",
"source": "run",
"period": "2026-09",
"validation_report": {
"entry_count": 0,
"error_count": 0,
"warning_count": 0,
"entries": [
{
"index": 1,
"severity": "error",
"code": "invalid_money_amount",
"detail": "The payee has no verified destination, so this line cannot be paid."
}
]
},
"run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"instructions": {
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "instruction_set",
"livemode": false,
"mocked": true,
"run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"paye": [
{
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"jurisdiction": "Rivers State Internal Revenue Service",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers",
"payee_count": 1
}
],
"pension": [
{
"administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers",
"administrator_name": "example",
"employee_amount": {
"amount": 4200000,
"currency": "NGN"
},
"employer_amount": {
"amount": 5400000,
"currency": "NGN"
}
}
],
"levies": [
{
"code": "nhf",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers"
}
],
"totals": {
"total": {
"amount": 57900000,
"currency": "NGN"
}
},
"period": "2026-09",
"created_at": "2026-09-01T09:00:00Z"
},
"jurisdiction_pack": {
"pack_id": "ng-paye",
"version": "2026.08.1"
},
"accepted_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"created_at": "2026-09-01T09:00:00Z"
}
/v1/remittance/instruction_sets/{instruction_set_id}#Read back one submission and its report
remittance.instruction_sets.retrieve
An instruction set is one month's figures as your payroll handed them over, together with the result of checking every line against the jurisdiction pack it is pinned to. Reading one back tells you which rules it was judged by, and that answer holds after a later pack release.
You get the whole record: its state, the figures it holds, the pack identifier and version it was checked against, and the validation report.
The discrepancies the check raised are not on this record. They are their own collection, at GET /v1/remittance/instruction_sets/{instruction_set_id}/discrepancies.
You now hold the month as it was judged, with the pack version to show for it. What it comes to is GET /v1/remittance/instruction_sets/{instruction_set_id}/totals.
Path parameters
instruction_set_id
string
requiredThe set's identifier: the id returned by POST /v1/remittance/instruction_sets or listed at GET /v1/remittance/instruction_sets, or an import's instruction_set_id. It starts with remit_authority_rail_instruction_.
Returns
The month as we hold it, traceable to the Droomwork payroll run behind it when there was one.
id
string
requiredThe set's identifier, starting remit_authority_rail_instruction_, as listed at GET /v1/remittance/instruction_sets. It never changes; pass it as instruction_set_id to retrieve, accept, reject or remit the set.
object
always "ingested_instruction_set"
requiredAlways ingested_instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
status
string
requiredNothing is committed until accepted.
receivedvalidatingpending_acceptanceacceptedrejectedsource
string
requiredWhere the set came from. Droomwork payroll or your own, by API or by file. Everything downstream behaves identically whichever it was.
runexternal_apiexternal_fileperiod
string
requiredThe month the set covers, as YYYY-MM, such as 2026-09. Filter the list by it with the period query.
run_id
string · nullable
optionalThe Droomwork payroll run the set came from, by its id from POST /v1/payroll/runs or GET /v1/payroll/runs, starting run_enterprise_. Present when source is run; null when the set came from your own payroll.
instructions
InstructionSet
optionalWhat is owed to whom for one run. This shape is owned jointly by RUN and REMIT. RUN row 19 emits it and REMIT row 1 ingests it, from RUN and from external payroll alike. It lives here rather than in either module document so the two cannot drift, which is the failure that would otherwise surface at M3 with RUN already accepted and paid. Totals reconcile to run totals to the kobo, because they sum payslip lines rather than recompute from an aggregate. This is the object REMIT ingests.
11 fields of InstructionSet
id
string
requiredThe instruction set's identifier, which never changes: read it at GET /v1/payroll/runs/{run_id}/instruction_set when Droomwork ran the payroll, and send the set on unchanged to POST /v1/remittance/instruction_sets. Quote it when you ask about the set.
object
always "instruction_set"
requiredAlways instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
run_id
string
requiredThe payroll run this set is owed for, by its id from POST /v1/payroll/runs, which starts with run_enterprise_. The set's totals reconcile to that run's totals to the kobo.
period
string
optionalThe pay period the amounts are owed for, as year and month, for example 2026-09.
paye
array of object
requiredGrouped by the State IRS of the employee's residence, not the employer's location.
5 fields
authority_id
string
requiredThe State Internal Revenue Service this PAYE is owed to, by its id from GET /v1/remittance/authorities, which starts with remit_authority_rail_obligation_. Use it wherever a call names the authority.
jurisdiction
string
requiredThe State Internal Revenue Service this line is grouped under, named in full, for example Rivers State Internal Revenue Service. Read it to label the line; authority_id names the authority in a call.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
payee_count
integer
optionalHow many employees this line's PAYE covers. Optional; when it is present, check it against your own headcount for that state.
reconciliation_reference
string
requiredThe reference that identifies this line when you reconcile it, for example paye-2026-09-rivers. Keep it with your own records so you can trace the line later.
pension
array of object
requiredGrouped by administrator and retirement savings account number.
6 fields
administrator_id
string
requiredThe Pension Fund Administrator these contributions are owed to, by its id from GET /v1/remittance/authorities with kind=pension_administrator, which starts with remit_authority_rail_obligation_. Use it wherever a call names the administrator.
administrator_name
string
optionalThe administrator's name in full, so you can label the line without a second call. Optional; administrator_id is what names the administrator in a call.
employee_amount
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
employer_amount
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
reconciliation_reference
string
requiredThe reference that identifies this line when you reconcile it. Keep it with your own records so you can trace the line later.
levies
array of object
requiredNHF, NSITF, ITF and NHIA totals, each with a reconciliation reference.
3 fields
code
string
requiredWhich levy this line is for: nhf the National Housing Fund, nsitf the Nigeria Social Insurance Trust Fund, itf the Industrial Training Fund, nhia the National Health Insurance Authority. One line per levy.
nhfnsitfitfnhiaamount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
reconciliation_reference
string
requiredThe reference that identifies this levy line when you reconcile it. Keep it with your own records so you can trace the line later.
totals
object
requiredThe set's grand total, which its lines sum to. From a Droomwork run it reconciles to the run's totals to the kobo.
1 field
total
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
validation_report
ValidationReport
requiredThe result of checking a submission before anything is committed. Names every failing entry rather than stopping at the first, so one submission tells you everything to fix. The same shape wherever the platform ingests, validates and reports, which is every bulk intake in every module.
4 fields of ValidationReport
entry_count
integer · minimum 0
requiredHow many entries the submission held: every row in the file or line in the instruction set, whether it passed or not.
error_count
integer · minimum 0
requiredHow many entries failed with an error. Each is named in entries with its position and why, so one submission tells you everything to fix.
warning_count
integer · minimum 0
requiredHow many entries passed with a warning, each named in entries. A warning does not fail the entry; it points at something to confirm before you go ahead.
entries
array of object
optionalOne item per error or warning found, with the row or line it sits on, its severity, a code and what was wrong. Empty or absent when every entry passed clean.
4 fields
index
integer · minimum 1
requiredThe row in a file, or the line in an instruction set.
severity
string
requirederror means the entry failed and must be fixed. warning means it passed, but points at something you should confirm before you go ahead.
errorwarningcode
string
requiredWhy the entry was flagged, as a code you can branch on. detail says the same in words and may change; the code does not.
detail
string
requiredWhat was wrong with the entry, in plain words. Show it beside the row; it may change, so branch on code.
jurisdiction_pack
object
optionalThe jurisdiction pack the set is pinned to, by identifier and version. Every line was recomputed against it, so its rules are the ones the validation report reflects.
2 fields
pack_id
string
optionalWhich jurisdiction pack the set is pinned to, such as ng-paye. We publish the packs and you never send this; with version, it names exactly which rules every line was checked against, and it stays with the set so you can show which rules applied.
version
string
optionalThe pack version the set was checked against, such as 2026.08.1. It's pinned, so a later pack release doesn't change what this set was judged by.
accepted_by
string · nullable
optionalWho accepted the set: the actor that called accept. null until the set is accepted.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
Other responses
Errors it can return
curl -X GET "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceInstructionSetsRetrieve({ instructionSetId: 'remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_instruction_sets_retrieve(instruction_set_id='remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')import os
import requests
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceInstructionSetsRetrieve(instruction_set_id: 'remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceInstructionSetsRetrieve("remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceInstructionSetsRetrieve(instructionSetId: "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceInstructionSetsRetrieve(ctx, "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "ingested_instruction_set",
"livemode": false,
"mocked": true,
"status": "received",
"source": "run",
"period": "2026-09",
"validation_report": {
"entry_count": 0,
"error_count": 0,
"warning_count": 0,
"entries": [
{
"index": 1,
"severity": "error",
"code": "invalid_money_amount",
"detail": "The payee has no verified destination, so this line cannot be paid."
}
]
},
"run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"instructions": {
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "instruction_set",
"livemode": false,
"mocked": true,
"run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"paye": [
{
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"jurisdiction": "Rivers State Internal Revenue Service",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers",
"payee_count": 1
}
],
"pension": [
{
"administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers",
"administrator_name": "example",
"employee_amount": {
"amount": 4200000,
"currency": "NGN"
},
"employer_amount": {
"amount": 5400000,
"currency": "NGN"
}
}
],
"levies": [
{
"code": "nhf",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers"
}
],
"totals": {
"total": {
"amount": 57900000,
"currency": "NGN"
}
},
"period": "2026-09",
"created_at": "2026-09-01T09:00:00Z"
},
"jurisdiction_pack": {
"pack_id": "ng-paye",
"version": "2026.08.1"
},
"accepted_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"created_at": "2026-09-01T09:00:00Z"
}
/v1/remittance/instruction_sets/{instruction_set_id}/accept#Accept an instruction set for remittance
remittance.instruction_sets.accept
This is the moment the figures are committed. Until it happens nothing is filed against the set, and after it this is the set a remittance is built from, so your product can submit when payroll closes and commit later, when somebody has read the report.
Send no request body. You get the whole set back, with its status now accepted and the validation report you decided on still attached.
The set must be waiting on your decision, which is where POST /v1/remittance/instruction_sets leaves it.
Carry the same instruction_set_id to POST /v1/remittance/remittances, which needs the set accepted. A set that is no longer waiting on your decision is refused with conflict.
Path parameters
instruction_set_id
string
requiredThe set's identifier: the id returned by POST /v1/remittance/instruction_sets or listed at GET /v1/remittance/instruction_sets, or an import's instruction_set_id. It starts with remit_authority_rail_instruction_.
Headers
Idempotency-Key
string
requiredA key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.
Returns
The set, with no field on it recording when the decision was taken.
id
string
requiredThe set's identifier, starting remit_authority_rail_instruction_, as listed at GET /v1/remittance/instruction_sets. It never changes; pass it as instruction_set_id to retrieve, accept, reject or remit the set.
object
always "ingested_instruction_set"
requiredAlways ingested_instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
status
string
requiredNothing is committed until accepted.
receivedvalidatingpending_acceptanceacceptedrejectedsource
string
requiredWhere the set came from. Droomwork payroll or your own, by API or by file. Everything downstream behaves identically whichever it was.
runexternal_apiexternal_fileperiod
string
requiredThe month the set covers, as YYYY-MM, such as 2026-09. Filter the list by it with the period query.
run_id
string · nullable
optionalThe Droomwork payroll run the set came from, by its id from POST /v1/payroll/runs or GET /v1/payroll/runs, starting run_enterprise_. Present when source is run; null when the set came from your own payroll.
instructions
InstructionSet
optionalWhat is owed to whom for one run. This shape is owned jointly by RUN and REMIT. RUN row 19 emits it and REMIT row 1 ingests it, from RUN and from external payroll alike. It lives here rather than in either module document so the two cannot drift, which is the failure that would otherwise surface at M3 with RUN already accepted and paid. Totals reconcile to run totals to the kobo, because they sum payslip lines rather than recompute from an aggregate. This is the object REMIT ingests.
11 fields of InstructionSet
id
string
requiredThe instruction set's identifier, which never changes: read it at GET /v1/payroll/runs/{run_id}/instruction_set when Droomwork ran the payroll, and send the set on unchanged to POST /v1/remittance/instruction_sets. Quote it when you ask about the set.
object
always "instruction_set"
requiredAlways instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
run_id
string
requiredThe payroll run this set is owed for, by its id from POST /v1/payroll/runs, which starts with run_enterprise_. The set's totals reconcile to that run's totals to the kobo.
period
string
optionalThe pay period the amounts are owed for, as year and month, for example 2026-09.
paye
array of object
requiredGrouped by the State IRS of the employee's residence, not the employer's location.
5 fields
authority_id
string
requiredThe State Internal Revenue Service this PAYE is owed to, by its id from GET /v1/remittance/authorities, which starts with remit_authority_rail_obligation_. Use it wherever a call names the authority.
jurisdiction
string
requiredThe State Internal Revenue Service this line is grouped under, named in full, for example Rivers State Internal Revenue Service. Read it to label the line; authority_id names the authority in a call.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
payee_count
integer
optionalHow many employees this line's PAYE covers. Optional; when it is present, check it against your own headcount for that state.
reconciliation_reference
string
requiredThe reference that identifies this line when you reconcile it, for example paye-2026-09-rivers. Keep it with your own records so you can trace the line later.
pension
array of object
requiredGrouped by administrator and retirement savings account number.
6 fields
administrator_id
string
requiredThe Pension Fund Administrator these contributions are owed to, by its id from GET /v1/remittance/authorities with kind=pension_administrator, which starts with remit_authority_rail_obligation_. Use it wherever a call names the administrator.
administrator_name
string
optionalThe administrator's name in full, so you can label the line without a second call. Optional; administrator_id is what names the administrator in a call.
employee_amount
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
employer_amount
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
reconciliation_reference
string
requiredThe reference that identifies this line when you reconcile it. Keep it with your own records so you can trace the line later.
levies
array of object
requiredNHF, NSITF, ITF and NHIA totals, each with a reconciliation reference.
3 fields
code
string
requiredWhich levy this line is for: nhf the National Housing Fund, nsitf the Nigeria Social Insurance Trust Fund, itf the Industrial Training Fund, nhia the National Health Insurance Authority. One line per levy.
nhfnsitfitfnhiaamount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
reconciliation_reference
string
requiredThe reference that identifies this levy line when you reconcile it. Keep it with your own records so you can trace the line later.
totals
object
requiredThe set's grand total, which its lines sum to. From a Droomwork run it reconciles to the run's totals to the kobo.
1 field
total
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
validation_report
ValidationReport
requiredThe result of checking a submission before anything is committed. Names every failing entry rather than stopping at the first, so one submission tells you everything to fix. The same shape wherever the platform ingests, validates and reports, which is every bulk intake in every module.
4 fields of ValidationReport
entry_count
integer · minimum 0
requiredHow many entries the submission held: every row in the file or line in the instruction set, whether it passed or not.
error_count
integer · minimum 0
requiredHow many entries failed with an error. Each is named in entries with its position and why, so one submission tells you everything to fix.
warning_count
integer · minimum 0
requiredHow many entries passed with a warning, each named in entries. A warning does not fail the entry; it points at something to confirm before you go ahead.
entries
array of object
optionalOne item per error or warning found, with the row or line it sits on, its severity, a code and what was wrong. Empty or absent when every entry passed clean.
4 fields
index
integer · minimum 1
requiredThe row in a file, or the line in an instruction set.
severity
string
requirederror means the entry failed and must be fixed. warning means it passed, but points at something you should confirm before you go ahead.
errorwarningcode
string
requiredWhy the entry was flagged, as a code you can branch on. detail says the same in words and may change; the code does not.
detail
string
requiredWhat was wrong with the entry, in plain words. Show it beside the row; it may change, so branch on code.
jurisdiction_pack
object
optionalThe jurisdiction pack the set is pinned to, by identifier and version. Every line was recomputed against it, so its rules are the ones the validation report reflects.
2 fields
pack_id
string
optionalWhich jurisdiction pack the set is pinned to, such as ng-paye. We publish the packs and you never send this; with version, it names exactly which rules every line was checked against, and it stays with the set so you can show which rules applied.
version
string
optionalThe pack version the set was checked against, such as 2026.08.1. It's pinned, so a later pack release doesn't change what this set was judged by.
accepted_by
string · nullable
optionalWho accepted the set: the actor that called accept. null until the set is accepted.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
Other responses
Errors it can return
curl -X POST "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/accept" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceInstructionSetsAccept({ instructionSetId: 'remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/accept', {
method: 'POST',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
'Idempotency-Key': crypto.randomUUID(),
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_instruction_sets_accept(instruction_set_id='remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')import os
import uuid
import requests
response = requests.request(
'POST',
'https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/accept',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
'Idempotency-Key': str(uuid.uuid4()),
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceInstructionSetsAccept(instruction_set_id: 'remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/accept');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceInstructionSetsAccept("remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/accept"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.header("Idempotency-Key", UUID.randomUUID().toString())
.method("POST", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceInstructionSetsAccept(instructionSetId: "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/accept");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceInstructionSetsAccept(ctx, "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/accept", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "ingested_instruction_set",
"livemode": false,
"mocked": true,
"status": "accepted",
"source": "run",
"period": "2026-09",
"validation_report": {
"entry_count": 0,
"error_count": 0,
"warning_count": 0,
"entries": [
{
"index": 1,
"severity": "error",
"code": "invalid_money_amount",
"detail": "The payee has no verified destination, so this line cannot be paid."
}
]
},
"run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"instructions": {
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "instruction_set",
"livemode": false,
"mocked": true,
"run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"paye": [
{
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"jurisdiction": "Rivers State Internal Revenue Service",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers",
"payee_count": 1
}
],
"pension": [
{
"administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers",
"administrator_name": "example",
"employee_amount": {
"amount": 4200000,
"currency": "NGN"
},
"employer_amount": {
"amount": 5400000,
"currency": "NGN"
}
}
],
"levies": [
{
"code": "nhf",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers"
}
],
"totals": {
"total": {
"amount": 57900000,
"currency": "NGN"
}
},
"period": "2026-09",
"created_at": "2026-09-01T09:00:00Z"
},
"jurisdiction_pack": {
"pack_id": "ng-paye",
"version": "2026.08.1"
},
"accepted_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"created_at": "2026-09-01T09:00:00Z"
}
/v1/remittance/instruction_sets/{instruction_set_id}/totals#What the month's figures add up to
remittance.instruction_sets.retrieve_totals
This is the number a filing decision rests on: what the month comes to across every authority the set names, in whole minor units with its currency. It also answers whether the figures hold together, so you can check the total before you accept the set and not after it is committed.
You get the grand total with its currency, and a flag saying whether it reconciles: against the originating payroll run when the set came from one, and against the figures' own stated total when it did not.
Nothing else waits on this call. What you hold is one figure to compare with your payroll's own total before you accept the set.
Path parameters
instruction_set_id
string
requiredThe set's identifier: the id returned by POST /v1/remittance/instruction_sets or listed at GET /v1/remittance/instruction_sets, or an import's instruction_set_id. It starts with remit_authority_rail_instruction_.
Returns
The totals, with the reconciliation result.
total
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
by_authority
array of object
optionalOne entry per authority the set pays, with the authority's identifier and the amount owed to it, in whole minor units.
2 fields
authority_id
string
requiredThe authority this amount is owed to, by its id as listed at GET /v1/remittance/authorities, starting remit_authority_rail_obligation_. Look it up at GET /v1/remittance/authorities/{authority_id} for its name, tier and capabilities.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
reconciles_to_run
boolean
requiredTrue when the totals match the originating run to the kobo. Absent a run, this reports whether the lines sum to the stated total.
difference
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
Other responses
Errors it can return
curl -X GET "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/totals" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceInstructionSetsRetrieveTotals({ instructionSetId: 'remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/totals', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_instruction_sets_retrieve_totals(instruction_set_id='remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')import os
import requests
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/totals',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceInstructionSetsRetrieveTotals(instruction_set_id: 'remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/totals');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceInstructionSetsRetrieveTotals("remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/totals"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceInstructionSetsRetrieveTotals(instructionSetId: "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/totals");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceInstructionSetsRetrieveTotals(ctx, "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/totals", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"total": {
"amount": 57900000,
"currency": "NGN"
},
"reconciles_to_run": true,
"by_authority": [
{
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"amount": {
"amount": 7500000,
"currency": "NGN"
}
}
],
"difference": {
"amount": 10000,
"currency": "NGN"
}
}
/v1/remittance/instruction_sets/{instruction_set_id}/discrepancies#See what our validation raised
remittance.discrepancies.list
A discrepancy is a finding our validation raised against your instruction set. Reading them is how a screen in your product shows a reviewer what the validation found, with the figure you submitted beside the one we recomputed.
Send the set's identifier in the path. You get them back, each with its kind, what you submitted, what we recomputed and whether it is still open.
Carry a row's id as discrepancy_id to GET /v1/remittance/instruction_sets/{instruction_set_id}/discrepancies/{discrepancy_id}.
Path parameters
instruction_set_id
string
requiredThe set's identifier: the id returned by POST /v1/remittance/instruction_sets or listed at GET /v1/remittance/instruction_sets, or an import's instruction_set_id. It starts with remit_authority_rail_instruction_.
Query parameters
limit
integer
optionalHow many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.
Returns
A page of discrepancies.
object
always "list"
requiredAlways list. Tells you which kind of record you are looking at, so one handler can read any response.
data
array of Discrepancy
requiredThe records on this page, in the order the list promises. Empty when nothing matched.
11 fields of Discrepancy
id
string
requiredThe discrepancy's identifier, as listed at GET /v1/remittance/instruction_sets/{instruction_set_id}/discrepancies. It never changes; pass it as discrepancy_id when you retrieve or override the discrepancy.
object
always "discrepancy"
requiredAlways discrepancy. Tells you which kind of record you are looking at, so one handler can read any response.
kind
string
requiredrecomputation_mismatchresidency_conflictmissing_identifierunknown_authoritystatus
string
requiredopen while it blocks acceptance, resolved once it's cleared, overridden once you've kept your submitted figure with a reason code at remittance.discrepancies.override. Acceptance needs none left open.
openresolvedoverriddenline
integer
optionalWhich line of the instruction set the discrepancy is on, counting from 1. Absent when it isn't tied to one line.
subject_id
string · nullable
optionalThe person the discrepancy is about, by the subject_id starting sub_ that's on their payslip at GET /v1/payroll/payslips: for example the employee whose residence puts their PAYE with another State IRS. null otherwise.
submitted
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
recomputed
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
difference
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
reason_code
string · nullable
optionalThe reason code you gave when you overrode the discrepancy, kept on the record permanently. null until it is overridden.
overridden_by
string · nullable
optionalWho overrode the discrepancy: the actor that supplied the reason code, recorded permanently. null until it is overridden.
has_more
boolean
requiredtrue when there are more records after this page. Pass the last record's id as starting_after to get the next page.
Other responses
Errors it can return
# query parameters: limit (optional)
curl -X GET "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies?limit=25" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
// query parameters: limit (optional)
const result = await api.remittanceDiscrepanciesList({ instructionSetId: 'remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', limit: 25 });// query parameters: limit (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies?limit=25', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
# query parameters: limit (optional)
result = api.remittance_discrepancies_list(instruction_set_id='remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', limit=25)import os
import requests
# query parameters: limit (optional)
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies?limit=25',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
# query parameters: limit (optional)
$result = $api->remittanceDiscrepanciesList(instruction_set_id: 'remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', limit: 25);<?php
// query parameters: limit (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies?limit=25');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
// query parameters: limit (optional)
var result = api.remittanceDiscrepanciesList("remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", 25);// query parameters: limit (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies?limit=25"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
// query parameters: limit (optional)
var result = api.RemittanceDiscrepanciesList(instructionSetId: "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", limit: 25);// query parameters: limit (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies?limit=25");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
// query parameters: limit (optional)
result, _, err := client.REMITAPI.RemittanceDiscrepanciesList(ctx, "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Limit(25).Execute()// query parameters: limit (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies?limit=25", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"object": "list",
"data": [
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "discrepancy",
"kind": "recomputation_mismatch",
"status": "open",
"submitted": {
"amount": 41250000,
"currency": "NGN"
},
"recomputed": {
"amount": 41250000,
"currency": "NGN"
},
"line": 1,
"subject_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"difference": {
"amount": 10000,
"currency": "NGN"
},
"reason_code": "example",
"overridden_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}
],
"has_more": true
}
/v1/remittance/instruction_sets/{instruction_set_id}/discrepancies/{discrepancy_id}#Compare your figure with ours
remittance.discrepancies.retrieve
This reads one discrepancy back as our validation left it: the figure you submitted and the figure we recomputed against the jurisdiction pack. So a reviewer handed one can put the two figures side by side and decide whether to stand by yours.
Send the set's identifier and the discrepancy's identifier in the path. You get the one record: its kind, both figures in whole minor units with their currency, and whether it is still open.
line is absent when the discrepancy is not tied to one line, and difference is absent when it is not about the figure, so check for each before you print it.
Keep the figure you submitted at POST /v1/remittance/instruction_sets/{instruction_set_id}/discrepancies/{discrepancy_id}/override, passing this id as discrepancy_id.
Path parameters
instruction_set_id
string
requiredThe set's identifier: the id returned by POST /v1/remittance/instruction_sets or listed at GET /v1/remittance/instruction_sets, or an import's instruction_set_id. It starts with remit_authority_rail_instruction_.
discrepancy_id
string
requiredThe discrepancy's identifier, from the id of a discrepancy listed at GET /v1/remittance/instruction_sets/{instruction_set_id}/discrepancies. It belongs to the set in the path.
Returns
The discrepancy.
id
string
requiredThe discrepancy's identifier, as listed at GET /v1/remittance/instruction_sets/{instruction_set_id}/discrepancies. It never changes; pass it as discrepancy_id when you retrieve or override the discrepancy.
object
always "discrepancy"
requiredAlways discrepancy. Tells you which kind of record you are looking at, so one handler can read any response.
kind
string
requiredrecomputation_mismatchresidency_conflictmissing_identifierunknown_authoritystatus
string
requiredopen while it blocks acceptance, resolved once it's cleared, overridden once you've kept your submitted figure with a reason code at remittance.discrepancies.override. Acceptance needs none left open.
openresolvedoverriddenline
integer
optionalWhich line of the instruction set the discrepancy is on, counting from 1. Absent when it isn't tied to one line.
subject_id
string · nullable
optionalThe person the discrepancy is about, by the subject_id starting sub_ that's on their payslip at GET /v1/payroll/payslips: for example the employee whose residence puts their PAYE with another State IRS. null otherwise.
submitted
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
recomputed
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
difference
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
reason_code
string · nullable
optionalThe reason code you gave when you overrode the discrepancy, kept on the record permanently. null until it is overridden.
overridden_by
string · nullable
optionalWho overrode the discrepancy: the actor that supplied the reason code, recorded permanently. null until it is overridden.
Other responses
Errors it can return
curl -X GET "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies/%7Bdiscrepancy_id%7D" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceDiscrepanciesRetrieve({ instructionSetId: 'remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', discrepancyId: '{discrepancy_id}' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies/%7Bdiscrepancy_id%7D', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_discrepancies_retrieve(instruction_set_id='remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', discrepancy_id='{discrepancy_id}')import os
import requests
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies/%7Bdiscrepancy_id%7D',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceDiscrepanciesRetrieve(instruction_set_id: 'remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', discrepancy_id: '{discrepancy_id}');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies/%7Bdiscrepancy_id%7D');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceDiscrepanciesRetrieve("remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "{discrepancy_id}");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies/%7Bdiscrepancy_id%7D"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceDiscrepanciesRetrieve(instructionSetId: "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", discrepancyId: "{discrepancy_id}");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies/%7Bdiscrepancy_id%7D");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceDiscrepanciesRetrieve(ctx, "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "{discrepancy_id}").Execute()req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies/%7Bdiscrepancy_id%7D", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "discrepancy",
"kind": "recomputation_mismatch",
"status": "open",
"submitted": {
"amount": 41250000,
"currency": "NGN"
},
"recomputed": {
"amount": 41250000,
"currency": "NGN"
},
"line": 1,
"subject_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"difference": {
"amount": 10000,
"currency": "NGN"
},
"reason_code": "example",
"overridden_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}
/v1/remittance/instruction_sets/{instruction_set_id}/discrepancies/{discrepancy_id}/override#Override a discrepancy with a reason
remittance.discrepancies.override
You have read a discrepancy and decided the figure you submitted is the one to keep. Overriding is how you record that decision, so a reviewer working through a set in your product can take each one off the list.
Send a reason_code saying why your figure is the one to keep. You get the whole discrepancy back, both figures unchanged, and its status now overridden.
Call POST /v1/remittance/instruction_sets or POST /v1/remittance/imports first; either one validates your lines and raises the discrepancies you override here.
Accept the set at POST /v1/remittance/instruction_sets/{instruction_set_id}/accept.
Path parameters
instruction_set_id
string
requiredThe set's identifier: the id returned by POST /v1/remittance/instruction_sets or listed at GET /v1/remittance/instruction_sets, or an import's instruction_set_id. It starts with remit_authority_rail_instruction_.
discrepancy_id
string
requiredThe discrepancy's identifier, from the id of a discrepancy listed at GET /v1/remittance/instruction_sets/{instruction_set_id}/discrepancies. It belongs to the set in the path.
Headers
Idempotency-Key
string
requiredA key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.
Body
reason_code
string
requiredRecorded permanently with the actor who supplied it.
note
string
optionalAnything a reviewer should know beyond the code, in your words. Optional; it goes on the record with the reason code.
Returns
The discrepancy, with the kind it was raised under, so your record names which finding you set aside.
id
string
requiredThe discrepancy's identifier, as listed at GET /v1/remittance/instruction_sets/{instruction_set_id}/discrepancies. It never changes; pass it as discrepancy_id when you retrieve or override the discrepancy.
object
always "discrepancy"
requiredAlways discrepancy. Tells you which kind of record you are looking at, so one handler can read any response.
kind
string
requiredrecomputation_mismatchresidency_conflictmissing_identifierunknown_authoritystatus
string
requiredopen while it blocks acceptance, resolved once it's cleared, overridden once you've kept your submitted figure with a reason code at remittance.discrepancies.override. Acceptance needs none left open.
openresolvedoverriddenline
integer
optionalWhich line of the instruction set the discrepancy is on, counting from 1. Absent when it isn't tied to one line.
subject_id
string · nullable
optionalThe person the discrepancy is about, by the subject_id starting sub_ that's on their payslip at GET /v1/payroll/payslips: for example the employee whose residence puts their PAYE with another State IRS. null otherwise.
submitted
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
recomputed
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
difference
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
reason_code
string · nullable
optionalThe reason code you gave when you overrode the discrepancy, kept on the record permanently. null until it is overridden.
overridden_by
string · nullable
optionalWho overrode the discrepancy: the actor that supplied the reason code, recorded permanently. null until it is overridden.
Other responses
Errors it can return
curl -X POST "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies/%7Bdiscrepancy_id%7D/override" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"reason_code":"example","note":"example"}'import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceDiscrepanciesOverride({
instructionSetId: 'remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z',
discrepancyId: '{discrepancy_id}',
idempotencyKey: crypto.randomUUID(),
remitDiscrepancyOverrideRequest: {"reasonCode":"example","note":"example"},
});const response = await fetch('https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies/%7Bdiscrepancy_id%7D/override', {
method: 'POST',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
"reason_code": "example",
"note": "example"
}),
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_discrepancies_override(instruction_set_id='remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', discrepancy_id='{discrepancy_id}', body={"reason_code": "example", "note": "example"})import os
import uuid
import requests
response = requests.request(
'POST',
'https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies/%7Bdiscrepancy_id%7D/override',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
'Idempotency-Key': str(uuid.uuid4()),
},
json={"reason_code": "example", "note": "example"},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceDiscrepanciesOverride($idempotencyKey, json_decode('{"reason_code":"example","note":"example"}', true));<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies/%7Bdiscrepancy_id%7D/override');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
'Content-Type: application/json',
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
],
CURLOPT_POSTFIELDS => '{"reason_code":"example","note":"example"}',
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceDiscrepanciesOverride("remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "{discrepancy_id}", idempotencyKey, body);var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies/%7Bdiscrepancy_id%7D/override"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.header("Content-Type", "application/json")
.header("Idempotency-Key", UUID.randomUUID().toString())
.method("POST", HttpRequest.BodyPublishers.ofString("""
{
"reason_code": "example",
"note": "example"
}
"""))
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceDiscrepanciesOverride(instructionSetId: "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", discrepancyId: "{discrepancy_id}", idempotencyKey, body);using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies/%7Bdiscrepancy_id%7D/override");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent("""
{
"reason_code": "example",
"note": "example"
}
""", Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceDiscrepanciesOverride(ctx, "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "{discrepancy_id}").IdempotencyKey(key).RemitDiscrepancyOverrideRequest(body).Execute()body := strings.NewReader(`{
"reason_code": "example",
"note": "example"
}`)
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/discrepancies/%7Bdiscrepancy_id%7D/override", body)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "discrepancy",
"kind": "recomputation_mismatch",
"status": "open",
"submitted": {
"amount": 41250000,
"currency": "NGN"
},
"recomputed": {
"amount": 41250000,
"currency": "NGN"
},
"line": 1,
"subject_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"difference": {
"amount": 10000,
"currency": "NGN"
},
"reason_code": "example",
"overridden_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}
/v1/remittance/imports#See how your file submissions validated
remittance.imports.list
This gives you every file you have sent for checking, each with the report on the rows it held. So a screen in your product can separate the uploads that came back clean from the ones that still have rows to correct, without opening each one.
Send nothing required. You get the records, each carrying its status, how many rows the file held, how many failed, how many were flagged, and an entry for each failure or flag, naming the row it sits on.
An import does not name the file it came from or the period it covered, so pair its id with both of them.
Read one back at GET /v1/remittance/imports/{import_id}; the list already carries each one whole. Send a corrected file at POST /v1/remittance/imports.
Query parameters
limit
integer
optionalHow many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.
starting_after
string
optionalThe id of the last record on the previous page of this same list. Leave it out to get the first page; when a page comes back with has_more true, send its last record's id here to get the page after it.
Returns
A page of imports, each with created_at where there is one, which your own log can keep.
object
always "list"
requiredAlways list. Tells you which kind of record you are looking at, so one handler can read any response.
data
array of Import
requiredThe records on this page, in the order the list promises. Empty when nothing matched.
8 fields of Import
id
string
requiredThe import's identifier, assigned at POST /v1/remittance/imports and starting remit_authority_rail_instruction_. It never changes; pass it as import_id at GET /v1/remittance/imports/{import_id} to read the validation report.
object
always "remittance_import"
requiredAlways remittance_import. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
status
string
requiredvalidating while the rows are checked, pending_acceptance once the report is back, accepted or rejected once you accept or reject the instruction set it produced (instruction_set_id). Nothing is committed before accepted.
validatingpending_acceptanceacceptedrejectedinstruction_set_id
string · nullable
optionalThe id of the instruction set made from the file, starting remit_authority_rail_instruction_, or null until there is one. Read it at GET /v1/remittance/instruction_sets/{instruction_set_id}, accept or reject it, or list its discrepancies.
validation_report
ValidationReport
requiredThe result of checking a submission before anything is committed. Names every failing entry rather than stopping at the first, so one submission tells you everything to fix. The same shape wherever the platform ingests, validates and reports, which is every bulk intake in every module.
4 fields of ValidationReport
entry_count
integer · minimum 0
requiredHow many entries the submission held: every row in the file or line in the instruction set, whether it passed or not.
error_count
integer · minimum 0
requiredHow many entries failed with an error. Each is named in entries with its position and why, so one submission tells you everything to fix.
warning_count
integer · minimum 0
requiredHow many entries passed with a warning, each named in entries. A warning does not fail the entry; it points at something to confirm before you go ahead.
entries
array of object
optionalOne item per error or warning found, with the row or line it sits on, its severity, a code and what was wrong. Empty or absent when every entry passed clean.
4 fields
index
integer · minimum 1
requiredThe row in a file, or the line in an instruction set.
severity
string
requirederror means the entry failed and must be fixed. warning means it passed, but points at something you should confirm before you go ahead.
errorwarningcode
string
requiredWhy the entry was flagged, as a code you can branch on. detail says the same in words and may change; the code does not.
detail
string
requiredWhat was wrong with the entry, in plain words. Show it beside the row; it may change, so branch on code.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
has_more
boolean
requiredtrue when there are more records after this page. Pass the last record's id as starting_after to get the next page.
Other responses
Errors it can return
# query parameters: limit (optional), starting_after (optional)
curl -X GET "https://sandbox.droomwork.io/v1/remittance/imports?limit=25" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
// query parameters: limit (optional), starting_after (optional)
const result = await api.remittanceImportsList({ limit: 25 });// query parameters: limit (optional), starting_after (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/remittance/imports?limit=25', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
# query parameters: limit (optional), starting_after (optional)
result = api.remittance_imports_list(limit=25)import os
import requests
# query parameters: limit (optional), starting_after (optional)
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/imports?limit=25',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
# query parameters: limit (optional), starting_after (optional)
$result = $api->remittanceImportsList(limit: 25);<?php
// query parameters: limit (optional), starting_after (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/imports?limit=25');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
// query parameters: limit (optional), starting_after (optional)
var result = api.remittanceImportsList(25, null);// query parameters: limit (optional), starting_after (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/imports?limit=25"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
// query parameters: limit (optional), starting_after (optional)
var result = api.RemittanceImportsList(limit: 25);// query parameters: limit (optional), starting_after (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/imports?limit=25");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
// query parameters: limit (optional), starting_after (optional)
result, _, err := client.REMITAPI.RemittanceImportsList(ctx).Limit(25).Execute()// query parameters: limit (optional), starting_after (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/imports?limit=25", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"object": "list",
"data": [
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance_import",
"livemode": false,
"mocked": true,
"status": "validating",
"validation_report": {
"entry_count": 0,
"error_count": 0,
"warning_count": 0,
"entries": [
{
"index": 1,
"severity": "error",
"code": "invalid_money_amount",
"detail": "The payee has no verified destination, so this line cannot be paid."
}
]
},
"instruction_set_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"created_at": "2026-09-01T09:00:00Z"
}
],
"has_more": true
}
/v1/remittance/imports#Submit an instruction set as a file
remittance.imports.create
This takes a month of statutory figures as a file, for a payroll system that cannot post them to this API. One upload comes back naming every row that failed, so you can put the whole file right in one pass.
Send the file as the file part of a multipart/form-data body, with the period it covers as YYYY-MM. You get the import back with its id and its validation report.
Nothing has to exist first.
An import's id starts remit_authority_rail_instruction_, which is also the prefix an instruction set carries, so keep the two apart in your own store.
A file with failing rows still answers 201: the failures are reported inside the import, not as a refusal. Carry the id as import_id to GET /v1/remittance/imports/{import_id} to read the report again.
Headers
Idempotency-Key
string
requiredA key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.
Returns
The import, carrying no period of its own, though you sent one with the file.
id
string
requiredThe import's identifier, assigned at POST /v1/remittance/imports and starting remit_authority_rail_instruction_. It never changes; pass it as import_id at GET /v1/remittance/imports/{import_id} to read the validation report.
object
always "remittance_import"
requiredAlways remittance_import. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
status
string
requiredvalidating while the rows are checked, pending_acceptance once the report is back, accepted or rejected once you accept or reject the instruction set it produced (instruction_set_id). Nothing is committed before accepted.
validatingpending_acceptanceacceptedrejectedinstruction_set_id
string · nullable
optionalThe id of the instruction set made from the file, starting remit_authority_rail_instruction_, or null until there is one. Read it at GET /v1/remittance/instruction_sets/{instruction_set_id}, accept or reject it, or list its discrepancies.
validation_report
ValidationReport
requiredThe result of checking a submission before anything is committed. Names every failing entry rather than stopping at the first, so one submission tells you everything to fix. The same shape wherever the platform ingests, validates and reports, which is every bulk intake in every module.
4 fields of ValidationReport
entry_count
integer · minimum 0
requiredHow many entries the submission held: every row in the file or line in the instruction set, whether it passed or not.
error_count
integer · minimum 0
requiredHow many entries failed with an error. Each is named in entries with its position and why, so one submission tells you everything to fix.
warning_count
integer · minimum 0
requiredHow many entries passed with a warning, each named in entries. A warning does not fail the entry; it points at something to confirm before you go ahead.
entries
array of object
optionalOne item per error or warning found, with the row or line it sits on, its severity, a code and what was wrong. Empty or absent when every entry passed clean.
4 fields
index
integer · minimum 1
requiredThe row in a file, or the line in an instruction set.
severity
string
requirederror means the entry failed and must be fixed. warning means it passed, but points at something you should confirm before you go ahead.
errorwarningcode
string
requiredWhy the entry was flagged, as a code you can branch on. detail says the same in words and may change; the code does not.
detail
string
requiredWhat was wrong with the entry, in plain words. Show it beside the row; it may change, so branch on code.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
Other responses
Errors it can return
curl -X POST "https://sandbox.droomwork.io/v1/remittance/imports" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceImportsCreate({});const response = await fetch('https://sandbox.droomwork.io/v1/remittance/imports', {
method: 'POST',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
'Idempotency-Key': crypto.randomUUID(),
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_imports_create()import os
import uuid
import requests
response = requests.request(
'POST',
'https://sandbox.droomwork.io/v1/remittance/imports',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
'Idempotency-Key': str(uuid.uuid4()),
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceImportsCreate();<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/imports');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceImportsCreate();var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/imports"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.header("Idempotency-Key", UUID.randomUUID().toString())
.method("POST", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceImportsCreate();using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/remittance/imports");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceImportsCreate(ctx).Execute()req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/remittance/imports", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance_import",
"livemode": false,
"mocked": true,
"status": "validating",
"validation_report": {
"entry_count": 0,
"error_count": 0,
"warning_count": 0,
"entries": [
{
"index": 1,
"severity": "error",
"code": "invalid_money_amount",
"detail": "The payee has no verified destination, so this line cannot be paid."
}
]
},
"instruction_set_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"created_at": "2026-09-01T09:00:00Z"
}
/v1/remittance/imports/{import_id}#Check an upload and the rows that failed
remittance.imports.retrieve
An import is one file you sent and the report on what was in it. This reads that report back from the id alone, so a correction screen in your product can list the rows to fix and nothing else.
Send the import's id in the path. You get its status, the row counts, and an entry for everything that failed or was flagged, each naming the row it sits on, a code to match on and a sentence for a person.
A warning does not fail the row: it passed and points at something to confirm. Only an error has to be fixed.
An import_id nothing matches is refused with not_found. See every upload at GET /v1/remittance/imports, and send a corrected file at POST /v1/remittance/imports.
Path parameters
import_id
string
requiredThe import's identifier, from the id returned by POST /v1/remittance/imports or listed at GET /v1/remittance/imports. It starts with remit_authority_rail_instruction_.
Returns
The import, with created_at where there is one, to date the upload in your own store.
id
string
requiredThe import's identifier, assigned at POST /v1/remittance/imports and starting remit_authority_rail_instruction_. It never changes; pass it as import_id at GET /v1/remittance/imports/{import_id} to read the validation report.
object
always "remittance_import"
requiredAlways remittance_import. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
status
string
requiredvalidating while the rows are checked, pending_acceptance once the report is back, accepted or rejected once you accept or reject the instruction set it produced (instruction_set_id). Nothing is committed before accepted.
validatingpending_acceptanceacceptedrejectedinstruction_set_id
string · nullable
optionalThe id of the instruction set made from the file, starting remit_authority_rail_instruction_, or null until there is one. Read it at GET /v1/remittance/instruction_sets/{instruction_set_id}, accept or reject it, or list its discrepancies.
validation_report
ValidationReport
requiredThe result of checking a submission before anything is committed. Names every failing entry rather than stopping at the first, so one submission tells you everything to fix. The same shape wherever the platform ingests, validates and reports, which is every bulk intake in every module.
4 fields of ValidationReport
entry_count
integer · minimum 0
requiredHow many entries the submission held: every row in the file or line in the instruction set, whether it passed or not.
error_count
integer · minimum 0
requiredHow many entries failed with an error. Each is named in entries with its position and why, so one submission tells you everything to fix.
warning_count
integer · minimum 0
requiredHow many entries passed with a warning, each named in entries. A warning does not fail the entry; it points at something to confirm before you go ahead.
entries
array of object
optionalOne item per error or warning found, with the row or line it sits on, its severity, a code and what was wrong. Empty or absent when every entry passed clean.
4 fields
index
integer · minimum 1
requiredThe row in a file, or the line in an instruction set.
severity
string
requirederror means the entry failed and must be fixed. warning means it passed, but points at something you should confirm before you go ahead.
errorwarningcode
string
requiredWhy the entry was flagged, as a code you can branch on. detail says the same in words and may change; the code does not.
detail
string
requiredWhat was wrong with the entry, in plain words. Show it beside the row; it may change, so branch on code.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
Other responses
Errors it can return
curl -X GET "https://sandbox.droomwork.io/v1/remittance/imports/%7Bimport_id%7D" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceImportsRetrieve({ importId: '{import_id}' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/imports/%7Bimport_id%7D', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_imports_retrieve(import_id='{import_id}')import os
import requests
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/imports/%7Bimport_id%7D',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceImportsRetrieve(import_id: '{import_id}');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/imports/%7Bimport_id%7D');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceImportsRetrieve("{import_id}");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/imports/%7Bimport_id%7D"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceImportsRetrieve(importId: "{import_id}");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/imports/%7Bimport_id%7D");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceImportsRetrieve(ctx, "{import_id}").Execute()req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/imports/%7Bimport_id%7D", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance_import",
"livemode": false,
"mocked": true,
"status": "validating",
"validation_report": {
"entry_count": 0,
"error_count": 0,
"warning_count": 0,
"entries": [
{
"index": 1,
"severity": "error",
"code": "invalid_money_amount",
"detail": "The payee has no verified destination, so this line cannot be paid."
}
]
},
"instruction_set_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"created_at": "2026-09-01T09:00:00Z"
}
/v1/remittance/obligations#What you still owe each authority
remittance.obligations.list
This is the ledger of what you owe each authority: one record for one authority for one month. So your product can show what is outstanding and when it is due, without keeping a deadline table of its own.
Send nothing required. You get the records, each with the authority as authority_id, the month as period, the liability in amount, what has settled against it, what is left in balance, and the date it is due.
Read balance.amount and not balance; balance is the object and amount is the figure.
Pass a record's id as obligation_id to GET /v1/remittance/obligations/{obligation_id}; the list already carries each one whole.
Query parameters
limit
integer
optionalHow many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.
starting_after
string
optionalThe id of the last record on the previous page of this same list. Leave it out to get the first page; when a page comes back with has_more true, send its last record's id here to get the page after it.
authority_id
string
optionalReturn only what's owed to this authority, by its id as listed at GET /v1/remittance/authorities, starting remit_authority_rail_obligation_. Leave it out to get every authority.
period
string
optionalReturn only obligations for this month, as YYYY-MM, such as 2026-09. Leave it out to get every period.
settled
boolean
optionaltrue for obligations with nothing left to pay, false for those with a balance outstanding. Leave it out to get both.
Returns
A page of obligations.
object
always "list"
requiredAlways list. Tells you which kind of record you are looking at, so one handler can read any response.
data
array of Obligation
requiredThe records on this page, in the order the list promises. Empty when nothing matched.
12 fields of Obligation
id
string
requiredThe obligation's identifier, assigned when you accept an instruction set or record one at POST /v1/remittance/obligations, starting remit_authority_rail_obligation_. It never changes; pass it as obligation_id to retrieve it.
object
always "obligation"
requiredAlways obligation. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
authority_id
string
requiredThe authority the amount is owed to: its id from GET /v1/remittance/authorities, starting remit_authority_rail_obligation_. GET /v1/remittance/authorities/{authority_id} gives its name, tier and capabilities; filter obligations by it.
authority_name
string
optionalThe authority's name as you'd write it, such as Rivers State Internal Revenue Service. For display; authority_id is what you filter and match on.
period
string
requiredThe month the liability arises from, as YYYY-MM, such as 2026-09. One obligation covers one authority for one period; filter the list by it with the period query.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
settled
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
balance
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
deadline
string · date
requiredDerived from the pack calendar rules, never entered by hand.
receipt_ids
array of string
optionalThe id of each vaulted receipt that settles against this obligation, empty until one is vaulted. Retrieve a receipt at GET /v1/remittance/receipts/{receipt_id} for the authority's reference and the document.
has_more
boolean
requiredtrue when there are more records after this page. Pass the last record's id as starting_after to get the next page.
Other responses
Errors it can return
# query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional), settled (optional)
curl -X GET "https://sandbox.droomwork.io/v1/remittance/obligations?limit=25&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&period=2026-09&settled=false" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
// query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional), settled (optional)
const result = await api.remittanceObligationsList({ limit: 25, authorityId: 'remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', period: '2026-09', settled: false });// query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional), settled (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/remittance/obligations?limit=25&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&period=2026-09&settled=false', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
# query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional), settled (optional)
result = api.remittance_obligations_list(limit=25, authority_id='remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', period='2026-09', settled=false)import os
import requests
# query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional), settled (optional)
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/obligations?limit=25&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&period=2026-09&settled=false',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
# query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional), settled (optional)
$result = $api->remittanceObligationsList(limit: 25, authority_id: 'remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', period: '2026-09', settled: false);<?php
// query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional), settled (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/obligations?limit=25&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&period=2026-09&settled=false');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
// query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional), settled (optional)
var result = api.remittanceObligationsList(25, null, "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "2026-09", false);// query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional), settled (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/obligations?limit=25&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&period=2026-09&settled=false"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
// query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional), settled (optional)
var result = api.RemittanceObligationsList(limit: 25, authorityId: "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", period: "2026-09", settled: false);// query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional), settled (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/obligations?limit=25&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&period=2026-09&settled=false");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
// query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional), settled (optional)
result, _, err := client.REMITAPI.RemittanceObligationsList(ctx).Limit(25).AuthorityId("remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Period("2026-09").Settled(false).Execute()// query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional), settled (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/obligations?limit=25&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&period=2026-09&settled=false", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"object": "list",
"data": [
{
"id": "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "obligation",
"livemode": false,
"mocked": true,
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"period": "2026-09",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"settled": {
"amount": 41250000,
"currency": "NGN"
},
"balance": {
"amount": 41250000,
"currency": "NGN"
},
"deadline": "2026-09-01",
"authority_name": "Sandbox State Internal Revenue Service",
"receipt_ids": [
"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
]
}
],
"has_more": true
}
/v1/remittance/obligations#Record a liability you already owe
remittance.obligations.create
This records a liability you owe an authority as an obligation of its own. So a debt that reached you from somewhere else is held in the same ledger, and reads back exactly like any obligation at GET /v1/remittance/obligations.
Send the period the liability arises from, as YYYY-MM. You get the obligation back with its own id, the authority it is owed to, the amount, what has settled against it, the balance left to pay and the date it is due.
Nothing has to exist first.
One obligation covers one authority for one period, so a second month or a second authority is a second call.
Carry the id as obligation_id to GET /v1/remittance/obligations/{obligation_id} to read the record back, and see the whole ledger at GET /v1/remittance/obligations.
Headers
Idempotency-Key
string
requiredA key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.
Body optional
authority
string
optionalThe authority the amount is owed to.
period
string
optionalThe period the obligation arises from, as YYYY-MM.
Returns
The recorded obligation.
id
string
requiredThe obligation's identifier, assigned when you accept an instruction set or record one at POST /v1/remittance/obligations, starting remit_authority_rail_obligation_. It never changes; pass it as obligation_id to retrieve it.
object
always "obligation"
requiredAlways obligation. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
authority_id
string
requiredThe authority the amount is owed to: its id from GET /v1/remittance/authorities, starting remit_authority_rail_obligation_. GET /v1/remittance/authorities/{authority_id} gives its name, tier and capabilities; filter obligations by it.
authority_name
string
optionalThe authority's name as you'd write it, such as Rivers State Internal Revenue Service. For display; authority_id is what you filter and match on.
period
string
requiredThe month the liability arises from, as YYYY-MM, such as 2026-09. One obligation covers one authority for one period; filter the list by it with the period query.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
settled
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
balance
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
deadline
string · date
requiredDerived from the pack calendar rules, never entered by hand.
receipt_ids
array of string
optionalThe id of each vaulted receipt that settles against this obligation, empty until one is vaulted. Retrieve a receipt at GET /v1/remittance/receipts/{receipt_id} for the authority's reference and the document.
Other responses
Errors it can return
curl -X POST "https://sandbox.droomwork.io/v1/remittance/obligations" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"authority":"example","period":"2026-09"}'import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceObligationsCreate({});const response = await fetch('https://sandbox.droomwork.io/v1/remittance/obligations', {
method: 'POST',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
"authority": "example",
"period": "2026-09"
}),
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_obligations_create()import os
import uuid
import requests
response = requests.request(
'POST',
'https://sandbox.droomwork.io/v1/remittance/obligations',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
'Idempotency-Key': str(uuid.uuid4()),
},
json={"authority": "example", "period": "2026-09"},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceObligationsCreate();<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/obligations');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
'Content-Type: application/json',
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
],
CURLOPT_POSTFIELDS => '{"authority":"example","period":"2026-09"}',
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceObligationsCreate();var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/obligations"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.header("Content-Type", "application/json")
.header("Idempotency-Key", UUID.randomUUID().toString())
.method("POST", HttpRequest.BodyPublishers.ofString("""
{
"authority": "example",
"period": "2026-09"
}
"""))
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceObligationsCreate();using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/remittance/obligations");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent("""
{
"authority": "example",
"period": "2026-09"
}
""", Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceObligationsCreate(ctx).Execute()body := strings.NewReader(`{
"authority": "example",
"period": "2026-09"
}`)
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/remittance/obligations", body)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "obligation",
"livemode": false,
"mocked": true,
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"period": "2026-09",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"settled": {
"amount": 41250000,
"currency": "NGN"
},
"balance": {
"amount": 41250000,
"currency": "NGN"
},
"deadline": "2026-09-01",
"authority_name": "Sandbox State Internal Revenue Service",
"receipt_ids": [
"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
]
}
/v1/remittance/obligations/{obligation_id}#Check one liability and its balance
remittance.obligations.retrieve
An obligation is what you owe one authority for one month: the liability, what has settled against it, the balance left to pay, and the date it is due. So one identifier your system already stores puts the liability, the balance and the due date on a screen, and you keep no figures of your own.
Send the obligation's id in the path, which starts remit_authority_rail_obligation_. You get that one record back whole, with the authority named as well as identified.
Read balance.amount and not balance; balance is the object and amount is the figure.
The deadline comes with the record and is not something you set.
An obligation_id nothing holds answers not_found. See the whole ledger at GET /v1/remittance/obligations.
Path parameters
obligation_id
string
requiredThe obligation's identifier, from the id of an obligation listed at GET /v1/remittance/obligations or recorded at POST /v1/remittance/obligations. It starts with remit_authority_rail_obligation_.
Returns
The obligation.
id
string
requiredThe obligation's identifier, assigned when you accept an instruction set or record one at POST /v1/remittance/obligations, starting remit_authority_rail_obligation_. It never changes; pass it as obligation_id to retrieve it.
object
always "obligation"
requiredAlways obligation. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
authority_id
string
requiredThe authority the amount is owed to: its id from GET /v1/remittance/authorities, starting remit_authority_rail_obligation_. GET /v1/remittance/authorities/{authority_id} gives its name, tier and capabilities; filter obligations by it.
authority_name
string
optionalThe authority's name as you'd write it, such as Rivers State Internal Revenue Service. For display; authority_id is what you filter and match on.
period
string
requiredThe month the liability arises from, as YYYY-MM, such as 2026-09. One obligation covers one authority for one period; filter the list by it with the period query.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
settled
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
balance
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
deadline
string · date
requiredDerived from the pack calendar rules, never entered by hand.
receipt_ids
array of string
optionalThe id of each vaulted receipt that settles against this obligation, empty until one is vaulted. Retrieve a receipt at GET /v1/remittance/receipts/{receipt_id} for the authority's reference and the document.
Other responses
Errors it can return
curl -X GET "https://sandbox.droomwork.io/v1/remittance/obligations/remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceObligationsRetrieve({ obligationId: 'remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/obligations/remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_obligations_retrieve(obligation_id='remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')import os
import requests
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/obligations/remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceObligationsRetrieve(obligation_id: 'remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/obligations/remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceObligationsRetrieve("remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/obligations/remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceObligationsRetrieve(obligationId: "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/obligations/remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceObligationsRetrieve(ctx, "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/obligations/remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "obligation",
"livemode": false,
"mocked": true,
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"period": "2026-09",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"settled": {
"amount": 41250000,
"currency": "NGN"
},
"balance": {
"amount": 41250000,
"currency": "NGN"
},
"deadline": "2026-09-01",
"authority_name": "Sandbox State Internal Revenue Service",
"receipt_ids": [
"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
]
}
/v1/remittance/calendar_entries#See when each filing falls due
remittance.calendar_entries.list
This is your statutory filing calendar: what falls due to each authority, and for which month. So a deadline screen in your product gets its dates from the jurisdiction pack, and never from anything you typed in.
You send nothing. Each entry names the authority in authority_id, the month it covers in period, the date the filing is due in deadline, and what is owed by then in amount, in whole minor units with its currency.
penalty_formula is text from the pack and not a figure: what filing late costs depends on when you file. Show it; do not compute with it.
Read one at GET /v1/remittance/calendar_entries/{calendar_entry_id}, passing an entry's id. A calendar entry says what is due and when; what is still outstanding sits on the obligation, at GET /v1/remittance/obligations.
Query parameters
limit
integer
optionalHow many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.
due_before
string
optionalReturn only deadlines that fall before this date, as YYYY-MM-DD, such as 2026-09-30. Leave it out to get every deadline.
authority_id
string
optionalReturn only the deadlines for this authority, by its id as listed at GET /v1/remittance/authorities, starting remit_authority_rail_obligation_. Leave it out to get every authority.
Returns
A page of calendar entries, each carrying its own lead time where there is one.
object
always "list"
requiredAlways list. Tells you which kind of record you are looking at, so one handler can read any response.
data
array of CalendarEntry
requiredThe records on this page, in the order the list promises. Empty when nothing matched.
10 fields of CalendarEntry
id
string
requiredThe deadline's identifier, as listed at GET /v1/remittance/calendar_entries, starting remit_authority_rail_obligation_. It never changes; pass it as calendar_entry_id at GET /v1/remittance/calendar_entries/{calendar_entry_id}.
object
always "calendar_entry"
requiredAlways calendar_entry. Tells you which kind of record you are looking at, so one handler can read any response.
authority_id
string
requiredThe authority this deadline is for: its id from GET /v1/remittance/authorities, starting remit_authority_rail_obligation_. GET /v1/remittance/authorities/{authority_id} gives its name, tier and capabilities; filter the calendar by it.
authority_name
string
optionalThe authority's name as you'd write it, such as Rivers State Internal Revenue Service. For display; authority_id is what you filter and match on.
period
string
requiredThe month the filing covers, as YYYY-MM, such as 2026-09. The deadline and amount are for this period alone.
deadline
string · date
requiredThe date the filing is due, as YYYY-MM-DD, such as 2026-09-01, set by the jurisdiction pack's calendar rules and never by anything you enter. File after it and penalty_formula says what that costs.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
penalty_formula
string
optionalPublished from the pack as a formula rather than a computed figure, because the amount depends on when you actually file.
lead_time_days
integer
optionalHow far ahead the due soon alert fires.
pack_version
string
optionalThe version of the jurisdiction pack this entry came from, such as 2026.08.1. Keep it with the entry, so you can show which rules set the deadline and the penalty formula.
has_more
boolean
requiredtrue when there are more records after this page. Pass the last record's id as starting_after to get the next page.
Other responses
Errors it can return
# query parameters: limit (optional), due_before (optional), authority_id (optional)
curl -X GET "https://sandbox.droomwork.io/v1/remittance/calendar_entries?limit=25&due_before=2026-09-30&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
// query parameters: limit (optional), due_before (optional), authority_id (optional)
const result = await api.remittanceCalendarEntriesList({ limit: 25, dueBefore: '2026-09-30', authorityId: 'remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });// query parameters: limit (optional), due_before (optional), authority_id (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/remittance/calendar_entries?limit=25&due_before=2026-09-30&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
# query parameters: limit (optional), due_before (optional), authority_id (optional)
result = api.remittance_calendar_entries_list(limit=25, due_before='2026-09-30', authority_id='remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')import os
import requests
# query parameters: limit (optional), due_before (optional), authority_id (optional)
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/calendar_entries?limit=25&due_before=2026-09-30&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
# query parameters: limit (optional), due_before (optional), authority_id (optional)
$result = $api->remittanceCalendarEntriesList(limit: 25, due_before: '2026-09-30', authority_id: 'remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');<?php
// query parameters: limit (optional), due_before (optional), authority_id (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/calendar_entries?limit=25&due_before=2026-09-30&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
// query parameters: limit (optional), due_before (optional), authority_id (optional)
var result = api.remittanceCalendarEntriesList(25, "2026-09-30", "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");// query parameters: limit (optional), due_before (optional), authority_id (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/calendar_entries?limit=25&due_before=2026-09-30&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
// query parameters: limit (optional), due_before (optional), authority_id (optional)
var result = api.RemittanceCalendarEntriesList(limit: 25, dueBefore: "2026-09-30", authorityId: "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");// query parameters: limit (optional), due_before (optional), authority_id (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/calendar_entries?limit=25&due_before=2026-09-30&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
// query parameters: limit (optional), due_before (optional), authority_id (optional)
result, _, err := client.REMITAPI.RemittanceCalendarEntriesList(ctx).Limit(25).DueBefore("2026-09-30").AuthorityId("remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()// query parameters: limit (optional), due_before (optional), authority_id (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/calendar_entries?limit=25&due_before=2026-09-30&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"object": "list",
"data": [
{
"id": "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "calendar_entry",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"period": "2026-09",
"deadline": "2026-09-01",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"authority_name": "Sandbox State Internal Revenue Service",
"penalty_formula": "10 percent of the unpaid amount plus interest at the CBN rate per annum",
"lead_time_days": 1,
"pack_version": "2026.08.1"
}
],
"has_more": true
}
/v1/remittance/calendar_entries/{calendar_entry_id}#Check one filing deadline on its own
remittance.calendar_entries.retrieve
A calendar entry is one filing deadline: one authority, one month, the date it is due, and what is owed by then. So one identifier you stored puts that deadline back on a screen, without reading the whole calendar to find it again.
Send the entry's id in the path as calendar_entry_id. You get the whole entry back, with amount in whole minor units with its currency and penalty_formula as the terms that apply if you file after the deadline.
An id nothing holds answers not_found. Other entries are listed at GET /v1/remittance/calendar_entries.
Path parameters
calendar_entry_id
string
requiredThe deadline's identifier, from the id of an entry listed at GET /v1/remittance/calendar_entries. It starts with remit_authority_rail_obligation_.
Returns
The deadline itself, with the lead time that says how early to warn whoever must file.
id
string
requiredThe deadline's identifier, as listed at GET /v1/remittance/calendar_entries, starting remit_authority_rail_obligation_. It never changes; pass it as calendar_entry_id at GET /v1/remittance/calendar_entries/{calendar_entry_id}.
object
always "calendar_entry"
requiredAlways calendar_entry. Tells you which kind of record you are looking at, so one handler can read any response.
authority_id
string
requiredThe authority this deadline is for: its id from GET /v1/remittance/authorities, starting remit_authority_rail_obligation_. GET /v1/remittance/authorities/{authority_id} gives its name, tier and capabilities; filter the calendar by it.
authority_name
string
optionalThe authority's name as you'd write it, such as Rivers State Internal Revenue Service. For display; authority_id is what you filter and match on.
period
string
requiredThe month the filing covers, as YYYY-MM, such as 2026-09. The deadline and amount are for this period alone.
deadline
string · date
requiredThe date the filing is due, as YYYY-MM-DD, such as 2026-09-01, set by the jurisdiction pack's calendar rules and never by anything you enter. File after it and penalty_formula says what that costs.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
penalty_formula
string
optionalPublished from the pack as a formula rather than a computed figure, because the amount depends on when you actually file.
lead_time_days
integer
optionalHow far ahead the due soon alert fires.
pack_version
string
optionalThe version of the jurisdiction pack this entry came from, such as 2026.08.1. Keep it with the entry, so you can show which rules set the deadline and the penalty formula.
Other responses
Errors it can return
curl -X GET "https://sandbox.droomwork.io/v1/remittance/calendar_entries/%7Bcalendar_entry_id%7D" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceCalendarEntriesRetrieve({ calendarEntryId: '{calendar_entry_id}' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/calendar_entries/%7Bcalendar_entry_id%7D', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_calendar_entries_retrieve(calendar_entry_id='{calendar_entry_id}')import os
import requests
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/calendar_entries/%7Bcalendar_entry_id%7D',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceCalendarEntriesRetrieve(calendar_entry_id: '{calendar_entry_id}');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/calendar_entries/%7Bcalendar_entry_id%7D');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceCalendarEntriesRetrieve("{calendar_entry_id}");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/calendar_entries/%7Bcalendar_entry_id%7D"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceCalendarEntriesRetrieve(calendarEntryId: "{calendar_entry_id}");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/calendar_entries/%7Bcalendar_entry_id%7D");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceCalendarEntriesRetrieve(ctx, "{calendar_entry_id}").Execute()req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/calendar_entries/%7Bcalendar_entry_id%7D", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "calendar_entry",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"period": "2026-09",
"deadline": "2026-09-01",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"authority_name": "Sandbox State Internal Revenue Service",
"penalty_formula": "10 percent of the unpaid amount plus interest at the CBN rate per annum",
"lead_time_days": 1,
"pack_version": "2026.08.1"
}
/v1/remittance/authorities#Find the authority you file with
remittance.authorities.list
An authority is a body you owe money to: a tax office, a pension body, or one of the statutory levies. This is the register of them, so your product can offer a list to pick from instead of a free text box.
You send nothing. Each authority comes back with its name, its kind, a tier, and a capabilities object answering separately for paying it, filing a return, uploading a schedule and retrieving a receipt.
Read capabilities before you build against an authority: the four answers are independent, so one may take a filing and not a payment.
Keep an authority's id and pass it as authority_id to read one on its own at GET /v1/remittance/authorities/{authority_id}.
Query parameters
limit
integer
optionalHow many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.
kind
string
optionalReturn only authorities of this kind: state_irs or federal_irs for tax, pension_commission or pension_administrator for pensions, nhf, nsitf, itf or nhia for the levies. Leave it out to get every kind.
state_irsfederal_irspension_commissionpension_administratornhfnsitfitfnhiatier
string
optionalReturn only authorities your filing reaches this way: direct_api, portal_automation or assisted_manual. Leave it out to get every tier; read a tier for timing, never as something to code against.
direct_apiportal_automationassisted_manualReturns
A page of authorities.
object
always "list"
requiredAlways list. Tells you which kind of record you are looking at, so one handler can read any response.
data
array of Authority
requiredThe records on this page, in the order the list promises. Empty when nothing matched.
9 fields of Authority
id
string
requiredThe authority's identifier, as listed at GET /v1/remittance/authorities, starting remit_authority_rail_obligation_. It never changes; pass it as authority_id to retrieve the authority, or to filter obligations and deadlines by it.
object
always "authority"
requiredAlways authority. Tells you which kind of record you are looking at, so one handler can read any response.
kind
string
requiredstate_irsfederal_irspension_commissionpension_administratornhfnsitfitfnhiatier
string
requiredHow the filing reaches the authority. Readable so you know what to expect on timing. Never something to code against, since all three present the same contract.
direct_apiportal_automationassisted_manualname
string
requiredThe authority's name as you'd write it, such as Rivers State Internal Revenue Service. It's what appears as authority_name on obligations, legs and deadlines.
jurisdiction
string
optionalWhich jurisdiction the authority collects for, such as the state whose PAYE a State IRS receives. Use it to tell the 37 tax jurisdictions apart.
capabilities
object
requiredWhat this authority supports. Absent a capability, the endpoint refuses rather than pretends.
4 fields
file_return
boolean
optionaltrue when you can file an employer return with this authority through Droomwork. When it's false, a return for this authority is refused rather than pretended.
pay
boolean
optionaltrue when you can pay this authority through a remittance leg. When it's false, a leg for this authority is refused rather than pretended.
receipt_retrieval
boolean
optionaltrue when we can retrieve the receipt for a filing from this authority and vault it as your proof. When it's false, none is retrieved for you: record the one the authority issued at POST /v1/remittance/receipts.
schedule_upload
boolean
optionaltrue when the per-employee schedule behind a filing can be uploaded to this authority. When it's false, a schedule upload for it is refused rather than pretended.
credentials_held
boolean
optionalWhether you have supplied credentials for this authority.
expected_completion
string
optionalTypical time to a vaulted receipt at this tier.
has_more
boolean
requiredtrue when there are more records after this page. Pass the last record's id as starting_after to get the next page.
Other responses
Errors it can return
# query parameters: limit (optional), kind (optional), tier (optional)
curl -X GET "https://sandbox.droomwork.io/v1/remittance/authorities?limit=25&kind=state_irs&tier=direct_api" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
// query parameters: limit (optional), kind (optional), tier (optional)
const result = await api.remittanceAuthoritiesList({ limit: 25, kind: 'state_irs', tier: 'direct_api' });// query parameters: limit (optional), kind (optional), tier (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/remittance/authorities?limit=25&kind=state_irs&tier=direct_api', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
# query parameters: limit (optional), kind (optional), tier (optional)
result = api.remittance_authorities_list(limit=25, kind='state_irs', tier='direct_api')import os
import requests
# query parameters: limit (optional), kind (optional), tier (optional)
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/authorities?limit=25&kind=state_irs&tier=direct_api',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
# query parameters: limit (optional), kind (optional), tier (optional)
$result = $api->remittanceAuthoritiesList(limit: 25, kind: 'state_irs', tier: 'direct_api');<?php
// query parameters: limit (optional), kind (optional), tier (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/authorities?limit=25&kind=state_irs&tier=direct_api');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
import com.droomwork.sdk.model.*;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
// query parameters: limit (optional), kind (optional), tier (optional)
var result = api.remittanceAuthoritiesList(25, RemitAuthorityKind.fromValue("state_irs"), RemitAuthorityTier.fromValue("direct_api"));// query parameters: limit (optional), kind (optional), tier (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/authorities?limit=25&kind=state_irs&tier=direct_api"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
// query parameters: limit (optional), kind (optional), tier (optional)
var result = api.RemittanceAuthoritiesList(limit: 25, kind: RemitAuthorityKind.StateIrs, tier: RemitAuthorityTier.DirectApi);// query parameters: limit (optional), kind (optional), tier (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/authorities?limit=25&kind=state_irs&tier=direct_api");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
// query parameters: limit (optional), kind (optional), tier (optional)
result, _, err := client.REMITAPI.RemittanceAuthoritiesList(ctx).Limit(25).Kind(droomwork.RemitAuthorityKind("state_irs")).Tier(droomwork.RemitAuthorityTier("direct_api")).Execute()// query parameters: limit (optional), kind (optional), tier (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/authorities?limit=25&kind=state_irs&tier=direct_api", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"object": "list",
"data": [
{
"id": "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "authority",
"kind": "state_irs",
"tier": "direct_api",
"name": "Rivers State Internal Revenue Service",
"capabilities": {
"file_return": true,
"pay": true,
"receipt_retrieval": true,
"schedule_upload": true
},
"jurisdiction": "Sandbox State Internal Revenue Service",
"credentials_held": true,
"expected_completion": "under 5 minutes"
}
],
"has_more": true
}
/v1/remittance/authorities/{authority_id}#Check what one authority supports
remittance.authorities.retrieve
An authority is a body you owe money to, and this reads one of them back on its own: who it is, how a filing reaches it, and what it accepts. So a page in your product can offer what may be done with that authority, and leave out the rest.
Send the authority's id in the path as authority_id. You get the authority back: its name, its kind, its tier, and the capabilities it answers for.
expected_completion is free text and typical of the tier, not a promise about one filing: show it, and do not parse it.
An id nothing holds answers not_found. Other authorities are listed at GET /v1/remittance/authorities.
Path parameters
authority_id
string
requiredThe authority's identifier: the id of an authority listed at GET /v1/remittance/authorities, or the authority_id on an obligation, leg, receipt or calendar entry. It starts with remit_authority_rail_obligation_.
Returns
One authority in full, with the typical time to a receipt there, to set a caller's expectations.
id
string
requiredThe authority's identifier, as listed at GET /v1/remittance/authorities, starting remit_authority_rail_obligation_. It never changes; pass it as authority_id to retrieve the authority, or to filter obligations and deadlines by it.
object
always "authority"
requiredAlways authority. Tells you which kind of record you are looking at, so one handler can read any response.
kind
string
requiredstate_irsfederal_irspension_commissionpension_administratornhfnsitfitfnhiatier
string
requiredHow the filing reaches the authority. Readable so you know what to expect on timing. Never something to code against, since all three present the same contract.
direct_apiportal_automationassisted_manualname
string
requiredThe authority's name as you'd write it, such as Rivers State Internal Revenue Service. It's what appears as authority_name on obligations, legs and deadlines.
jurisdiction
string
optionalWhich jurisdiction the authority collects for, such as the state whose PAYE a State IRS receives. Use it to tell the 37 tax jurisdictions apart.
capabilities
object
requiredWhat this authority supports. Absent a capability, the endpoint refuses rather than pretends.
4 fields
file_return
boolean
optionaltrue when you can file an employer return with this authority through Droomwork. When it's false, a return for this authority is refused rather than pretended.
pay
boolean
optionaltrue when you can pay this authority through a remittance leg. When it's false, a leg for this authority is refused rather than pretended.
receipt_retrieval
boolean
optionaltrue when we can retrieve the receipt for a filing from this authority and vault it as your proof. When it's false, none is retrieved for you: record the one the authority issued at POST /v1/remittance/receipts.
schedule_upload
boolean
optionaltrue when the per-employee schedule behind a filing can be uploaded to this authority. When it's false, a schedule upload for it is refused rather than pretended.
credentials_held
boolean
optionalWhether you have supplied credentials for this authority.
expected_completion
string
optionalTypical time to a vaulted receipt at this tier.
Other responses
Errors it can return
curl -X GET "https://sandbox.droomwork.io/v1/remittance/authorities/%7Bauthority_id%7D" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceAuthoritiesRetrieve({ authorityId: '{authority_id}' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/authorities/%7Bauthority_id%7D', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_authorities_retrieve(authority_id='{authority_id}')import os
import requests
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/authorities/%7Bauthority_id%7D',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceAuthoritiesRetrieve(authority_id: '{authority_id}');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/authorities/%7Bauthority_id%7D');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceAuthoritiesRetrieve("{authority_id}");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/authorities/%7Bauthority_id%7D"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceAuthoritiesRetrieve(authorityId: "{authority_id}");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/authorities/%7Bauthority_id%7D");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceAuthoritiesRetrieve(ctx, "{authority_id}").Execute()req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/authorities/%7Bauthority_id%7D", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "authority",
"kind": "state_irs",
"tier": "direct_api",
"name": "Rivers State Internal Revenue Service",
"capabilities": {
"file_return": true,
"pay": true,
"receipt_retrieval": true,
"schedule_upload": true
},
"jurisdiction": "Sandbox State Internal Revenue Service",
"credentials_held": true,
"expected_completion": "under 5 minutes"
}
/v1/remittance/remittances#Find a remittance you opened earlier
remittance.remittances.list
This hands you the remittances your organisation has created, each one a month's payment to the authorities. A record comes back whole, figures and legs together, so a filing screen in your product needs no second call for each row, and an id you did not keep is found again here.
You send nothing. Each record carries the state that remittance has reached, its total in whole minor units with its currency, the instruction set it was built from, and each leg with its own state and amount.
Carry a record's id as remittance_id to read the same remittance at GET /v1/remittance/remittances/{remittance_id}, or its legs on their own at GET /v1/remittance/remittances/{remittance_id}/legs.
Query parameters
limit
integer
optionalHow many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.
starting_after
string
optionalThe id of the last record on the previous page of this same list. Leave it out to get the first page; when a page comes back with has_more true, send its last record's id here to get the page after it.
status
string
optionalReturn only remittances in one state: draft (created, not yet approved), approved, executing (legs running), completed, partially_completed (some legs failed) or failed. Leave it out to get every state.
draftapprovedexecutingcompletedpartially_completedfailedReturns
A page of remittances, each carrying the month it pays where there is one.
object
always "list"
requiredAlways list. Tells you which kind of record you are looking at, so one handler can read any response.
data
array of Remittance
requiredThe records on this page, in the order the list promises. Empty when nothing matched.
11 fields of Remittance
id
string
requiredThe remittance's identifier, first returned by POST /v1/remittance/remittances; it starts with remit_authority_rail_remittance_ and never changes. Pass it as remittance_id wherever a call names this remittance.
object
always "remittance"
requiredAlways remittance. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
status
string
requireddraftapprovedexecutingcompletedpartially_completedfailedinstruction_set_id
string
requiredThe id of the accepted instruction set whose figures the legs pay, from POST /v1/remittance/instruction_sets, starting with remit_authority_rail_instruction_. Retrieve it at GET /v1/remittance/instruction_sets/{instruction_set_id}.
period
string
optionalThe month the remittance pays for, as YYYY-MM, such as 2026-09. It's the period of the instruction set it was created from.
total
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
legs
array of Leg
requiredOne leg per authority the remittance pays, each with its own state, amount and receipt. A leg runs on its own, so one authority being down never holds the others; read each to see what settled where.
11 fields of Leg
id
string
requiredThe leg's identifier, first returned in legs on the remittance from POST /v1/remittance/remittances; it never changes. Pass it as leg_id, with the remittance's id as remittance_id, to retrieve or retry the leg.
object
always "remittance_leg"
requiredAlways remittance_leg. Tells you which kind of record you are looking at, so one handler can read any response.
remittance_id
string
optionalThe id of the remittance this leg belongs to, from POST /v1/remittance/remittances; it starts with remit_authority_rail_remittance_. Every call that names the leg names it too, at /v1/remittance/remittances/{remittance_id}/legs/{leg_id}.
authority_id
string
requiredThe id of the authority this leg pays, as listed at GET /v1/remittance/authorities; it starts with remit_authority_rail_obligation_. Look it up at GET /v1/remittance/authorities/{authority_id} for its name, tier and capabilities.
authority_name
string
optionalThe authority's name as you'd write it, such as Rivers State Internal Revenue Service. For display; authority_id is what you match on.
tier
string
optionalHow the filing reaches the authority. Readable so you know what to expect on timing. Never something to code against, since all three present the same contract.
direct_apiportal_automationassisted_manualstatus
string
requiredA leg reaches completed only once its receipt is vaulted. quarantined means a receipt arrived but disagreed with the leg.
pendingexecutingawaiting_receiptcompletedquarantinedfailedamount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
receipt_id
string · nullable
optionalThe id of the receipt that is this leg's proof of payment, once vaulted; it starts with remit_authority_rail_receipt_ and you retrieve it at GET /v1/remittance/receipts/{receipt_id}. null until a receipt is vaulted.
attempts
integer · minimum 0
optionalHow many times filing this leg with its authority has been tried, retries included. 0 before the first try; read it with last_fault before you retry.
last_fault
string · nullable
optionalWhy the latest attempt failed, in words for a person to read, such as The register did not answer within the timeout. null when there is no fault to report; read it before you retry.
approved_by
string · nullable
optionalWho approved the remittance: the actor that called approve. null while it is still draft, and execution is refused until a person is named here.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
has_more
boolean
requiredtrue when there are more records after this page. Pass the last record's id as starting_after to get the next page.
Other responses
Errors it can return
# query parameters: limit (optional), starting_after (optional), status (optional)
curl -X GET "https://sandbox.droomwork.io/v1/remittance/remittances?limit=25&status=draft" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
// query parameters: limit (optional), starting_after (optional), status (optional)
const result = await api.remittanceRemittancesList({ limit: 25, status: 'draft' });// query parameters: limit (optional), starting_after (optional), status (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/remittance/remittances?limit=25&status=draft', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
# query parameters: limit (optional), starting_after (optional), status (optional)
result = api.remittance_remittances_list(limit=25, status='draft')import os
import requests
# query parameters: limit (optional), starting_after (optional), status (optional)
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/remittances?limit=25&status=draft',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
# query parameters: limit (optional), starting_after (optional), status (optional)
$result = $api->remittanceRemittancesList(limit: 25, status: 'draft');<?php
// query parameters: limit (optional), starting_after (optional), status (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/remittances?limit=25&status=draft');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
import com.droomwork.sdk.model.*;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
// query parameters: limit (optional), starting_after (optional), status (optional)
var result = api.remittanceRemittancesList(25, null, RemitRemittanceStatus.fromValue("draft"));// query parameters: limit (optional), starting_after (optional), status (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/remittances?limit=25&status=draft"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
// query parameters: limit (optional), starting_after (optional), status (optional)
var result = api.RemittanceRemittancesList(limit: 25, status: RemitRemittanceStatus.Draft);// query parameters: limit (optional), starting_after (optional), status (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/remittances?limit=25&status=draft");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
// query parameters: limit (optional), starting_after (optional), status (optional)
result, _, err := client.REMITAPI.RemittanceRemittancesList(ctx).Limit(25).Status(droomwork.RemitRemittanceStatus("draft")).Execute()// query parameters: limit (optional), starting_after (optional), status (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/remittances?limit=25&status=draft", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"object": "list",
"data": [
{
"id": "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance",
"livemode": false,
"mocked": true,
"status": "draft",
"instruction_set_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"legs": [
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance_leg",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"status": "pending",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"remittance_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_name": "Sandbox State Internal Revenue Service",
"tier": "direct_api",
"receipt_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"attempts": 0,
"last_fault": "The register did not answer within the timeout."
}
],
"total": {
"amount": 57900000,
"currency": "NGN"
},
"period": "2026-09",
"approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"created_at": "2026-09-01T09:00:00Z"
}
],
"has_more": true
}
/v1/remittance/remittances#Open a remittance from an accepted instruction set
remittance.remittances.create
This turns figures you have accepted into the payment of them. Everything that follows hangs off the identifier it hands back, the approval, the execution and each leg's own retry, so your system keeps one string and reads each authority's state off it from then on.
Send the instruction set's id. You get the remittance back in draft, with an id starting remit_authority_rail_remittance_ to keep and its total in whole minor units with its currency across every leg.
The set has to be accepted first, at POST /v1/remittance/instruction_sets/{instruction_set_id}/accept.
One remittance pays one month, the month of the set it was created from. Another month means another accepted set.
Approve it next at POST /v1/remittance/remittances/{remittance_id}/approve, sending this id as remittance_id.
Headers
Idempotency-Key
string
requiredA key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.
Body
instruction_set_id
string
requiredThe id of the instruction set to remit, from POST /v1/remittance/instruction_sets; it starts with remit_authority_rail_instruction_ and must be accepted first. You get one leg per authority it names, or only those in authority_ids.
authority_ids
array of string
optionalDefaults to every authority named in the instruction set.
Returns
The remittance, with created_at where there is one, to date your own row by.
id
string
requiredThe remittance's identifier, first returned by POST /v1/remittance/remittances; it starts with remit_authority_rail_remittance_ and never changes. Pass it as remittance_id wherever a call names this remittance.
object
always "remittance"
requiredAlways remittance. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
status
string
requireddraftapprovedexecutingcompletedpartially_completedfailedinstruction_set_id
string
requiredThe id of the accepted instruction set whose figures the legs pay, from POST /v1/remittance/instruction_sets, starting with remit_authority_rail_instruction_. Retrieve it at GET /v1/remittance/instruction_sets/{instruction_set_id}.
period
string
optionalThe month the remittance pays for, as YYYY-MM, such as 2026-09. It's the period of the instruction set it was created from.
total
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
legs
array of Leg
requiredOne leg per authority the remittance pays, each with its own state, amount and receipt. A leg runs on its own, so one authority being down never holds the others; read each to see what settled where.
11 fields of Leg
id
string
requiredThe leg's identifier, first returned in legs on the remittance from POST /v1/remittance/remittances; it never changes. Pass it as leg_id, with the remittance's id as remittance_id, to retrieve or retry the leg.
object
always "remittance_leg"
requiredAlways remittance_leg. Tells you which kind of record you are looking at, so one handler can read any response.
remittance_id
string
optionalThe id of the remittance this leg belongs to, from POST /v1/remittance/remittances; it starts with remit_authority_rail_remittance_. Every call that names the leg names it too, at /v1/remittance/remittances/{remittance_id}/legs/{leg_id}.
authority_id
string
requiredThe id of the authority this leg pays, as listed at GET /v1/remittance/authorities; it starts with remit_authority_rail_obligation_. Look it up at GET /v1/remittance/authorities/{authority_id} for its name, tier and capabilities.
authority_name
string
optionalThe authority's name as you'd write it, such as Rivers State Internal Revenue Service. For display; authority_id is what you match on.
tier
string
optionalHow the filing reaches the authority. Readable so you know what to expect on timing. Never something to code against, since all three present the same contract.
direct_apiportal_automationassisted_manualstatus
string
requiredA leg reaches completed only once its receipt is vaulted. quarantined means a receipt arrived but disagreed with the leg.
pendingexecutingawaiting_receiptcompletedquarantinedfailedamount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
receipt_id
string · nullable
optionalThe id of the receipt that is this leg's proof of payment, once vaulted; it starts with remit_authority_rail_receipt_ and you retrieve it at GET /v1/remittance/receipts/{receipt_id}. null until a receipt is vaulted.
attempts
integer · minimum 0
optionalHow many times filing this leg with its authority has been tried, retries included. 0 before the first try; read it with last_fault before you retry.
last_fault
string · nullable
optionalWhy the latest attempt failed, in words for a person to read, such as The register did not answer within the timeout. null when there is no fault to report; read it before you retry.
approved_by
string · nullable
optionalWho approved the remittance: the actor that called approve. null while it is still draft, and execution is refused until a person is named here.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
Other responses
Errors it can return
curl -X POST "https://sandbox.droomwork.io/v1/remittance/remittances" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"instruction_set_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","authority_ids":["sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"]}'import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceRemittancesCreate({
idempotencyKey: crypto.randomUUID(),
remitRemittanceCreateRequest: {"instructionSetId":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","authorityIds":["sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"]},
});const response = await fetch('https://sandbox.droomwork.io/v1/remittance/remittances', {
method: 'POST',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
"instruction_set_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_ids": [
"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
]
}),
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_remittances_create(body={"instruction_set_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "authority_ids": ["sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"]})import os
import uuid
import requests
response = requests.request(
'POST',
'https://sandbox.droomwork.io/v1/remittance/remittances',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
'Idempotency-Key': str(uuid.uuid4()),
},
json={"instruction_set_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "authority_ids": ["sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"]},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceRemittancesCreate($idempotencyKey, json_decode('{"instruction_set_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","authority_ids":["sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"]}', true));<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/remittances');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
'Content-Type: application/json',
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
],
CURLOPT_POSTFIELDS => '{"instruction_set_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","authority_ids":["sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"]}',
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceRemittancesCreate(idempotencyKey, body);var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/remittances"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.header("Content-Type", "application/json")
.header("Idempotency-Key", UUID.randomUUID().toString())
.method("POST", HttpRequest.BodyPublishers.ofString("""
{
"instruction_set_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_ids": [
"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
]
}
"""))
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceRemittancesCreate(idempotencyKey, body);using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/remittance/remittances");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent("""
{
"instruction_set_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_ids": [
"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
]
}
""", Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceRemittancesCreate(ctx).IdempotencyKey(key).RemitRemittanceCreateRequest(body).Execute()body := strings.NewReader(`{
"instruction_set_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_ids": [
"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
]
}`)
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/remittance/remittances", body)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance",
"livemode": false,
"mocked": true,
"status": "draft",
"instruction_set_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"legs": [
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance_leg",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"status": "pending",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"remittance_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_name": "Sandbox State Internal Revenue Service",
"tier": "direct_api",
"receipt_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"attempts": 0,
"last_fault": "The register did not answer within the timeout."
}
],
"total": {
"amount": 57900000,
"currency": "NGN"
},
"period": "2026-09",
"approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"created_at": "2026-09-01T09:00:00Z"
}
/v1/remittance/remittances/{remittance_id}#Read one remittance and every leg it holds
remittance.remittances.retrieve
A remittance is one month's payment of what an accepted instruction set says you owe, split into a leg for each authority it pays. This reads one back whole, its total and every leg's amount in the same answer, so a screen in your product can show a month's filing from a single call.
Send the remittance's id in the path. You get the record as it stands: status for where the remittance has got to, and on each leg its own status, the authority it pays and what it pays them.
While it is still draft, approve it at POST /v1/remittance/remittances/{remittance_id}/approve. Read the legs on their own at GET /v1/remittance/remittances/{remittance_id}/legs.
Path parameters
remittance_id
string
requiredThe remittance's identifier: the id of a remittance you created at POST /v1/remittance/remittances or listed at GET /v1/remittance/remittances. It starts with remit_authority_rail_remittance_.
Returns
One remittance, naming the receipt behind each leg that has one, so the proof can be fetched next.
id
string
requiredThe remittance's identifier, first returned by POST /v1/remittance/remittances; it starts with remit_authority_rail_remittance_ and never changes. Pass it as remittance_id wherever a call names this remittance.
object
always "remittance"
requiredAlways remittance. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
status
string
requireddraftapprovedexecutingcompletedpartially_completedfailedinstruction_set_id
string
requiredThe id of the accepted instruction set whose figures the legs pay, from POST /v1/remittance/instruction_sets, starting with remit_authority_rail_instruction_. Retrieve it at GET /v1/remittance/instruction_sets/{instruction_set_id}.
period
string
optionalThe month the remittance pays for, as YYYY-MM, such as 2026-09. It's the period of the instruction set it was created from.
total
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
legs
array of Leg
requiredOne leg per authority the remittance pays, each with its own state, amount and receipt. A leg runs on its own, so one authority being down never holds the others; read each to see what settled where.
11 fields of Leg
id
string
requiredThe leg's identifier, first returned in legs on the remittance from POST /v1/remittance/remittances; it never changes. Pass it as leg_id, with the remittance's id as remittance_id, to retrieve or retry the leg.
object
always "remittance_leg"
requiredAlways remittance_leg. Tells you which kind of record you are looking at, so one handler can read any response.
remittance_id
string
optionalThe id of the remittance this leg belongs to, from POST /v1/remittance/remittances; it starts with remit_authority_rail_remittance_. Every call that names the leg names it too, at /v1/remittance/remittances/{remittance_id}/legs/{leg_id}.
authority_id
string
requiredThe id of the authority this leg pays, as listed at GET /v1/remittance/authorities; it starts with remit_authority_rail_obligation_. Look it up at GET /v1/remittance/authorities/{authority_id} for its name, tier and capabilities.
authority_name
string
optionalThe authority's name as you'd write it, such as Rivers State Internal Revenue Service. For display; authority_id is what you match on.
tier
string
optionalHow the filing reaches the authority. Readable so you know what to expect on timing. Never something to code against, since all three present the same contract.
direct_apiportal_automationassisted_manualstatus
string
requiredA leg reaches completed only once its receipt is vaulted. quarantined means a receipt arrived but disagreed with the leg.
pendingexecutingawaiting_receiptcompletedquarantinedfailedamount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
receipt_id
string · nullable
optionalThe id of the receipt that is this leg's proof of payment, once vaulted; it starts with remit_authority_rail_receipt_ and you retrieve it at GET /v1/remittance/receipts/{receipt_id}. null until a receipt is vaulted.
attempts
integer · minimum 0
optionalHow many times filing this leg with its authority has been tried, retries included. 0 before the first try; read it with last_fault before you retry.
last_fault
string · nullable
optionalWhy the latest attempt failed, in words for a person to read, such as The register did not answer within the timeout. null when there is no fault to report; read it before you retry.
approved_by
string · nullable
optionalWho approved the remittance: the actor that called approve. null while it is still draft, and execution is refused until a person is named here.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
Other responses
Errors it can return
curl -X GET "https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceRemittancesRetrieve({ remittanceId: 'remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_remittances_retrieve(remittance_id='remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')import os
import requests
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceRemittancesRetrieve(remittance_id: 'remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceRemittancesRetrieve("remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceRemittancesRetrieve(remittanceId: "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceRemittancesRetrieve(ctx, "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance",
"livemode": false,
"mocked": true,
"status": "draft",
"instruction_set_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"legs": [
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance_leg",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"status": "pending",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"remittance_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_name": "Sandbox State Internal Revenue Service",
"tier": "direct_api",
"receipt_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"attempts": 0,
"last_fault": "The register did not answer within the timeout."
}
],
"total": {
"amount": 57900000,
"currency": "NGN"
},
"period": "2026-09",
"approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"created_at": "2026-09-01T09:00:00Z"
}
/v1/remittance/remittances/{remittance_id}/approve#Approve a remittance for filing
remittance.remittances.approve
This is where a person agrees that a remittance should go to the authorities with the figures it holds. Approving is a call of its own, so your product can put a month's figures in front of whoever signs them off, and filing is refused until they have.
Send the remittance's id in the path and no request body. You get the whole remittance back, its total and its legs with it, and its status now approved.
The remittance has to be in draft, which is where POST /v1/remittance/remittances leaves it.
Execute it next at POST /v1/remittance/remittances/{remittance_id}/execute, which is the call that files with each authority. A remittance that has left draft is refused with conflict.
Path parameters
remittance_id
string
requiredThe remittance's identifier: the id of a remittance you created at POST /v1/remittance/remittances or listed at GET /v1/remittance/remittances. It starts with remit_authority_rail_remittance_.
Headers
Idempotency-Key
string
requiredA key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.
Returns
The remittance, now approved and not yet executed.
id
string
requiredThe remittance's identifier, first returned by POST /v1/remittance/remittances; it starts with remit_authority_rail_remittance_ and never changes. Pass it as remittance_id wherever a call names this remittance.
object
always "remittance"
requiredAlways remittance. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
status
string
requireddraftapprovedexecutingcompletedpartially_completedfailedinstruction_set_id
string
requiredThe id of the accepted instruction set whose figures the legs pay, from POST /v1/remittance/instruction_sets, starting with remit_authority_rail_instruction_. Retrieve it at GET /v1/remittance/instruction_sets/{instruction_set_id}.
period
string
optionalThe month the remittance pays for, as YYYY-MM, such as 2026-09. It's the period of the instruction set it was created from.
total
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
legs
array of Leg
requiredOne leg per authority the remittance pays, each with its own state, amount and receipt. A leg runs on its own, so one authority being down never holds the others; read each to see what settled where.
11 fields of Leg
id
string
requiredThe leg's identifier, first returned in legs on the remittance from POST /v1/remittance/remittances; it never changes. Pass it as leg_id, with the remittance's id as remittance_id, to retrieve or retry the leg.
object
always "remittance_leg"
requiredAlways remittance_leg. Tells you which kind of record you are looking at, so one handler can read any response.
remittance_id
string
optionalThe id of the remittance this leg belongs to, from POST /v1/remittance/remittances; it starts with remit_authority_rail_remittance_. Every call that names the leg names it too, at /v1/remittance/remittances/{remittance_id}/legs/{leg_id}.
authority_id
string
requiredThe id of the authority this leg pays, as listed at GET /v1/remittance/authorities; it starts with remit_authority_rail_obligation_. Look it up at GET /v1/remittance/authorities/{authority_id} for its name, tier and capabilities.
authority_name
string
optionalThe authority's name as you'd write it, such as Rivers State Internal Revenue Service. For display; authority_id is what you match on.
tier
string
optionalHow the filing reaches the authority. Readable so you know what to expect on timing. Never something to code against, since all three present the same contract.
direct_apiportal_automationassisted_manualstatus
string
requiredA leg reaches completed only once its receipt is vaulted. quarantined means a receipt arrived but disagreed with the leg.
pendingexecutingawaiting_receiptcompletedquarantinedfailedamount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
receipt_id
string · nullable
optionalThe id of the receipt that is this leg's proof of payment, once vaulted; it starts with remit_authority_rail_receipt_ and you retrieve it at GET /v1/remittance/receipts/{receipt_id}. null until a receipt is vaulted.
attempts
integer · minimum 0
optionalHow many times filing this leg with its authority has been tried, retries included. 0 before the first try; read it with last_fault before you retry.
last_fault
string · nullable
optionalWhy the latest attempt failed, in words for a person to read, such as The register did not answer within the timeout. null when there is no fault to report; read it before you retry.
approved_by
string · nullable
optionalWho approved the remittance: the actor that called approve. null while it is still draft, and execution is refused until a person is named here.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
Other responses
Errors it can return
curl -X POST "https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/approve" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceRemittancesApprove({ remittanceId: 'remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/approve', {
method: 'POST',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
'Idempotency-Key': crypto.randomUUID(),
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_remittances_approve(remittance_id='remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')import os
import uuid
import requests
response = requests.request(
'POST',
'https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/approve',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
'Idempotency-Key': str(uuid.uuid4()),
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceRemittancesApprove(remittance_id: 'remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/approve');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceRemittancesApprove("remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/approve"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.header("Idempotency-Key", UUID.randomUUID().toString())
.method("POST", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceRemittancesApprove(remittanceId: "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/approve");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceRemittancesApprove(ctx, "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/approve", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance",
"livemode": false,
"mocked": true,
"status": "approved",
"instruction_set_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"legs": [
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance_leg",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"status": "pending",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"remittance_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_name": "Sandbox State Internal Revenue Service",
"tier": "direct_api",
"receipt_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"attempts": 0,
"last_fault": "The register did not answer within the timeout."
}
],
"total": {
"amount": 57900000,
"currency": "NGN"
},
"period": "2026-09",
"approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"created_at": "2026-09-01T09:00:00Z"
}
/v1/remittance/remittances/{remittance_id}/legs#See each authority's part of a remittance
remittance.legs.list
This reads all of one remittance's legs in a single answer. Your product can then work a queue of only the legs that failed, without reading a whole remittance to find them.
Send the remittance's id in the path. Each leg you get back carries the authority_id it pays, a status, an amount in whole minor units with its currency, and last_fault when an attempt has left one.
Read one leg in full at GET /v1/remittance/remittances/{remittance_id}/legs/{leg_id}, and retry that leg at POST /v1/remittance/remittances/{remittance_id}/legs/{leg_id}/retry when its status is failed. An unknown remittance_id answers not_found.
Path parameters
remittance_id
string
requiredThe remittance's identifier: the id of a remittance you created at POST /v1/remittance/remittances or listed at GET /v1/remittance/remittances. It starts with remit_authority_rail_remittance_.
Query parameters
limit
integer
optionalHow many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.
status
string
optionalReturn only legs in one state: pending (not yet executed), executing, awaiting_receipt (filed), completed (receipt vaulted), quarantined (receipt disagreed with the leg) or failed (needs a retry). Leave it out to get every state.
pendingexecutingawaiting_receiptcompletedquarantinedfailedReturns
One row for each leg, with how each filing reaches its authority, so a slow one is no surprise.
object
always "list"
requiredAlways list. Tells you which kind of record you are looking at, so one handler can read any response.
data
array of Leg
requiredThe records on this page, in the order the list promises. Empty when nothing matched.
11 fields of Leg
id
string
requiredThe leg's identifier, first returned in legs on the remittance from POST /v1/remittance/remittances; it never changes. Pass it as leg_id, with the remittance's id as remittance_id, to retrieve or retry the leg.
object
always "remittance_leg"
requiredAlways remittance_leg. Tells you which kind of record you are looking at, so one handler can read any response.
remittance_id
string
optionalThe id of the remittance this leg belongs to, from POST /v1/remittance/remittances; it starts with remit_authority_rail_remittance_. Every call that names the leg names it too, at /v1/remittance/remittances/{remittance_id}/legs/{leg_id}.
authority_id
string
requiredThe id of the authority this leg pays, as listed at GET /v1/remittance/authorities; it starts with remit_authority_rail_obligation_. Look it up at GET /v1/remittance/authorities/{authority_id} for its name, tier and capabilities.
authority_name
string
optionalThe authority's name as you'd write it, such as Rivers State Internal Revenue Service. For display; authority_id is what you match on.
tier
string
optionalHow the filing reaches the authority. Readable so you know what to expect on timing. Never something to code against, since all three present the same contract.
direct_apiportal_automationassisted_manualstatus
string
requiredA leg reaches completed only once its receipt is vaulted. quarantined means a receipt arrived but disagreed with the leg.
pendingexecutingawaiting_receiptcompletedquarantinedfailedamount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
receipt_id
string · nullable
optionalThe id of the receipt that is this leg's proof of payment, once vaulted; it starts with remit_authority_rail_receipt_ and you retrieve it at GET /v1/remittance/receipts/{receipt_id}. null until a receipt is vaulted.
attempts
integer · minimum 0
optionalHow many times filing this leg with its authority has been tried, retries included. 0 before the first try; read it with last_fault before you retry.
last_fault
string · nullable
optionalWhy the latest attempt failed, in words for a person to read, such as The register did not answer within the timeout. null when there is no fault to report; read it before you retry.
has_more
boolean
requiredtrue when there are more records after this page. Pass the last record's id as starting_after to get the next page.
Other responses
Errors it can return
# query parameters: limit (optional), status (optional)
curl -X GET "https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs?limit=25&status=pending" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
// query parameters: limit (optional), status (optional)
const result = await api.remittanceLegsList({ remittanceId: 'remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', limit: 25, status: 'pending' });// query parameters: limit (optional), status (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs?limit=25&status=pending', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
# query parameters: limit (optional), status (optional)
result = api.remittance_legs_list(remittance_id='remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', limit=25, status='pending')import os
import requests
# query parameters: limit (optional), status (optional)
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs?limit=25&status=pending',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
# query parameters: limit (optional), status (optional)
$result = $api->remittanceLegsList(remittance_id: 'remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', limit: 25, status: 'pending');<?php
// query parameters: limit (optional), status (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs?limit=25&status=pending');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
import com.droomwork.sdk.model.*;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
// query parameters: limit (optional), status (optional)
var result = api.remittanceLegsList("remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", 25, RemitLegStatus.fromValue("pending"));// query parameters: limit (optional), status (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs?limit=25&status=pending"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
// query parameters: limit (optional), status (optional)
var result = api.RemittanceLegsList(remittanceId: "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", limit: 25, status: RemitLegStatus.Pending);// query parameters: limit (optional), status (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs?limit=25&status=pending");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
// query parameters: limit (optional), status (optional)
result, _, err := client.REMITAPI.RemittanceLegsList(ctx, "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Limit(25).Status(droomwork.RemitLegStatus("pending")).Execute()// query parameters: limit (optional), status (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs?limit=25&status=pending", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"object": "list",
"data": [
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance_leg",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"status": "pending",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"remittance_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_name": "Sandbox State Internal Revenue Service",
"tier": "direct_api",
"receipt_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"attempts": 0,
"last_fault": "The register did not answer within the timeout."
}
],
"has_more": true
}
/v1/remittance/remittances/{remittance_id}/legs/{leg_id}#Check where one leg has got to
remittance.legs.retrieve
A leg is one authority's part of a remittance, with its own state, amount and receipt. This reads one back on its own, so your product can follow a single authority's filing, and show the fault behind its last attempt, without reading the whole remittance again.
Send the remittance's id and the leg's id in the path. You get that leg: status for how far its filing has got, amount for what it pays, tier for how the filing reaches the authority, and last_fault for why the latest attempt failed.
Where the leg carries a receipt_id, read that receipt at GET /v1/remittance/receipts/{receipt_id}. See the remittance's legs together at GET /v1/remittance/remittances/{remittance_id}/legs. A leg_id from another remittance answers not_found.
Path parameters
remittance_id
string
requiredThe remittance's identifier: the id of a remittance you created at POST /v1/remittance/remittances or listed at GET /v1/remittance/remittances. It starts with remit_authority_rail_remittance_.
leg_id
string
requiredThe leg's identifier: the id of a leg in legs on the remittance from POST /v1/remittance/remittances, or listed at GET /v1/remittance/remittances/{remittance_id}/legs. It belongs to the remittance in the path.
Returns
One leg in full, with the count of tries behind it, enough to judge whether another is worth it.
id
string
requiredThe leg's identifier, first returned in legs on the remittance from POST /v1/remittance/remittances; it never changes. Pass it as leg_id, with the remittance's id as remittance_id, to retrieve or retry the leg.
object
always "remittance_leg"
requiredAlways remittance_leg. Tells you which kind of record you are looking at, so one handler can read any response.
remittance_id
string
optionalThe id of the remittance this leg belongs to, from POST /v1/remittance/remittances; it starts with remit_authority_rail_remittance_. Every call that names the leg names it too, at /v1/remittance/remittances/{remittance_id}/legs/{leg_id}.
authority_id
string
requiredThe id of the authority this leg pays, as listed at GET /v1/remittance/authorities; it starts with remit_authority_rail_obligation_. Look it up at GET /v1/remittance/authorities/{authority_id} for its name, tier and capabilities.
authority_name
string
optionalThe authority's name as you'd write it, such as Rivers State Internal Revenue Service. For display; authority_id is what you match on.
tier
string
optionalHow the filing reaches the authority. Readable so you know what to expect on timing. Never something to code against, since all three present the same contract.
direct_apiportal_automationassisted_manualstatus
string
requiredA leg reaches completed only once its receipt is vaulted. quarantined means a receipt arrived but disagreed with the leg.
pendingexecutingawaiting_receiptcompletedquarantinedfailedamount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
receipt_id
string · nullable
optionalThe id of the receipt that is this leg's proof of payment, once vaulted; it starts with remit_authority_rail_receipt_ and you retrieve it at GET /v1/remittance/receipts/{receipt_id}. null until a receipt is vaulted.
attempts
integer · minimum 0
optionalHow many times filing this leg with its authority has been tried, retries included. 0 before the first try; read it with last_fault before you retry.
last_fault
string · nullable
optionalWhy the latest attempt failed, in words for a person to read, such as The register did not answer within the timeout. null when there is no fault to report; read it before you retry.
Other responses
Errors it can return
curl -X GET "https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs/%7Bleg_id%7D" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceLegsRetrieve({ remittanceId: 'remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', legId: '{leg_id}' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs/%7Bleg_id%7D', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_legs_retrieve(remittance_id='remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', leg_id='{leg_id}')import os
import requests
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs/%7Bleg_id%7D',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceLegsRetrieve(remittance_id: 'remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', leg_id: '{leg_id}');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs/%7Bleg_id%7D');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceLegsRetrieve("remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "{leg_id}");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs/%7Bleg_id%7D"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceLegsRetrieve(remittanceId: "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", legId: "{leg_id}");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs/%7Bleg_id%7D");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceLegsRetrieve(ctx, "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "{leg_id}").Execute()req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs/%7Bleg_id%7D", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance_leg",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"status": "pending",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"remittance_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_name": "Sandbox State Internal Revenue Service",
"tier": "direct_api",
"receipt_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"attempts": 0,
"last_fault": "The register did not answer within the timeout."
}
/v1/remittance/remittances/{remittance_id}/legs/{leg_id}/retry#Retry a failed leg
remittance.legs.retry
A leg that came back failed is one authority's filing left undone. This retries that one leg, so a single authority's failure does not mean re-running a remittance you have already executed.
Send the remittance's id and the leg's id in the path. Send no request body. You get the leg back with its status set to pending, accepted for another attempt and not yet filed.
The remittance has to exist, from POST /v1/remittance/remittances, and the leg has to be one listed at GET /v1/remittance/remittances/{remittance_id}/legs.
Read the leg again at GET /v1/remittance/remittances/{remittance_id}/legs/{leg_id} for its state and its last_fault. An unknown remittance_id, or a leg_id from another remittance, answers not_found.
Path parameters
remittance_id
string
requiredThe remittance's identifier: the id of a remittance you created at POST /v1/remittance/remittances or listed at GET /v1/remittance/remittances. It starts with remit_authority_rail_remittance_.
leg_id
string
requiredThe leg's identifier: the id of a leg in legs on the remittance from POST /v1/remittance/remittances, or listed at GET /v1/remittance/remittances/{remittance_id}/legs. It belongs to the remittance in the path.
Headers
Idempotency-Key
string
requiredA key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.
Returns
The leg itself, still carrying the fault behind the previous attempt, so a repeat is recognisable.
id
string
requiredThe leg's identifier, first returned in legs on the remittance from POST /v1/remittance/remittances; it never changes. Pass it as leg_id, with the remittance's id as remittance_id, to retrieve or retry the leg.
object
always "remittance_leg"
requiredAlways remittance_leg. Tells you which kind of record you are looking at, so one handler can read any response.
remittance_id
string
optionalThe id of the remittance this leg belongs to, from POST /v1/remittance/remittances; it starts with remit_authority_rail_remittance_. Every call that names the leg names it too, at /v1/remittance/remittances/{remittance_id}/legs/{leg_id}.
authority_id
string
requiredThe id of the authority this leg pays, as listed at GET /v1/remittance/authorities; it starts with remit_authority_rail_obligation_. Look it up at GET /v1/remittance/authorities/{authority_id} for its name, tier and capabilities.
authority_name
string
optionalThe authority's name as you'd write it, such as Rivers State Internal Revenue Service. For display; authority_id is what you match on.
tier
string
optionalHow the filing reaches the authority. Readable so you know what to expect on timing. Never something to code against, since all three present the same contract.
direct_apiportal_automationassisted_manualstatus
string
requiredA leg reaches completed only once its receipt is vaulted. quarantined means a receipt arrived but disagreed with the leg.
pendingexecutingawaiting_receiptcompletedquarantinedfailedamount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
receipt_id
string · nullable
optionalThe id of the receipt that is this leg's proof of payment, once vaulted; it starts with remit_authority_rail_receipt_ and you retrieve it at GET /v1/remittance/receipts/{receipt_id}. null until a receipt is vaulted.
attempts
integer · minimum 0
optionalHow many times filing this leg with its authority has been tried, retries included. 0 before the first try; read it with last_fault before you retry.
last_fault
string · nullable
optionalWhy the latest attempt failed, in words for a person to read, such as The register did not answer within the timeout. null when there is no fault to report; read it before you retry.
Other responses
Errors it can return
curl -X POST "https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs/%7Bleg_id%7D/retry" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceLegsRetry({ remittanceId: 'remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', legId: '{leg_id}' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs/%7Bleg_id%7D/retry', {
method: 'POST',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
'Idempotency-Key': crypto.randomUUID(),
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_legs_retry(remittance_id='remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', leg_id='{leg_id}')import os
import uuid
import requests
response = requests.request(
'POST',
'https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs/%7Bleg_id%7D/retry',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
'Idempotency-Key': str(uuid.uuid4()),
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceLegsRetry(remittance_id: 'remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', leg_id: '{leg_id}');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs/%7Bleg_id%7D/retry');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceLegsRetry("remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "{leg_id}");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs/%7Bleg_id%7D/retry"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.header("Idempotency-Key", UUID.randomUUID().toString())
.method("POST", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceLegsRetry(remittanceId: "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", legId: "{leg_id}");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs/%7Bleg_id%7D/retry");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceLegsRetry(ctx, "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "{leg_id}").Execute()req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/legs/%7Bleg_id%7D/retry", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance_leg",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"status": "pending",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"remittance_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_name": "Sandbox State Internal Revenue Service",
"tier": "direct_api",
"receipt_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"attempts": 0,
"last_fault": "The register did not answer within the timeout."
}
/v1/remittance/receipts#What proof of payment you hold
remittance.receipts.list
A receipt is one authority's acknowledgement that money reached it, for one month, under the reference that authority itself issued. So your own system can show that an authority acknowledged a payment, which a filing reported as successful does not prove on its own.
You get one row per receipt, with its id, the authority and period it covers, the amount acknowledged, and what kind of proof it is. The document itself, where there is one, is a URL on the row.
Read one on its own at GET /v1/remittance/receipts/{receipt_id}, passing its id as receipt_id.
Query parameters
limit
integer
optionalHow many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.
starting_after
string
optionalThe id of the last record on the previous page of this same list. Leave it out to get the first page; when a page comes back with has_more true, send its last record's id here to get the page after it.
authority_id
string
optionalReturn only receipts issued by one authority: its id from GET /v1/remittance/authorities, or the authority_id on a leg or obligation, starting with remit_authority_rail_obligation_. Leave it out to get every authority.
period
string
optionalReturn only receipts whose payment covers one month, as YYYY-MM, such as 2026-09: the period each receipt carries. Leave it out to get every period.
Returns
A page of receipts, each carrying the hash that fixes its place in the chain.
object
always "list"
requiredAlways list. Tells you which kind of record you are looking at, so one handler can read any response.
data
array of Receipt
requiredThe records on this page, in the order the list promises. Empty when nothing matched.
17 fields of Receipt
id
string
requiredThe receipt's identifier, starting with remit_authority_rail_receipt_; it never changes. It is the receipt_id on the leg it proves and in receipt_ids on its obligation; pass it as receipt_id to GET /v1/remittance/receipts/{receipt_id}.
object
always "remittance_receipt"
requiredAlways remittance_receipt. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
leg_id
string · nullable
optionalThe id of the leg this receipt proves paid, from legs on a remittance or GET /v1/remittance/remittances/{remittance_id}/legs; vaulting the receipt takes that leg to completed. null when the receipt is not tied to a leg.
obligation_id
string · nullable
optionalThe id of the obligation this receipt settles against, from GET /v1/remittance/obligations, starting with remit_authority_rail_obligation_; the receipt also appears in its receipt_ids. null when not tied to an obligation.
authority_id
string
requiredThe id of the authority that issued this receipt, from GET /v1/remittance/authorities, starting with remit_authority_rail_obligation_; filter the list by it. It must agree with the leg's authority_id, or the receipt is quarantined.
period
string
requiredThe month the payment covers, as YYYY-MM, such as 2026-09; filter the list by it with the period query. It must agree with the leg's period, or the receipt is quarantined.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
authority_reference
string
optionalThe reference the authority itself issued.
evidence_class
string
requiredThe same classes apply whichever tier filed. An assisted manual filing carries a receipt reference, a document scan and an operator attestation under dual control, which is the same evidence class as an API filing.
authority_api_receiptportal_receiptassisted_manual_attesteddocument_url
string · uri · nullable
optionalWhere to fetch the receipt document the authority issued, as a URL. Present for an assisted manual filing, where you supplied the scan; null when there is no document.
hash
string
requiredThis receipt position in the append only chain.
previous_hash
string
requiredThe hash of the receipt vaulted just before this one. Each receipt carries the last one's hash, so you can walk the chain back and confirm nothing was changed or removed.
trace_references
array of string
optionalThe payroll trace references this receipt covers.
attested_by
array of string
optionalTwo actors for an assisted manual filing, under dual control.
vaulted_at
string · date-time
optionalWhen the receipt was hash chained into the vault, as an RFC 3339 timestamp in UTC. From this moment it never changes, and the leg it belongs to can reach completed.
has_more
boolean
requiredtrue when there are more records after this page. Pass the last record's id as starting_after to get the next page.
Other responses
Errors it can return
# query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional)
curl -X GET "https://sandbox.droomwork.io/v1/remittance/receipts?limit=25&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&period=2026-09" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
// query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional)
const result = await api.remittanceReceiptsList({ limit: 25, authorityId: 'remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', period: '2026-09' });// query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/remittance/receipts?limit=25&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&period=2026-09', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
# query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional)
result = api.remittance_receipts_list(limit=25, authority_id='remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', period='2026-09')import os
import requests
# query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional)
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/receipts?limit=25&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&period=2026-09',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
# query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional)
$result = $api->remittanceReceiptsList(limit: 25, authority_id: 'remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', period: '2026-09');<?php
// query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/receipts?limit=25&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&period=2026-09');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
// query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional)
var result = api.remittanceReceiptsList(25, null, "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "2026-09");// query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/receipts?limit=25&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&period=2026-09"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
// query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional)
var result = api.RemittanceReceiptsList(limit: 25, authorityId: "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", period: "2026-09");// query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/receipts?limit=25&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&period=2026-09");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
// query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional)
result, _, err := client.REMITAPI.RemittanceReceiptsList(ctx).Limit(25).AuthorityId("remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Period("2026-09").Execute()// query parameters: limit (optional), starting_after (optional), authority_id (optional), period (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/receipts?limit=25&authority_id=remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&period=2026-09", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"object": "list",
"data": [
{
"id": "remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance_receipt",
"livemode": false,
"mocked": true,
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"period": "2026-09",
"evidence_class": "authority_api_receipt",
"hash": "sha256:9f2c1e0043a1b8",
"previous_hash": "sha256:9f2c1e0043a1b8",
"leg_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"obligation_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_reference": "paye-2026-09-rivers",
"document_url": "https://files.sandbox.droomwork.com/example",
"trace_references": [
"paye-2026-09-rivers"
],
"attested_by": [
"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
],
"vaulted_at": "2026-09-01T09:00:00Z"
}
],
"has_more": true
}
/v1/remittance/receipts#Record a receipt from an assisted manual filing
remittance.receipts.create
Some authorities have no machine interface, so a person files with them and the authority hands back its own receipt. This is how that receipt becomes a record in the vault, the document kept beside the figures. So a hand filing stands as proof of payment in its own right, beside the receipts an authority's own system returned.
Send the leg_id you filed, the authority's reference, the amount it acknowledged, a link to your scan and two actors in attested_by. You get the vaulted receipt, its id starting remit_authority_rail_receipt_.
You need the leg you filed by hand, one of the legs on a remittance from POST /v1/remittance/remittances.
Line up two people before you call: attested_by needs two different actors, and one credential is not enough.
Keep the id; GET /v1/remittance/receipts/{receipt_id} reads it back.
Headers
Idempotency-Key
string
requiredA key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.
Body
leg_id
string
requiredThe id of the leg you filed by hand, from legs on the remittance or GET /v1/remittance/remittances/{remittance_id}/legs: one whose authority has no machine interface. The receipt is vaulted against it, which takes the leg to completed.
authority_reference
string
requiredThe reference the authority put on its receipt, exactly as issued, such as paye-2026-09-rivers. It comes back as authority_reference on the vaulted receipt.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
document_url
string · uri
requiredA scan of the receipt the authority issued.
attested_by
array of string
requiredTwo distinct actors. Dual control, so one credential is not enough.
Returns
The vaulted receipt, with the payroll traces it covers, so each figure reaches its proof.
id
string
requiredThe receipt's identifier, starting with remit_authority_rail_receipt_; it never changes. It is the receipt_id on the leg it proves and in receipt_ids on its obligation; pass it as receipt_id to GET /v1/remittance/receipts/{receipt_id}.
object
always "remittance_receipt"
requiredAlways remittance_receipt. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
leg_id
string · nullable
optionalThe id of the leg this receipt proves paid, from legs on a remittance or GET /v1/remittance/remittances/{remittance_id}/legs; vaulting the receipt takes that leg to completed. null when the receipt is not tied to a leg.
obligation_id
string · nullable
optionalThe id of the obligation this receipt settles against, from GET /v1/remittance/obligations, starting with remit_authority_rail_obligation_; the receipt also appears in its receipt_ids. null when not tied to an obligation.
authority_id
string
requiredThe id of the authority that issued this receipt, from GET /v1/remittance/authorities, starting with remit_authority_rail_obligation_; filter the list by it. It must agree with the leg's authority_id, or the receipt is quarantined.
period
string
requiredThe month the payment covers, as YYYY-MM, such as 2026-09; filter the list by it with the period query. It must agree with the leg's period, or the receipt is quarantined.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
authority_reference
string
optionalThe reference the authority itself issued.
evidence_class
string
requiredThe same classes apply whichever tier filed. An assisted manual filing carries a receipt reference, a document scan and an operator attestation under dual control, which is the same evidence class as an API filing.
authority_api_receiptportal_receiptassisted_manual_attesteddocument_url
string · uri · nullable
optionalWhere to fetch the receipt document the authority issued, as a URL. Present for an assisted manual filing, where you supplied the scan; null when there is no document.
hash
string
requiredThis receipt position in the append only chain.
previous_hash
string
requiredThe hash of the receipt vaulted just before this one. Each receipt carries the last one's hash, so you can walk the chain back and confirm nothing was changed or removed.
trace_references
array of string
optionalThe payroll trace references this receipt covers.
attested_by
array of string
optionalTwo actors for an assisted manual filing, under dual control.
vaulted_at
string · date-time
optionalWhen the receipt was hash chained into the vault, as an RFC 3339 timestamp in UTC. From this moment it never changes, and the leg it belongs to can reach completed.
Other responses
Errors it can return
curl -X POST "https://sandbox.droomwork.io/v1/remittance/receipts" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"leg_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","authority_reference":"paye-2026-09-rivers","amount":{"amount":7500000,"currency":"NGN"},"document_url":"https://files.sandbox.droomwork.com/example","attested_by":["usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"]}'import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceReceiptsCreate({
idempotencyKey: crypto.randomUUID(),
remitReceiptCreateRequest: {"legId":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","authorityReference":"paye-2026-09-rivers","amount":{"amount":7500000,"currency":"NGN"},"documentUrl":"https://files.sandbox.droomwork.com/example","attestedBy":["usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"]},
});const response = await fetch('https://sandbox.droomwork.io/v1/remittance/receipts', {
method: 'POST',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
"leg_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_reference": "paye-2026-09-rivers",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"document_url": "https://files.sandbox.droomwork.com/example",
"attested_by": [
"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
]
}),
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_receipts_create(body={"leg_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "authority_reference": "paye-2026-09-rivers", "amount": {"amount": 7500000, "currency": "NGN"}, "document_url": "https://files.sandbox.droomwork.com/example", "attested_by": ["usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"]})import os
import uuid
import requests
response = requests.request(
'POST',
'https://sandbox.droomwork.io/v1/remittance/receipts',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
'Idempotency-Key': str(uuid.uuid4()),
},
json={"leg_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "authority_reference": "paye-2026-09-rivers", "amount": {"amount": 7500000, "currency": "NGN"}, "document_url": "https://files.sandbox.droomwork.com/example", "attested_by": ["usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"]},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceReceiptsCreate($idempotencyKey, json_decode('{"leg_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","authority_reference":"paye-2026-09-rivers","amount":{"amount":7500000,"currency":"NGN"},"document_url":"https://files.sandbox.droomwork.com/example","attested_by":["usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"]}', true));<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/receipts');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
'Content-Type: application/json',
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
],
CURLOPT_POSTFIELDS => '{"leg_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","authority_reference":"paye-2026-09-rivers","amount":{"amount":7500000,"currency":"NGN"},"document_url":"https://files.sandbox.droomwork.com/example","attested_by":["usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"]}',
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceReceiptsCreate(idempotencyKey, body);var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/receipts"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.header("Content-Type", "application/json")
.header("Idempotency-Key", UUID.randomUUID().toString())
.method("POST", HttpRequest.BodyPublishers.ofString("""
{
"leg_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_reference": "paye-2026-09-rivers",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"document_url": "https://files.sandbox.droomwork.com/example",
"attested_by": [
"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
]
}
"""))
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceReceiptsCreate(idempotencyKey, body);using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/remittance/receipts");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent("""
{
"leg_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_reference": "paye-2026-09-rivers",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"document_url": "https://files.sandbox.droomwork.com/example",
"attested_by": [
"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
]
}
""", Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceReceiptsCreate(ctx).IdempotencyKey(key).RemitReceiptCreateRequest(body).Execute()body := strings.NewReader(`{
"leg_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_reference": "paye-2026-09-rivers",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"document_url": "https://files.sandbox.droomwork.com/example",
"attested_by": [
"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
]
}`)
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/remittance/receipts", body)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance_receipt",
"livemode": false,
"mocked": true,
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"period": "2026-09",
"evidence_class": "authority_api_receipt",
"hash": "sha256:9f2c1e0043a1b8",
"previous_hash": "sha256:9f2c1e0043a1b8",
"leg_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"obligation_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_reference": "paye-2026-09-rivers",
"document_url": "https://files.sandbox.droomwork.com/example",
"trace_references": [
"paye-2026-09-rivers"
],
"attested_by": [
"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
],
"vaulted_at": "2026-09-01T09:00:00Z"
}
/v1/remittance/receipts/{receipt_id}#Open one receipt in the vault
remittance.receipts.retrieve
A receipt is what an authority gives back when money reaches it. So an identifier you stored once is all you need to pull up a single payment's proof long after the month it covers.
Send the receipt's id in the path as receipt_id. You get the amount acknowledged, the month that payment covers, what kind of proof it is, and a link to the document where there is one.
Nothing changes a receipt once it is vaulted and nothing deletes one, so the id you hold reads the same record back whenever you ask. A receipt_id nothing holds answers not_found.
Path parameters
receipt_id
string
requiredThe receipt's identifier: the id of a receipt listed at GET /v1/remittance/receipts or recorded at POST /v1/remittance/receipts, or the receipt_id on a leg. It starts with remit_authority_rail_receipt_.
Returns
The receipt, with the hash that fixes its place in the vault, to keep beside your own copy.
id
string
requiredThe receipt's identifier, starting with remit_authority_rail_receipt_; it never changes. It is the receipt_id on the leg it proves and in receipt_ids on its obligation; pass it as receipt_id to GET /v1/remittance/receipts/{receipt_id}.
object
always "remittance_receipt"
requiredAlways remittance_receipt. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
leg_id
string · nullable
optionalThe id of the leg this receipt proves paid, from legs on a remittance or GET /v1/remittance/remittances/{remittance_id}/legs; vaulting the receipt takes that leg to completed. null when the receipt is not tied to a leg.
obligation_id
string · nullable
optionalThe id of the obligation this receipt settles against, from GET /v1/remittance/obligations, starting with remit_authority_rail_obligation_; the receipt also appears in its receipt_ids. null when not tied to an obligation.
authority_id
string
requiredThe id of the authority that issued this receipt, from GET /v1/remittance/authorities, starting with remit_authority_rail_obligation_; filter the list by it. It must agree with the leg's authority_id, or the receipt is quarantined.
period
string
requiredThe month the payment covers, as YYYY-MM, such as 2026-09; filter the list by it with the period query. It must agree with the leg's period, or the receipt is quarantined.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
authority_reference
string
optionalThe reference the authority itself issued.
evidence_class
string
requiredThe same classes apply whichever tier filed. An assisted manual filing carries a receipt reference, a document scan and an operator attestation under dual control, which is the same evidence class as an API filing.
authority_api_receiptportal_receiptassisted_manual_attesteddocument_url
string · uri · nullable
optionalWhere to fetch the receipt document the authority issued, as a URL. Present for an assisted manual filing, where you supplied the scan; null when there is no document.
hash
string
requiredThis receipt position in the append only chain.
previous_hash
string
requiredThe hash of the receipt vaulted just before this one. Each receipt carries the last one's hash, so you can walk the chain back and confirm nothing was changed or removed.
trace_references
array of string
optionalThe payroll trace references this receipt covers.
attested_by
array of string
optionalTwo actors for an assisted manual filing, under dual control.
vaulted_at
string · date-time
optionalWhen the receipt was hash chained into the vault, as an RFC 3339 timestamp in UTC. From this moment it never changes, and the leg it belongs to can reach completed.
Other responses
Errors it can return
curl -X GET "https://sandbox.droomwork.io/v1/remittance/receipts/remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceReceiptsRetrieve({ receiptId: 'remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/receipts/remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_receipts_retrieve(receipt_id='remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')import os
import requests
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/receipts/remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceReceiptsRetrieve(receipt_id: 'remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/receipts/remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceReceiptsRetrieve("remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/receipts/remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceReceiptsRetrieve(receiptId: "remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/receipts/remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceReceiptsRetrieve(ctx, "remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/receipts/remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance_receipt",
"livemode": false,
"mocked": true,
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"period": "2026-09",
"evidence_class": "authority_api_receipt",
"hash": "sha256:9f2c1e0043a1b8",
"previous_hash": "sha256:9f2c1e0043a1b8",
"leg_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"obligation_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_reference": "paye-2026-09-rivers",
"document_url": "https://files.sandbox.droomwork.com/example",
"trace_references": [
"paye-2026-09-rivers"
],
"attested_by": [
"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
],
"vaulted_at": "2026-09-01T09:00:00Z"
}
/v1/remittance/audit_exports#Bundle the receipts you hold into one file
remittance.audit_exports.create
This gathers the receipts you hold for one month, one authority or one employee into a single pack. So passing on a period's proof is one call and one file, not a folder of receipts you gathered yourself.
Send the scope you want covered. You get the pack back with an id starting remit_authority_rail_return_, its status, and, where there is one, a download_url to fetch the file from.
Nothing has to exist first.
Carry the id as audit_export_id to GET /v1/remittance/audit_exports/{audit_export_id}. No call lists your packs, so the id is the only way back to one.
Headers
Idempotency-Key
string
requiredA key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.
Body
period
string
optionalScope the pack to one month, as YYYY-MM, such as 2026-09: every receipt for that period goes in. Send this, authority_id or subject_id, and only one of them.
authority_id
string
optionalScope the pack to one authority, by its id from GET /v1/remittance/authorities, starting with remit_authority_rail_obligation_: every receipt filed with it goes in. Send this, period or subject_id, and only one of them.
subject_id
string
optionalScope the pack to one employee, by their subject identifier starting with sub_, the subject_id on their payslips at GET /v1/payroll/payslips: every receipt covering them goes in. Send this, period or authority_id, and only one of them.
Returns
The export.
id
string
requiredThe pack's identifier, first returned by POST /v1/remittance/audit_exports; it starts with remit_authority_rail_return_ and never changes. Pass it as audit_export_id to GET /v1/remittance/audit_exports/{audit_export_id} to poll the pack.
object
always "audit_export"
requiredAlways audit_export. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
status
string
requiredgenerating while the pack is being built, ready once it can be downloaded and verified, failed when it could not be produced. Poll GET /v1/remittance/audit_exports/{audit_export_id} until it leaves generating.
generatingreadyfailedscope
object
requiredWhat the pack covers, as the one scope you named when you asked for it: a period, an authority_id or a subject_id. The other two are null.
3 fields
period
string · nullable
optionalThe month the pack covers, as YYYY-MM, when you scoped it by period. null when you scoped it by authority or by employee.
authority_id
string · nullable
optionalThe authority the pack covers, when you scoped it by authority: the authority_id you sent to POST /v1/remittance/audit_exports, an id from GET /v1/remittance/authorities. null when you scoped it by period or by employee.
subject_id
string · nullable
optionalThe employee the pack covers, when you scoped it by employee: the subject_id you sent to POST /v1/remittance/audit_exports, their subject identifier starting with sub_. null when you scoped it by period or by authority.
download_url
string · uri · nullable
optionalWhere to fetch the pack, as a URL, once status is ready; null before then and when the pack failed. Verify what you download against signature.
signature
string · nullable
optionalVerify the pack against this without trusting the system that made it.
verification_instructions_url
string · uri · nullable
optionalWhere to read how to check the pack against its signature, as a URL; null until the pack is ready. Hand it on with the pack, so whoever receives it can verify it without trusting where it came from.
receipt_count
integer
optionalHow many vaulted receipts the pack holds for the scope you named. Compare it with your own count before you send the pack on; 0 means nothing was vaulted in that scope.
Other responses
Errors it can return
curl -X POST "https://sandbox.droomwork.io/v1/remittance/audit_exports" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"period":"2026-09","authority_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","subject_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"}'import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceAuditExportsCreate({
idempotencyKey: crypto.randomUUID(),
remitAuditExportCreateRequest: {"period":"2026-09","authorityId":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","subjectId":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"},
});const response = await fetch('https://sandbox.droomwork.io/v1/remittance/audit_exports', {
method: 'POST',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
"period": "2026-09",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"subject_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}),
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_audit_exports_create(body={"period": "2026-09", "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "subject_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"})import os
import uuid
import requests
response = requests.request(
'POST',
'https://sandbox.droomwork.io/v1/remittance/audit_exports',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
'Idempotency-Key': str(uuid.uuid4()),
},
json={"period": "2026-09", "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "subject_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceAuditExportsCreate($idempotencyKey, json_decode('{"period":"2026-09","authority_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","subject_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"}', true));<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/audit_exports');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
'Content-Type: application/json',
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
],
CURLOPT_POSTFIELDS => '{"period":"2026-09","authority_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","subject_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"}',
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceAuditExportsCreate(idempotencyKey, body);var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/audit_exports"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.header("Content-Type", "application/json")
.header("Idempotency-Key", UUID.randomUUID().toString())
.method("POST", HttpRequest.BodyPublishers.ofString("""
{
"period": "2026-09",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"subject_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}
"""))
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceAuditExportsCreate(idempotencyKey, body);using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/remittance/audit_exports");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent("""
{
"period": "2026-09",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"subject_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}
""", Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceAuditExportsCreate(ctx).IdempotencyKey(key).RemitAuditExportCreateRequest(body).Execute()body := strings.NewReader(`{
"period": "2026-09",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"subject_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}`)
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/remittance/audit_exports", body)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "audit_export",
"livemode": false,
"mocked": true,
"status": "generating",
"scope": {
"period": "2026-09",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"subject_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
},
"download_url": "https://files.sandbox.droomwork.com/example",
"signature": "example",
"verification_instructions_url": "https://files.sandbox.droomwork.com/example",
"receipt_count": 1
}
/v1/remittance/audit_exports/{audit_export_id}#Read back a pack you asked for
remittance.audit_exports.retrieve
An audit pack is one file holding the receipts for the month, authority or employee it was asked for. So the id that POST /v1/remittance/audit_exports returned brings the same pack back, without asking for it to be built again.
Send the pack's id in the path as audit_export_id. You get the pack's record again, with its status and, where there is one, the download_url to fetch the file from.
No call lists your packs, so the id is the only way back to one.
Path parameters
audit_export_id
string
requiredThe pack's identifier: the id of a pack you asked for at POST /v1/remittance/audit_exports. It starts with remit_authority_rail_return_; poll it here until status leaves generating.
Returns
The export.
id
string
requiredThe pack's identifier, first returned by POST /v1/remittance/audit_exports; it starts with remit_authority_rail_return_ and never changes. Pass it as audit_export_id to GET /v1/remittance/audit_exports/{audit_export_id} to poll the pack.
object
always "audit_export"
requiredAlways audit_export. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
status
string
requiredgenerating while the pack is being built, ready once it can be downloaded and verified, failed when it could not be produced. Poll GET /v1/remittance/audit_exports/{audit_export_id} until it leaves generating.
generatingreadyfailedscope
object
requiredWhat the pack covers, as the one scope you named when you asked for it: a period, an authority_id or a subject_id. The other two are null.
3 fields
period
string · nullable
optionalThe month the pack covers, as YYYY-MM, when you scoped it by period. null when you scoped it by authority or by employee.
authority_id
string · nullable
optionalThe authority the pack covers, when you scoped it by authority: the authority_id you sent to POST /v1/remittance/audit_exports, an id from GET /v1/remittance/authorities. null when you scoped it by period or by employee.
subject_id
string · nullable
optionalThe employee the pack covers, when you scoped it by employee: the subject_id you sent to POST /v1/remittance/audit_exports, their subject identifier starting with sub_. null when you scoped it by period or by authority.
download_url
string · uri · nullable
optionalWhere to fetch the pack, as a URL, once status is ready; null before then and when the pack failed. Verify what you download against signature.
signature
string · nullable
optionalVerify the pack against this without trusting the system that made it.
verification_instructions_url
string · uri · nullable
optionalWhere to read how to check the pack against its signature, as a URL; null until the pack is ready. Hand it on with the pack, so whoever receives it can verify it without trusting where it came from.
receipt_count
integer
optionalHow many vaulted receipts the pack holds for the scope you named. Compare it with your own count before you send the pack on; 0 means nothing was vaulted in that scope.
Other responses
Errors it can return
curl -X GET "https://sandbox.droomwork.io/v1/remittance/audit_exports/%7Baudit_export_id%7D" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceAuditExportsRetrieve({ auditExportId: '{audit_export_id}' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/audit_exports/%7Baudit_export_id%7D', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_audit_exports_retrieve(audit_export_id='{audit_export_id}')import os
import requests
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/audit_exports/%7Baudit_export_id%7D',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceAuditExportsRetrieve(audit_export_id: '{audit_export_id}');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/audit_exports/%7Baudit_export_id%7D');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceAuditExportsRetrieve("{audit_export_id}");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/audit_exports/%7Baudit_export_id%7D"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceAuditExportsRetrieve(auditExportId: "{audit_export_id}");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/audit_exports/%7Baudit_export_id%7D");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceAuditExportsRetrieve(ctx, "{audit_export_id}").Execute()req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/audit_exports/%7Baudit_export_id%7D", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "audit_export",
"livemode": false,
"mocked": true,
"status": "generating",
"scope": {
"period": "2026-09",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"subject_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
},
"download_url": "https://files.sandbox.droomwork.com/example",
"signature": "example",
"verification_instructions_url": "https://files.sandbox.droomwork.com/example",
"receipt_count": 1
}
/v1/remittance/reconciliations#Check your ring fenced account, day by day
remittance.reconciliations.list
This gives you the reconciliations your organisation holds, each one a day of the ring fenced account your statutory money moves through. So a screen in your product can carry a row for each day, and a reader sees which of them did not balance without opening one.
Every record carries the day as on, a balanced flag and any breaks recorded against that day, each break with the amount it is out by, in whole minor units with its currency.
Carry a record's id as reconciliation_id to read one day in full at GET /v1/remittance/reconciliations/{reconciliation_id}.
Query parameters
limit
integer
optionalHow many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.
on
string
optionalReturn only the reconciliation for one day, as YYYY-MM-DD, such as 2026-09-01: the on each reconciliation carries. Leave it out to get every day.
Returns
A page of reconciliations, each with the balances either end of the day, where the record has them.
object
always "list"
requiredAlways list. Tells you which kind of record you are looking at, so one handler can read any response.
data
array of Reconciliation
requiredThe records on this page, in the order the list promises. Empty when nothing matched.
9 fields of Reconciliation
id
string
requiredThe reconciliation's identifier, as listed at GET /v1/remittance/reconciliations; it starts with remit_authority_rail_return_ and never changes. Pass it as reconciliation_id to GET /v1/remittance/reconciliations/{reconciliation_id}.
object
always "reconciliation"
requiredAlways reconciliation. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
on
string · date
requiredThe day this reconciliation is for, as YYYY-MM-DD, such as 2026-09-01. One is produced for every day; filter the list by it with the on query.
balanced
boolean
requiredEvery kobo debited is a kobo credited, with no commingling.
opening_balance
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
closing_balance
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
breaks
array of object
requiredEmpty when balanced is true.
3 fields
code
string
requiredWhich kind of break this is, as a code you can match on, such as no_payee_destination. detail says what it means in words.
detail
string
requiredWhat went wrong, in words for a person to read, such as The payee has no verified destination, so this line cannot be paid. Match on code rather than on this text.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
has_more
boolean
requiredtrue when there are more records after this page. Pass the last record's id as starting_after to get the next page.
Other responses
Errors it can return
# query parameters: limit (optional), on (optional)
curl -X GET "https://sandbox.droomwork.io/v1/remittance/reconciliations?limit=25&on=2026-09-01" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
// query parameters: limit (optional), on (optional)
const result = await api.remittanceReconciliationsList({ limit: 25, on: '2026-09-01' });// query parameters: limit (optional), on (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/remittance/reconciliations?limit=25&on=2026-09-01', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
# query parameters: limit (optional), on (optional)
result = api.remittance_reconciliations_list(limit=25, on='2026-09-01')import os
import requests
# query parameters: limit (optional), on (optional)
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/reconciliations?limit=25&on=2026-09-01',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
# query parameters: limit (optional), on (optional)
$result = $api->remittanceReconciliationsList(limit: 25, on: '2026-09-01');<?php
// query parameters: limit (optional), on (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/reconciliations?limit=25&on=2026-09-01');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
// query parameters: limit (optional), on (optional)
var result = api.remittanceReconciliationsList(25, "2026-09-01");// query parameters: limit (optional), on (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/reconciliations?limit=25&on=2026-09-01"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
// query parameters: limit (optional), on (optional)
var result = api.RemittanceReconciliationsList(limit: 25, on: "2026-09-01");// query parameters: limit (optional), on (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/reconciliations?limit=25&on=2026-09-01");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
// query parameters: limit (optional), on (optional)
result, _, err := client.REMITAPI.RemittanceReconciliationsList(ctx).Limit(25).On("2026-09-01").Execute()// query parameters: limit (optional), on (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/reconciliations?limit=25&on=2026-09-01", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"object": "list",
"data": [
{
"id": "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "reconciliation",
"livemode": false,
"mocked": true,
"on": "2026-09-01",
"balanced": true,
"breaks": [
{
"code": "no_payee_destination",
"detail": "The payee has no verified destination, so this line cannot be paid.",
"amount": {
"amount": 7500000,
"currency": "NGN"
}
}
],
"opening_balance": {
"amount": 0,
"currency": "NGN"
},
"closing_balance": {
"amount": 41250000,
"currency": "NGN"
}
}
],
"has_more": true
}
/v1/remittance/reconciliations/{reconciliation_id}#See one day's debits against its credits
remittance.reconciliations.retrieve
A reconciliation is one day of the ring fenced account your statutory money moves through, and it says whether every kobo debited that day was a kobo credited, with nothing commingled. So one screen can show a break in words a person reads while your own code matches on the break's code.
Send the day's reconciliation_id in the path. You get the day as on, balanced, every break with the amount it is out by, in whole minor units with its currency, and the opening and closing balances where the record carries them.
Nothing else waits on this call. See the other days at GET /v1/remittance/reconciliations.
Path parameters
reconciliation_id
string
requiredThe reconciliation's identifier: the id of a reconciliation listed at GET /v1/remittance/reconciliations, starting with remit_authority_rail_return_. Each one is a day's proof that every kobo debited was a kobo credited.
Returns
The reconciliation, with no account number anywhere on it, only the day's own figures.
id
string
requiredThe reconciliation's identifier, as listed at GET /v1/remittance/reconciliations; it starts with remit_authority_rail_return_ and never changes. Pass it as reconciliation_id to GET /v1/remittance/reconciliations/{reconciliation_id}.
object
always "reconciliation"
requiredAlways reconciliation. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
on
string · date
requiredThe day this reconciliation is for, as YYYY-MM-DD, such as 2026-09-01. One is produced for every day; filter the list by it with the on query.
balanced
boolean
requiredEvery kobo debited is a kobo credited, with no commingling.
opening_balance
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
closing_balance
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
breaks
array of object
requiredEmpty when balanced is true.
3 fields
code
string
requiredWhich kind of break this is, as a code you can match on, such as no_payee_destination. detail says what it means in words.
detail
string
requiredWhat went wrong, in words for a person to read, such as The payee has no verified destination, so this line cannot be paid. Match on code rather than on this text.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
Other responses
Errors it can return
curl -X GET "https://sandbox.droomwork.io/v1/remittance/reconciliations/%7Breconciliation_id%7D" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceReconciliationsRetrieve({ reconciliationId: '{reconciliation_id}' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/reconciliations/%7Breconciliation_id%7D', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_reconciliations_retrieve(reconciliation_id='{reconciliation_id}')import os
import requests
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/reconciliations/%7Breconciliation_id%7D',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceReconciliationsRetrieve(reconciliation_id: '{reconciliation_id}');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/reconciliations/%7Breconciliation_id%7D');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceReconciliationsRetrieve("{reconciliation_id}");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/reconciliations/%7Breconciliation_id%7D"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceReconciliationsRetrieve(reconciliationId: "{reconciliation_id}");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/reconciliations/%7Breconciliation_id%7D");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceReconciliationsRetrieve(ctx, "{reconciliation_id}").Execute()req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/reconciliations/%7Breconciliation_id%7D", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "reconciliation",
"livemode": false,
"mocked": true,
"on": "2026-09-01",
"balanced": true,
"breaks": [
{
"code": "no_payee_destination",
"detail": "The payee has no verified destination, so this line cannot be paid.",
"amount": {
"amount": 7500000,
"currency": "NGN"
}
}
],
"opening_balance": {
"amount": 0,
"currency": "NGN"
},
"closing_balance": {
"amount": 41250000,
"currency": "NGN"
}
}
/v1/remittance/returns#Where each filing to an authority has reached
remittance.returns.list
This gives you the employer returns your organisation holds, which are the filings you owe each authority, not the payments you made to them. So a screen can set what you owe each authority side by side, one row for each period you have a return for.
Each record carries its kind, the authority_id it is filed with, the period it covers and its status, with the id you need for everything that follows.
Carry a row's id as return_id to read it in full at GET /v1/remittance/returns/{return_id}, or to approve it at POST /v1/remittance/returns/{return_id}/approve.
Query parameters
limit
integer
optionalHow many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.
starting_after
string
optionalThe id of the last record on the previous page of this same list. Leave it out to get the first page; when a page comes back with has_more true, send its last record's id here to get the page after it.
status
string
optionalRestricts the list to returns in one state: draft or pending_approval (not yet approved), approved, submitted (filed), accepted or rejected (the authority's answer). Leave it out to get every return.
draftpending_approvalapprovedsubmittedacceptedrejectedReturns
A page of returns.
object
always "list"
requiredAlways list. Tells you which kind of record you are looking at, so one handler can read any response.
data
array of EmployerReturn
requiredThe records on this page, in the order the list promises. Empty when nothing matched.
13 fields of EmployerReturn
id
string
requiredThe return's identifier, first given by POST /v1/remittance/returns and on every record of GET /v1/remittance/returns. It starts with remit_authority_rail_return_ and never changes; pass it as return_id to retrieve, approve or submit.
object
always "employer_return"
requiredAlways employer_return. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
kind
string
requiredmonthly_payeannual_payepension_schedulenhf_schedulensitf_returnitf_returnnhia_schedulestatus
string
requireddraftpending_approvalapprovedsubmittedacceptedrejectedauthority_id
string
requiredThe authority this return is filed with: the id of an authority from GET /v1/remittance/authorities, which starts with remit_authority_rail_obligation_. It is the authority_id you sent when you generated the return.
period
string
requiredThe period the return covers, as you named it: YYYY-MM for a month, YYYY for a whole year. For example 2026-09.
generated_from
array of string
optionalThe vaulted receipts this return was generated from.
totals
object
optionalWhat the return declares, summed from the vaulted receipts it was generated from: how many employees and the total amount.
2 fields
employee_count
integer
optionalHow many employees the return declares for the period.
total
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
approved_by
string · nullable
optionalA named person. Required before submission.
submitted_at
string · date-time · nullable
optionalWhen the return was filed with the authority, as an RFC 3339 timestamp in UTC. null until you submit it.
authority_reference
string · nullable
optionalThe reference the authority gave your filing, such as paye-2026-09-rivers. null until the authority has issued one.
has_more
boolean
requiredtrue when there are more records after this page. Pass the last record's id as starting_after to get the next page.
Other responses
Errors it can return
# query parameters: limit (optional), starting_after (optional), status (optional)
curl -X GET "https://sandbox.droomwork.io/v1/remittance/returns?limit=25&status=draft" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
// query parameters: limit (optional), starting_after (optional), status (optional)
const result = await api.remittanceReturnsList({ limit: 25, status: 'draft' });// query parameters: limit (optional), starting_after (optional), status (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/remittance/returns?limit=25&status=draft', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
# query parameters: limit (optional), starting_after (optional), status (optional)
result = api.remittance_returns_list(limit=25, status='draft')import os
import requests
# query parameters: limit (optional), starting_after (optional), status (optional)
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/returns?limit=25&status=draft',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
# query parameters: limit (optional), starting_after (optional), status (optional)
$result = $api->remittanceReturnsList(limit: 25, status: 'draft');<?php
// query parameters: limit (optional), starting_after (optional), status (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/returns?limit=25&status=draft');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
import com.droomwork.sdk.model.*;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
// query parameters: limit (optional), starting_after (optional), status (optional)
var result = api.remittanceReturnsList(25, null, RemitReturnStatus.fromValue("draft"));// query parameters: limit (optional), starting_after (optional), status (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/returns?limit=25&status=draft"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
// query parameters: limit (optional), starting_after (optional), status (optional)
var result = api.RemittanceReturnsList(limit: 25, status: RemitReturnStatus.Draft);// query parameters: limit (optional), starting_after (optional), status (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/returns?limit=25&status=draft");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
// query parameters: limit (optional), starting_after (optional), status (optional)
result, _, err := client.REMITAPI.RemittanceReturnsList(ctx).Limit(25).Status(droomwork.RemitReturnStatus("draft")).Execute()// query parameters: limit (optional), starting_after (optional), status (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/returns?limit=25&status=draft", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"object": "list",
"data": [
{
"id": "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "employer_return",
"livemode": false,
"mocked": true,
"kind": "monthly_paye",
"status": "draft",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"period": "2026-09",
"generated_from": [
"example"
],
"totals": {
"employee_count": 1,
"total": {
"amount": 57900000,
"currency": "NGN"
}
},
"approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"submitted_at": "2026-09-01T09:00:00Z",
"authority_reference": "paye-2026-09-rivers"
}
],
"has_more": true
}
/v1/remittance/returns#Produce a period's filing for one authority
remittance.returns.create
This opens the employer return for one period and one authority, which is the filing you owe them, not the payment you made to them. So your own system never has to total a period: the figures are taken from the receipts already in your vault.
Send the filing's kind, the authority_id to file with and the period it covers. You get the return back in draft, with the id you will approve and submit it by.
The receipts for that period and authority must already be in your vault, where executing a remittance at POST /v1/remittance/remittances/{remittance_id}/execute puts them.
Match period to the kind you asked for: YYYY-MM for a month, YYYY for a whole year.
Approve it at POST /v1/remittance/returns/{return_id}/approve before anything can be filed, passing the id as return_id.
Headers
Idempotency-Key
string
requiredA key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.
Body
kind
string
requiredmonthly_payeannual_payepension_schedulenhf_schedulensitf_returnitf_returnnhia_scheduleauthority_id
string
requiredThe authority to file with: the id of an authority from GET /v1/remittance/authorities, which starts with remit_authority_rail_obligation_. The return is generated from your vaulted receipts for that authority.
period
string
requiredThe period to file for, as YYYY-MM for a month or YYYY for a whole year, such as 2026-09. The figures come from your vaulted receipts for that period, not from you.
Returns
The new filing, with the totals it declares, so what will be filed can be checked first.
id
string
requiredThe return's identifier, first given by POST /v1/remittance/returns and on every record of GET /v1/remittance/returns. It starts with remit_authority_rail_return_ and never changes; pass it as return_id to retrieve, approve or submit.
object
always "employer_return"
requiredAlways employer_return. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
kind
string
requiredmonthly_payeannual_payepension_schedulenhf_schedulensitf_returnitf_returnnhia_schedulestatus
string
requireddraftpending_approvalapprovedsubmittedacceptedrejectedauthority_id
string
requiredThe authority this return is filed with: the id of an authority from GET /v1/remittance/authorities, which starts with remit_authority_rail_obligation_. It is the authority_id you sent when you generated the return.
period
string
requiredThe period the return covers, as you named it: YYYY-MM for a month, YYYY for a whole year. For example 2026-09.
generated_from
array of string
optionalThe vaulted receipts this return was generated from.
totals
object
optionalWhat the return declares, summed from the vaulted receipts it was generated from: how many employees and the total amount.
2 fields
employee_count
integer
optionalHow many employees the return declares for the period.
total
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
approved_by
string · nullable
optionalA named person. Required before submission.
submitted_at
string · date-time · nullable
optionalWhen the return was filed with the authority, as an RFC 3339 timestamp in UTC. null until you submit it.
authority_reference
string · nullable
optionalThe reference the authority gave your filing, such as paye-2026-09-rivers. null until the authority has issued one.
Other responses
Errors it can return
curl -X POST "https://sandbox.droomwork.io/v1/remittance/returns" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"kind":"monthly_paye","authority_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","period":"2026-09"}'import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceReturnsCreate({
idempotencyKey: crypto.randomUUID(),
remitEmployerReturnCreateRequest: {"kind":"monthly_paye","authorityId":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","period":"2026-09"},
});const response = await fetch('https://sandbox.droomwork.io/v1/remittance/returns', {
method: 'POST',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
"kind": "monthly_paye",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"period": "2026-09"
}),
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_returns_create(body={"kind": "monthly_paye", "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "period": "2026-09"})import os
import uuid
import requests
response = requests.request(
'POST',
'https://sandbox.droomwork.io/v1/remittance/returns',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
'Idempotency-Key': str(uuid.uuid4()),
},
json={"kind": "monthly_paye", "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "period": "2026-09"},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceReturnsCreate($idempotencyKey, json_decode('{"kind":"monthly_paye","authority_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","period":"2026-09"}', true));<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/returns');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
'Content-Type: application/json',
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
],
CURLOPT_POSTFIELDS => '{"kind":"monthly_paye","authority_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","period":"2026-09"}',
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceReturnsCreate(idempotencyKey, body);var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/returns"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.header("Content-Type", "application/json")
.header("Idempotency-Key", UUID.randomUUID().toString())
.method("POST", HttpRequest.BodyPublishers.ofString("""
{
"kind": "monthly_paye",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"period": "2026-09"
}
"""))
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceReturnsCreate(idempotencyKey, body);using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/remittance/returns");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent("""
{
"kind": "monthly_paye",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"period": "2026-09"
}
""", Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceReturnsCreate(ctx).IdempotencyKey(key).RemitEmployerReturnCreateRequest(body).Execute()body := strings.NewReader(`{
"kind": "monthly_paye",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"period": "2026-09"
}`)
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/remittance/returns", body)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "employer_return",
"livemode": false,
"mocked": true,
"kind": "monthly_paye",
"status": "draft",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"period": "2026-09",
"generated_from": [
"example"
],
"totals": {
"employee_count": 1,
"total": {
"amount": 57900000,
"currency": "NGN"
}
},
"approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"submitted_at": "2026-09-01T09:00:00Z",
"authority_reference": "paye-2026-09-rivers"
}
/v1/remittance/returns/{return_id}#One filing, and whether it is approved
remittance.returns.retrieve
An employer return is what you file with one authority for one period: the filing you owe them, not the payment you made to them. So a screen in your product can refresh a filing it saved earlier and see whether somebody has approved it yet.
Send the return_id in the path. You get the filing back: its kind, the authority_id it is for, the period it covers, and status for where it has got to.
Read status before you act on a filing you stored earlier: POST /v1/remittance/returns/{return_id}/approve is refused with conflict once it is approved, and POST /v1/remittance/returns/{return_id}/submit until it is.
Path parameters
return_id
string
requiredThe return's identifier: the id on the return POST /v1/remittance/returns gave you, or on any record of GET /v1/remittance/returns. It starts with remit_authority_rail_return_.
Returns
The filing, and the authority_reference the authority knows it by, so you can quote it when you ask them.
id
string
requiredThe return's identifier, first given by POST /v1/remittance/returns and on every record of GET /v1/remittance/returns. It starts with remit_authority_rail_return_ and never changes; pass it as return_id to retrieve, approve or submit.
object
always "employer_return"
requiredAlways employer_return. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
kind
string
requiredmonthly_payeannual_payepension_schedulenhf_schedulensitf_returnitf_returnnhia_schedulestatus
string
requireddraftpending_approvalapprovedsubmittedacceptedrejectedauthority_id
string
requiredThe authority this return is filed with: the id of an authority from GET /v1/remittance/authorities, which starts with remit_authority_rail_obligation_. It is the authority_id you sent when you generated the return.
period
string
requiredThe period the return covers, as you named it: YYYY-MM for a month, YYYY for a whole year. For example 2026-09.
generated_from
array of string
optionalThe vaulted receipts this return was generated from.
totals
object
optionalWhat the return declares, summed from the vaulted receipts it was generated from: how many employees and the total amount.
2 fields
employee_count
integer
optionalHow many employees the return declares for the period.
total
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
approved_by
string · nullable
optionalA named person. Required before submission.
submitted_at
string · date-time · nullable
optionalWhen the return was filed with the authority, as an RFC 3339 timestamp in UTC. null until you submit it.
authority_reference
string · nullable
optionalThe reference the authority gave your filing, such as paye-2026-09-rivers. null until the authority has issued one.
Other responses
Errors it can return
curl -X GET "https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceReturnsRetrieve({ returnId: 'remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_returns_retrieve(return_id='remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')import os
import requests
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceReturnsRetrieve(return_id: 'remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceReturnsRetrieve("remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceReturnsRetrieve(returnId: "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceReturnsRetrieve(ctx, "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "employer_return",
"livemode": false,
"mocked": true,
"kind": "monthly_paye",
"status": "draft",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"period": "2026-09",
"generated_from": [
"example"
],
"totals": {
"employee_count": 1,
"total": {
"amount": 57900000,
"currency": "NGN"
}
},
"approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"submitted_at": "2026-09-01T09:00:00Z",
"authority_reference": "paye-2026-09-rivers"
}
/v1/remittance/returns/{return_id}/approve#Approve a return for submission
remittance.returns.approve
This records the decision that a filing should go to the authority as it stands. So the moment a person signs a filing off becomes an event your product can act on, and approving files nothing by itself.
Send the return_id in the path and no request body. You get the filing back with status moved to approved, which is the only state submission runs from.
The filing has to exist, from POST /v1/remittance/returns, and be in draft or pending_approval.
A return already approved or submitted is refused with conflict. The event it publishes is return.approved. File it at POST /v1/remittance/returns/{return_id}/submit when you want it filed.
Path parameters
return_id
string
requiredThe return's identifier: the id on the return POST /v1/remittance/returns gave you, or on any record of GET /v1/remittance/returns. It starts with remit_authority_rail_return_.
Headers
Idempotency-Key
string
requiredA key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.
Returns
The filing with a named person on it, so one name answers for it from here on.
id
string
requiredThe return's identifier, first given by POST /v1/remittance/returns and on every record of GET /v1/remittance/returns. It starts with remit_authority_rail_return_ and never changes; pass it as return_id to retrieve, approve or submit.
object
always "employer_return"
requiredAlways employer_return. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
kind
string
requiredmonthly_payeannual_payepension_schedulenhf_schedulensitf_returnitf_returnnhia_schedulestatus
string
requireddraftpending_approvalapprovedsubmittedacceptedrejectedauthority_id
string
requiredThe authority this return is filed with: the id of an authority from GET /v1/remittance/authorities, which starts with remit_authority_rail_obligation_. It is the authority_id you sent when you generated the return.
period
string
requiredThe period the return covers, as you named it: YYYY-MM for a month, YYYY for a whole year. For example 2026-09.
generated_from
array of string
optionalThe vaulted receipts this return was generated from.
totals
object
optionalWhat the return declares, summed from the vaulted receipts it was generated from: how many employees and the total amount.
2 fields
employee_count
integer
optionalHow many employees the return declares for the period.
total
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
approved_by
string · nullable
optionalA named person. Required before submission.
submitted_at
string · date-time · nullable
optionalWhen the return was filed with the authority, as an RFC 3339 timestamp in UTC. null until you submit it.
authority_reference
string · nullable
optionalThe reference the authority gave your filing, such as paye-2026-09-rivers. null until the authority has issued one.
Other responses
Errors it can return
curl -X POST "https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/approve" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceReturnsApprove({ returnId: 'remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/approve', {
method: 'POST',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
'Idempotency-Key': crypto.randomUUID(),
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_returns_approve(return_id='remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')import os
import uuid
import requests
response = requests.request(
'POST',
'https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/approve',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
'Idempotency-Key': str(uuid.uuid4()),
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceReturnsApprove(return_id: 'remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/approve');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceReturnsApprove("remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/approve"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.header("Idempotency-Key", UUID.randomUUID().toString())
.method("POST", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceReturnsApprove(returnId: "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/approve");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceReturnsApprove(ctx, "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/approve", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "employer_return",
"livemode": false,
"mocked": true,
"kind": "monthly_paye",
"status": "approved",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"period": "2026-09",
"generated_from": [
"example"
],
"totals": {
"employee_count": 1,
"total": {
"amount": 57900000,
"currency": "NGN"
}
},
"approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"submitted_at": "2026-09-01T09:00:00Z",
"authority_reference": "paye-2026-09-rivers"
}
/v1/remittance/returns/{return_id}/submit#Submit an approved return to the authority
remittance.returns.submit
This files the return with the authority, which is the last step of the filing you drew up. So nothing reaches an authority before it has been approved, and a filing leaves only on the call you make to send it.
Send the return_id in the path and no request body. You get the whole filing back with status moved to submitted: its kind, authority_id and period are as you left them.
The filing has to be approved first, which POST /v1/remittance/returns/{return_id}/approve does.
A return that has not been approved is refused with conflict, and so is one already submitted. Nothing else waits on this call.
Path parameters
return_id
string
requiredThe return's identifier: the id on the return POST /v1/remittance/returns gave you, or on any record of GET /v1/remittance/returns. It starts with remit_authority_rail_return_.
Headers
Idempotency-Key
string
requiredA key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.
Returns
Submission accepted.
id
string
requiredThe return's identifier, first given by POST /v1/remittance/returns and on every record of GET /v1/remittance/returns. It starts with remit_authority_rail_return_ and never changes; pass it as return_id to retrieve, approve or submit.
object
always "employer_return"
requiredAlways employer_return. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
kind
string
requiredmonthly_payeannual_payepension_schedulenhf_schedulensitf_returnitf_returnnhia_schedulestatus
string
requireddraftpending_approvalapprovedsubmittedacceptedrejectedauthority_id
string
requiredThe authority this return is filed with: the id of an authority from GET /v1/remittance/authorities, which starts with remit_authority_rail_obligation_. It is the authority_id you sent when you generated the return.
period
string
requiredThe period the return covers, as you named it: YYYY-MM for a month, YYYY for a whole year. For example 2026-09.
generated_from
array of string
optionalThe vaulted receipts this return was generated from.
totals
object
optionalWhat the return declares, summed from the vaulted receipts it was generated from: how many employees and the total amount.
2 fields
employee_count
integer
optionalHow many employees the return declares for the period.
total
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
approved_by
string · nullable
optionalA named person. Required before submission.
submitted_at
string · date-time · nullable
optionalWhen the return was filed with the authority, as an RFC 3339 timestamp in UTC. null until you submit it.
authority_reference
string · nullable
optionalThe reference the authority gave your filing, such as paye-2026-09-rivers. null until the authority has issued one.
Other responses
Errors it can return
curl -X POST "https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/submit" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceReturnsSubmit({ returnId: 'remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/submit', {
method: 'POST',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
'Idempotency-Key': crypto.randomUUID(),
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_returns_submit(return_id='remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')import os
import uuid
import requests
response = requests.request(
'POST',
'https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/submit',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
'Idempotency-Key': str(uuid.uuid4()),
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceReturnsSubmit(return_id: 'remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/submit');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceReturnsSubmit("remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/submit"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.header("Idempotency-Key", UUID.randomUUID().toString())
.method("POST", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceReturnsSubmit(returnId: "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/submit");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceReturnsSubmit(ctx, "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/remittance/returns/remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/submit", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "employer_return",
"livemode": false,
"mocked": true,
"kind": "monthly_paye",
"status": "submitted",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"period": "2026-09",
"generated_from": [
"example"
],
"totals": {
"employee_count": 1,
"total": {
"amount": 57900000,
"currency": "NGN"
}
},
"approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"submitted_at": "2026-09-01T09:00:00Z",
"authority_reference": "paye-2026-09-rivers"
}
/v1/remittance/readiness#What REMIT needs before it files anything
remittance.readiness.retrieve
A filing rests on facts REMIT has to have before anything reaches an authority, and this is where they are written down. The list tells you which facts you may attest to and which are gates no attestation lifts, so the shape of the integration is settled before you build any of it.
Send no parameters. You get rows, one per fact REMIT asks for, naming the fact, its owner and the assurance it has to reach, and always_enforced beside them.
Nothing else waits on this call.
Returns
The readiness report.
object
always "readiness_report"
requiredAlways readiness_report. Tells you which kind of record you are looking at, so one handler can read any response.
module
string
requiredThe module whose readiness endpoint you called, such as GET /v1/payroll/readiness: anchor (identity), proof (credentials), rail (engagements), flow (sourcing), match (allocation), run (payroll), remit (remittance) or route (payouts).
anchorproofrailflowmatchrunremitroutemode
string
requiredintegrated means a required fact comes from the Droomwork module that owns it; standalone means you supply it yourself under an attestation. The checks are the same in both, and what each fact is worth is recorded on its row as held.
integratedstandaloneready
boolean
requiredtrue when every row is satisfied and the module has what it needs from you. false when a required fact is missing or held at too low an assurance; rows says which.
rows
array of ReadinessRow
requiredOne row per fact the module requires: who owns it, the assurance it needs, what you hold and whether that satisfies it. The rows that are not satisfied are what to bring.
8 fields of ReadinessRow
fact
string
requiredNamed for what it is, not for who supplies it.
owner
string
requiredThe sibling module that owns this fact when running integrated.
contract_row
string
optionalrequired
string
requiredHow a fact was established. Recorded on the fact rather than in configuration, so an attested identity and a verified one stay distinguishable a year later, which is the distinction that matters when something is disputed.
attestedverifiedheld
one of
requiredAssuranceorsource
string · nullable
optionalintegratedstandalonenullsatisfied
boolean
requiredmissing_because
string · nullable
optionalnot_suppliedassurance_too_lownullalways_enforced
array of string
optionalGates that hold in every mode and cannot be attested away. Consent before any source is queried, bank account validation, the tax identifiers returns are filed under, and duplicate detection within the organisation's own population.
authorities_without_credentials
array of string
optionalFiling cannot proceed for these until credentials are supplied.
Other responses
Errors it can return
curl -X GET "https://sandbox.droomwork.io/v1/remittance/readiness" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceReadinessRetrieve({});const response = await fetch('https://sandbox.droomwork.io/v1/remittance/readiness', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_readiness_retrieve()import os
import requests
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/readiness',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceReadinessRetrieve();<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/readiness');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceReadinessRetrieve();var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/readiness"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceReadinessRetrieve();using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/readiness");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceReadinessRetrieve(ctx).Execute()req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/readiness", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"object": "readiness_report",
"module": "remit",
"mode": "integrated",
"ready": true,
"rows": [
{
"fact": "instruction_set",
"owner": "run",
"contract_row": "6.2.1",
"required": "attested",
"held": "attested",
"source": "integrated",
"satisfied": true,
"missing_because": null
}
],
"always_enforced": [
"consent_token",
"bank_account_validation",
"tax_identifier_validation",
"duplicate_detection"
],
"authorities_without_credentials": []
}
/v1/remittance/instruction_sets/{instruction_set_id}/reject#Reject figures you do not want filed
remittance.instruction_sets.reject
This closes a submission you will not file. A rejected set is final: nothing is remitted against it and nothing moves it back, so a month you decided against cannot be committed later by another call or another system.
Send no request body. You get the whole set back, with its status now rejected and the figures it held kept as a record of what was sent.
The set must be waiting on your decision, which is where POST /v1/remittance/instruction_sets leaves it.
A month you rejected is submitted again as a new set at POST /v1/remittance/instruction_sets, and a rejected set is never corrected in place. A set that is no longer waiting on your decision is refused with conflict.
Path parameters
instruction_set_id
string
requiredThe set's identifier: the id returned by POST /v1/remittance/instruction_sets or listed at GET /v1/remittance/instruction_sets, or an import's instruction_set_id. It starts with remit_authority_rail_instruction_.
Headers
Idempotency-Key
string
requiredA key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.
Returns
The set, with no field on it recording who decided against it.
id
string
requiredThe set's identifier, starting remit_authority_rail_instruction_, as listed at GET /v1/remittance/instruction_sets. It never changes; pass it as instruction_set_id to retrieve, accept, reject or remit the set.
object
always "ingested_instruction_set"
requiredAlways ingested_instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
status
string
requiredNothing is committed until accepted.
receivedvalidatingpending_acceptanceacceptedrejectedsource
string
requiredWhere the set came from. Droomwork payroll or your own, by API or by file. Everything downstream behaves identically whichever it was.
runexternal_apiexternal_fileperiod
string
requiredThe month the set covers, as YYYY-MM, such as 2026-09. Filter the list by it with the period query.
run_id
string · nullable
optionalThe Droomwork payroll run the set came from, by its id from POST /v1/payroll/runs or GET /v1/payroll/runs, starting run_enterprise_. Present when source is run; null when the set came from your own payroll.
instructions
InstructionSet
optionalWhat is owed to whom for one run. This shape is owned jointly by RUN and REMIT. RUN row 19 emits it and REMIT row 1 ingests it, from RUN and from external payroll alike. It lives here rather than in either module document so the two cannot drift, which is the failure that would otherwise surface at M3 with RUN already accepted and paid. Totals reconcile to run totals to the kobo, because they sum payslip lines rather than recompute from an aggregate. This is the object REMIT ingests.
11 fields of InstructionSet
id
string
requiredThe instruction set's identifier, which never changes: read it at GET /v1/payroll/runs/{run_id}/instruction_set when Droomwork ran the payroll, and send the set on unchanged to POST /v1/remittance/instruction_sets. Quote it when you ask about the set.
object
always "instruction_set"
requiredAlways instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
run_id
string
requiredThe payroll run this set is owed for, by its id from POST /v1/payroll/runs, which starts with run_enterprise_. The set's totals reconcile to that run's totals to the kobo.
period
string
optionalThe pay period the amounts are owed for, as year and month, for example 2026-09.
paye
array of object
requiredGrouped by the State IRS of the employee's residence, not the employer's location.
5 fields
authority_id
string
requiredThe State Internal Revenue Service this PAYE is owed to, by its id from GET /v1/remittance/authorities, which starts with remit_authority_rail_obligation_. Use it wherever a call names the authority.
jurisdiction
string
requiredThe State Internal Revenue Service this line is grouped under, named in full, for example Rivers State Internal Revenue Service. Read it to label the line; authority_id names the authority in a call.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
payee_count
integer
optionalHow many employees this line's PAYE covers. Optional; when it is present, check it against your own headcount for that state.
reconciliation_reference
string
requiredThe reference that identifies this line when you reconcile it, for example paye-2026-09-rivers. Keep it with your own records so you can trace the line later.
pension
array of object
requiredGrouped by administrator and retirement savings account number.
6 fields
administrator_id
string
requiredThe Pension Fund Administrator these contributions are owed to, by its id from GET /v1/remittance/authorities with kind=pension_administrator, which starts with remit_authority_rail_obligation_. Use it wherever a call names the administrator.
administrator_name
string
optionalThe administrator's name in full, so you can label the line without a second call. Optional; administrator_id is what names the administrator in a call.
employee_amount
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
employer_amount
Money
optional2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
amount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
reconciliation_reference
string
requiredThe reference that identifies this line when you reconcile it. Keep it with your own records so you can trace the line later.
levies
array of object
requiredNHF, NSITF, ITF and NHIA totals, each with a reconciliation reference.
3 fields
code
string
requiredWhich levy this line is for: nhf the National Housing Fund, nsitf the Nigeria Social Insurance Trust Fund, itf the Industrial Training Fund, nhia the National Health Insurance Authority. One line per levy.
nhfnsitfitfnhiaamount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
reconciliation_reference
string
requiredThe reference that identifies this levy line when you reconcile it. Keep it with your own records so you can trace the line later.
totals
object
requiredThe set's grand total, which its lines sum to. From a Droomwork run it reconciles to the run's totals to the kobo.
1 field
total
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
validation_report
ValidationReport
requiredThe result of checking a submission before anything is committed. Names every failing entry rather than stopping at the first, so one submission tells you everything to fix. The same shape wherever the platform ingests, validates and reports, which is every bulk intake in every module.
4 fields of ValidationReport
entry_count
integer · minimum 0
requiredHow many entries the submission held: every row in the file or line in the instruction set, whether it passed or not.
error_count
integer · minimum 0
requiredHow many entries failed with an error. Each is named in entries with its position and why, so one submission tells you everything to fix.
warning_count
integer · minimum 0
requiredHow many entries passed with a warning, each named in entries. A warning does not fail the entry; it points at something to confirm before you go ahead.
entries
array of object
optionalOne item per error or warning found, with the row or line it sits on, its severity, a code and what was wrong. Empty or absent when every entry passed clean.
4 fields
index
integer · minimum 1
requiredThe row in a file, or the line in an instruction set.
severity
string
requirederror means the entry failed and must be fixed. warning means it passed, but points at something you should confirm before you go ahead.
errorwarningcode
string
requiredWhy the entry was flagged, as a code you can branch on. detail says the same in words and may change; the code does not.
detail
string
requiredWhat was wrong with the entry, in plain words. Show it beside the row; it may change, so branch on code.
jurisdiction_pack
object
optionalThe jurisdiction pack the set is pinned to, by identifier and version. Every line was recomputed against it, so its rules are the ones the validation report reflects.
2 fields
pack_id
string
optionalWhich jurisdiction pack the set is pinned to, such as ng-paye. We publish the packs and you never send this; with version, it names exactly which rules every line was checked against, and it stays with the set so you can show which rules applied.
version
string
optionalThe pack version the set was checked against, such as 2026.08.1. It's pinned, so a later pack release doesn't change what this set was judged by.
accepted_by
string · nullable
optionalWho accepted the set: the actor that called accept. null until the set is accepted.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
Other responses
Errors it can return
curl -X POST "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/reject" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceInstructionSetsReject({ instructionSetId: 'remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/reject', {
method: 'POST',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
'Idempotency-Key': crypto.randomUUID(),
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_instruction_sets_reject(instruction_set_id='remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')import os
import uuid
import requests
response = requests.request(
'POST',
'https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/reject',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
'Idempotency-Key': str(uuid.uuid4()),
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceInstructionSetsReject(instruction_set_id: 'remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/reject');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceInstructionSetsReject("remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/reject"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.header("Idempotency-Key", UUID.randomUUID().toString())
.method("POST", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceInstructionSetsReject(instructionSetId: "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/reject");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceInstructionSetsReject(ctx, "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/remittance/instruction_sets/remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/reject", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "ingested_instruction_set",
"livemode": false,
"mocked": true,
"status": "rejected",
"source": "run",
"period": "2026-09",
"validation_report": {
"entry_count": 0,
"error_count": 0,
"warning_count": 0,
"entries": [
{
"index": 1,
"severity": "error",
"code": "invalid_money_amount",
"detail": "The payee has no verified destination, so this line cannot be paid."
}
]
},
"run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"instructions": {
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "instruction_set",
"livemode": false,
"mocked": true,
"run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"paye": [
{
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"jurisdiction": "Rivers State Internal Revenue Service",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers",
"payee_count": 1
}
],
"pension": [
{
"administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers",
"administrator_name": "example",
"employee_amount": {
"amount": 4200000,
"currency": "NGN"
},
"employer_amount": {
"amount": 5400000,
"currency": "NGN"
}
}
],
"levies": [
{
"code": "nhf",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"reconciliation_reference": "paye-2026-09-rivers"
}
],
"totals": {
"total": {
"amount": 57900000,
"currency": "NGN"
}
},
"period": "2026-09",
"created_at": "2026-09-01T09:00:00Z"
},
"jurisdiction_pack": {
"pack_id": "ng-paye",
"version": "2026.08.1"
},
"accepted_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"created_at": "2026-09-01T09:00:00Z"
}
/v1/remittance/remittances/{remittance_id}/execute#Execute an approved remittance
remittance.remittances.execute
This is the call that files. Each leg of an approved remittance goes to its own authority, and what that authority acknowledges receiving comes back as a receipt in the vault, so your product can show a month's figures beside each authority's own proof of payment.
Send the remittance's id in the path and no request body. You get the whole remittance back, its total in whole minor units with its currency, and every leg with its own status and the amount it pays.
The remittance has to be approved first, at POST /v1/remittance/remittances/{remittance_id}/approve.
The proof of each filing is in the vault at GET /v1/remittance/receipts. A leg that came back failed is retried at POST /v1/remittance/remittances/{remittance_id}/legs/{leg_id}/retry. A remittance that is not approved is refused with conflict.
Path parameters
remittance_id
string
requiredThe remittance's identifier: the id of a remittance you created at POST /v1/remittance/remittances or listed at GET /v1/remittance/remittances. It starts with remit_authority_rail_remittance_.
Headers
Idempotency-Key
string
requiredA key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.
Returns
The remittance, with created_at where there is one, which dates the record and not this call.
id
string
requiredThe remittance's identifier, first returned by POST /v1/remittance/remittances; it starts with remit_authority_rail_remittance_ and never changes. Pass it as remittance_id wherever a call names this remittance.
object
always "remittance"
requiredAlways remittance. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm this record is in: false is the sandbox, true is live. Read it before you act on anything.
mocked
boolean
requiredWhere these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.
status
string
requireddraftapprovedexecutingcompletedpartially_completedfailedinstruction_set_id
string
requiredThe id of the accepted instruction set whose figures the legs pay, from POST /v1/remittance/instruction_sets, starting with remit_authority_rail_instruction_. Retrieve it at GET /v1/remittance/instruction_sets/{instruction_set_id}.
period
string
optionalThe month the remittance pays for, as YYYY-MM, such as 2026-09. It's the period of the instruction set it was created from.
total
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
legs
array of Leg
requiredOne leg per authority the remittance pays, each with its own state, amount and receipt. A leg runs on its own, so one authority being down never holds the others; read each to see what settled where.
11 fields of Leg
id
string
requiredThe leg's identifier, first returned in legs on the remittance from POST /v1/remittance/remittances; it never changes. Pass it as leg_id, with the remittance's id as remittance_id, to retrieve or retry the leg.
object
always "remittance_leg"
requiredAlways remittance_leg. Tells you which kind of record you are looking at, so one handler can read any response.
remittance_id
string
optionalThe id of the remittance this leg belongs to, from POST /v1/remittance/remittances; it starts with remit_authority_rail_remittance_. Every call that names the leg names it too, at /v1/remittance/remittances/{remittance_id}/legs/{leg_id}.
authority_id
string
requiredThe id of the authority this leg pays, as listed at GET /v1/remittance/authorities; it starts with remit_authority_rail_obligation_. Look it up at GET /v1/remittance/authorities/{authority_id} for its name, tier and capabilities.
authority_name
string
optionalThe authority's name as you'd write it, such as Rivers State Internal Revenue Service. For display; authority_id is what you match on.
tier
string
optionalHow the filing reaches the authority. Readable so you know what to expect on timing. Never something to code against, since all three present the same contract.
direct_apiportal_automationassisted_manualstatus
string
requiredA leg reaches completed only once its receipt is vaulted. quarantined means a receipt arrived but disagreed with the leg.
pendingexecutingawaiting_receiptcompletedquarantinedfailedamount
Money
required2 fields of Money
amount
integer · int64
requiredA whole number of the currency's minor unit, as defined by the ISO 4217 exponent. For NGN that is kobo, so 1234567 is twelve thousand three hundred and forty five naira and sixty seven kobo. A fractional value is refused with the code invalid_money_amount. Call GET /v1/currencies for the exponent of any currency. Never divide by a hundred by hand.
currency
string
requiredISO 4217 code.
receipt_id
string · nullable
optionalThe id of the receipt that is this leg's proof of payment, once vaulted; it starts with remit_authority_rail_receipt_ and you retrieve it at GET /v1/remittance/receipts/{receipt_id}. null until a receipt is vaulted.
attempts
integer · minimum 0
optionalHow many times filing this leg with its authority has been tried, retries included. 0 before the first try; read it with last_fault before you retry.
last_fault
string · nullable
optionalWhy the latest attempt failed, in words for a person to read, such as The register did not answer within the timeout. null when there is no fault to report; read it before you retry.
approved_by
string · nullable
optionalWho approved the remittance: the actor that called approve. null while it is still draft, and execution is refused until a person is named here.
created_at
string · date-time
optionalWhen the record was created, as an RFC 3339 timestamp in UTC.
Other responses
Errors it can return
curl -X POST "https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/execute" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceRemittancesExecute({ remittanceId: 'remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/execute', {
method: 'POST',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
'Idempotency-Key': crypto.randomUUID(),
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_remittances_execute(remittance_id='remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')import os
import uuid
import requests
response = requests.request(
'POST',
'https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/execute',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
'Idempotency-Key': str(uuid.uuid4()),
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceRemittancesExecute(remittance_id: 'remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/execute');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
'Idempotency-Key: ' . bin2hex(random_bytes(16)),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceRemittancesExecute("remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/execute"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.header("Idempotency-Key", UUID.randomUUID().toString())
.method("POST", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceRemittancesExecute(remittanceId: "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/execute");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceRemittancesExecute(ctx, "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/remittance/remittances/remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/execute", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance",
"livemode": false,
"mocked": true,
"status": "completed",
"instruction_set_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"legs": [
{
"id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "remittance_leg",
"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"status": "pending",
"amount": {
"amount": 7500000,
"currency": "NGN"
},
"remittance_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"authority_name": "Sandbox State Internal Revenue Service",
"tier": "direct_api",
"receipt_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"attempts": 0,
"last_fault": "The register did not answer within the timeout."
}
],
"total": {
"amount": 57900000,
"currency": "NGN"
},
"period": "2026-09",
"approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"created_at": "2026-09-01T09:00:00Z"
}
/v1/remittance/events#Catch up on your remittance history
remittance.events.list
REMIT records what happens to the records it holds, and this reads those events back. Every event carries the record as it stood at that moment, so your product can show what changed on an instruction set or a return, not only where it stands now.
Send nothing and you get a page of events across your records, oldest first, each under an evt_ identifier. Pass a record's id as stream for that record's own history in sequence order.
after counts inside one stream, so it needs stream beside it. Across records you get the order REMIT recorded events in, which is not always occurred_at order.
An event says what happened to a record and never who did it. GET /v1/remittance/audit_entries is who, matched on request_id.
Open one at GET /v1/remittance/events/{event_id}. Until something has happened in REMIT, this comes back empty and not refused.
Query parameters
stream
string
optionalThe id of the record whose events you want, such as an instruction set's (remit_authority_rail_instruction_…, from POST /v1/remittance/instruction_sets) or a return's (remit_authority_rail_return_…). Omit it to get every record's events.
after
integer
optionalThe last sequence you handled on that record; you get the events after it, so 0 reads from the start. Send stream beside it, because a sequence counts within one record's events.
limit
integer
optionalHow many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.
starting_after
string
optionalThe id of the last record on the previous page of this same list. Leave it out to get the first page; when a page comes back with has_more true, send its last record's id here to get the page after it.
Returns
A page of events, each with occurred_at, so your own log carries when each one happened.
object
always "list"
requiredAlways list. Tells you which kind of record you are looking at, so one handler can read any response.
data
array of StoredEvent
requiredThe records on this page, in the order the list promises. Empty when nothing matched.
13 fields of StoredEvent
id
string
requiredThe event's identifier, starting with evt_, the same on a webhook delivery and on the module's events list, such as GET /v1/payroll/events. It never changes: a redelivery carries the same id, so you can recognise an event you have already handled.
type
string
requiredWhat happened, as module.resource.past_tense_verb, for example run.payslip.calculated. Pick your handler on it; data takes the shape this type promises.
schema_version
integer · minimum 1
requiredThe version of the shape data takes for this type, starting at 1. A change to the shape raises it, so check it before you read data.
org_id
string
requiredThe organisation the event belongs to, by its id, which starts with org_: the one POST /v1/registrations gave you and GET /v1/me returns. You only ever receive events for your own organisation.
sequence
integer · minimum 0
requiredPer organisation and per stream. It is how a consumer tells a replay from a new event, and it is what the delivery guarantee rests on.
occurred_at
string · date-time
requiredWhen the event happened, as an RFC 3339 timestamp in UTC. Not when it was delivered: a redelivery carries the original value.
request_id
string
optionalThe request that caused this event, where one did: the Droomwork-Request-Id that request returned, starting with req_. Absent for an event a schedule raised, such as an engagement lapsing on its end date.
livemode
boolean
requiredWhich realm the event happened in. False is the sandbox.
mocked
boolean
requiredWhether a mock produced this fact, rather than an engine computing it. Recorded on the event when it was appended and never worked out afterwards from the realm: the two answers agree while every module is on its mock and part on the day the first engine ships. See ADR-0011.
source
string
requiredWhich part of Droomwork is the authority for this fact: anchor (identity), proof (credentials), rail (engagements), flow (sourcing), match (allocation), run (payroll), remit (remittance), route (payouts), gateway (the API's front door), iam (accounts and API keys), ledger (the books), registry (rule packs), delivery (webhooks and messages), documents (rendered payslips and instruments) or intelligence (AI decisions). Read the fact from there when it matters; your own copy is never the authority.
anchorproofrailflowmatchrunremitroutegatewayiamledgerregistrydeliverydocumentsintelligenceobject
always "event"
requiredAlways event. Tells you which kind of record you are looking at, so one handler can read any response.
stream
string
requiredThe id of the record the event is about: an instruction set (remit_authority_rail_instruction_…), obligation, leg, receipt or return (remit_authority_rail_return_…). sequence counts within it; replay with both at GET /v1/remittance/events.
data
object
requiredThe record the event is about, as it stood when the event happened. Its shape follows type: an instruction set, an obligation, a leg, a receipt or an employer return.
has_more
boolean
requiredtrue when there are more records after this page. Pass the last record's id as starting_after to get the next page.
Other responses
Errors it can return
# query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
curl -X GET "https://sandbox.droomwork.io/v1/remittance/events?stream=remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&after=0&limit=25" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
// query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
const result = await api.remittanceEventsList({ stream: 'remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', after: 0, limit: 25 });// query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/remittance/events?stream=remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&after=0&limit=25', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
# query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
result = api.remittance_events_list(stream='remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', after=0, limit=25)import os
import requests
# query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/events?stream=remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&after=0&limit=25',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
# query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
$result = $api->remittanceEventsList(stream: 'remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', after: 0, limit: 25);<?php
// query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/events?stream=remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&after=0&limit=25');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
// query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
var result = api.remittanceEventsList("remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", 0, 25, null);// query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/events?stream=remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&after=0&limit=25"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
// query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
var result = api.RemittanceEventsList(stream: "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", after: 0, limit: 25);// query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/events?stream=remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&after=0&limit=25");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
// query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
result, _, err := client.REMITAPI.RemittanceEventsList(ctx).Stream("remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").After(0).Limit(25).Execute()// query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/events?stream=remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&after=0&limit=25", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"object": "list",
"data": [
{
"id": "evt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"type": "run.payslip.calculated",
"schema_version": 1,
"org_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"sequence": 0,
"occurred_at": "2026-09-01T09:00:00Z",
"livemode": false,
"mocked": true,
"source": "anchor",
"request_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "event",
"stream": "example",
"data": {}
}
],
"has_more": true
}
/v1/remittance/events/{event_id}#Look up one event you already logged
remittance.events.retrieve
An event identifier on its own becomes the whole record here: what happened, which remittance record it happened to, and that record's state at the time. The identifier never changes, so an event you logged once still shows that record as it stood then, after the record itself has moved on.
Send the event's id in the path. You get the event whole: its type, the stream it belongs to, its sequence in that stream, and data, the record the event is about.
Carry stream and sequence to GET /v1/remittance/events as stream and after to read what followed in that record's history. An event_id nothing holds answers not_found.
Path parameters
event_id
string
requiredThe event's identifier: the id on an event from GET /v1/remittance/events or on the body of a webhook delivery. It starts with evt_, and a redelivery carries the same one.
Returns
The event, with occurred_at, so your own log carries when it happened.
id
string
requiredThe event's identifier, starting with evt_, the same on a webhook delivery and on the module's events list, such as GET /v1/payroll/events. It never changes: a redelivery carries the same id, so you can recognise an event you have already handled.
type
string
requiredWhat happened, as module.resource.past_tense_verb, for example run.payslip.calculated. Pick your handler on it; data takes the shape this type promises.
schema_version
integer · minimum 1
requiredThe version of the shape data takes for this type, starting at 1. A change to the shape raises it, so check it before you read data.
org_id
string
requiredThe organisation the event belongs to, by its id, which starts with org_: the one POST /v1/registrations gave you and GET /v1/me returns. You only ever receive events for your own organisation.
sequence
integer · minimum 0
requiredPer organisation and per stream. It is how a consumer tells a replay from a new event, and it is what the delivery guarantee rests on.
occurred_at
string · date-time
requiredWhen the event happened, as an RFC 3339 timestamp in UTC. Not when it was delivered: a redelivery carries the original value.
request_id
string
optionalThe request that caused this event, where one did: the Droomwork-Request-Id that request returned, starting with req_. Absent for an event a schedule raised, such as an engagement lapsing on its end date.
livemode
boolean
requiredWhich realm the event happened in. False is the sandbox.
mocked
boolean
requiredWhether a mock produced this fact, rather than an engine computing it. Recorded on the event when it was appended and never worked out afterwards from the realm: the two answers agree while every module is on its mock and part on the day the first engine ships. See ADR-0011.
source
string
requiredWhich part of Droomwork is the authority for this fact: anchor (identity), proof (credentials), rail (engagements), flow (sourcing), match (allocation), run (payroll), remit (remittance), route (payouts), gateway (the API's front door), iam (accounts and API keys), ledger (the books), registry (rule packs), delivery (webhooks and messages), documents (rendered payslips and instruments) or intelligence (AI decisions). Read the fact from there when it matters; your own copy is never the authority.
anchorproofrailflowmatchrunremitroutegatewayiamledgerregistrydeliverydocumentsintelligenceobject
always "event"
requiredAlways event. Tells you which kind of record you are looking at, so one handler can read any response.
stream
string
requiredThe id of the record the event is about: an instruction set (remit_authority_rail_instruction_…), obligation, leg, receipt or return (remit_authority_rail_return_…). sequence counts within it; replay with both at GET /v1/remittance/events.
data
object
requiredThe record the event is about, as it stood when the event happened. Its shape follows type: an instruction set, an obligation, a leg, a receipt or an employer return.
Other responses
Errors it can return
curl -X GET "https://sandbox.droomwork.io/v1/remittance/events/%7Bevent_id%7D" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceEventsRetrieve({ eventId: '{event_id}' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/events/%7Bevent_id%7D', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_events_retrieve(event_id='{event_id}')import os
import requests
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/events/%7Bevent_id%7D',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceEventsRetrieve(event_id: '{event_id}');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/events/%7Bevent_id%7D');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceEventsRetrieve("{event_id}");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/events/%7Bevent_id%7D"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceEventsRetrieve(eventId: "{event_id}");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/events/%7Bevent_id%7D");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceEventsRetrieve(ctx, "{event_id}").Execute()req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/events/%7Bevent_id%7D", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "evt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"type": "run.payslip.calculated",
"schema_version": 1,
"org_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"sequence": 0,
"occurred_at": "2026-09-01T09:00:00Z",
"livemode": false,
"mocked": true,
"source": "anchor",
"request_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "event",
"stream": "example",
"data": {}
}
/v1/remittance/audit_entries#Who approved or overrode what, and when
remittance.audit_entries.list
This is who did what in REMIT. Every attempt that changed something is recorded, and so is every one refused under a credential we recognised, so your product can name who approved a remittance or who overrode a discrepancy.
Send nothing, or narrow by action, actor, record, outcome or a window of time. You get a page of entries newest first, each naming who acted, what they attempted and the status they were given.
action matches exactly and holds the route pattern, not the URL you called, so read the value off an entry before you filter on it.
Your own successful reads leave no entry here, and nothing refused with unauthenticated is recorded, so a revoked credential's calls are not here either.
An entry never says what changed, or the reason behind a refusal. Read one in full at GET /v1/remittance/audit_entries/{audit_entry_id}.
Query parameters
action
string
optionalRestricts the list to attempts at one route, as action reads on an entry: the method and route pattern, such as POST /v1/remittance/returns. Leave it out to get attempts at every route.
actor_id
string
optionalRestricts the list to one credential, by the exact actor_id on its entries: the id of the API key (key_…) or staff account that made the attempt. Pair it with outcome=refused to see repeated refusals; leave it out to get every actor.
resource
string
optionalRestricts the list to attempts on one kind of record, as resource reads on an entry: the collection segment of the route, such as returns, remittances, legs or receipts. Leave it out to get every kind.
resource_id
string
optionalRestricts the list to attempts on one record, as resource_id reads on an entry: the identifier the route named, such as a return's id from POST /v1/remittance/returns (remit_authority_rail_return_…). Leave it out to get every record.
outcome
string
optionalRestricts the list to one outcome: succeeded, refused (a 4xx answer) or failed (a 5xx answer). refused is where to look for a credential being probed; leave it out to get every outcome.
succeededrefusedfailedrecorded_after
string
optionalOnly entries recorded after this moment, as an RFC 3339 timestamp in UTC such as 2026-01-01T00:00:00Z; an entry at exactly this time is left out. Leave it out to read from the oldest entry.
recorded_before
string
optionalOnly entries recorded before this moment, as an RFC 3339 timestamp in UTC such as 2027-01-01T00:00:00Z; an entry at exactly this time is left out. Pair it with recorded_after to read one window, or leave it out to read up to the newest.
limit
integer
optionalHow many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.
starting_after
string
optionalThe id of the last record on the previous page of this same list. Leave it out to get the first page; when a page comes back with has_more true, send its last record's id here to get the page after it.
Returns
A page of audit entries.
object
always "list"
requiredAlways list. Tells you which kind of record you are looking at, so one handler can read any response.
data
array of AuditEntry
requiredThe records on this page, in the order the list promises. Empty when nothing matched.
13 fields of AuditEntry
id
string
requiredThe entry's identifier, on every entry from GET /v1/remittance/audit_entries. It starts with audit_entry_ and never changes; pass it as audit_entry_id to GET /v1/remittance/audit_entries/{audit_entry_id} to retrieve one entry.
object
always "audit_entry"
requiredAlways audit_entry. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm the action happened in. False is the sandbox.
mocked
boolean
requiredWhether the route this attempt was aimed at is mocked. It describes the route, not the answer: a refused attempt and a replayed idempotent request against a mocked route both record true. Recorded with the entry, not inferred from the realm beside it.
at
string · date-time
requiredWhen the attempt was recorded, as an RFC 3339 timestamp in UTC. The list is ordered by it, newest first.
request_id
string
requiredThe request this attempt was made in: the Droomwork-Request-Id header on its response, and the request_id on any error body. Quote it when you ask us about one.
actor_type
string
requiredWhat kind of credential made the attempt: client for an API key or OAuth client, user for a signed-in person, staff for a Droomwork staff member under a grant, service when Droomwork acted for you.
actor_id
string
requiredThe id of the credential that made the attempt, of the kind actor_type says: the API key's (key_…) for client, the staff account's for staff. Pass it as actor_id to GET /v1/remittance/audit_entries to follow one credential.
action
string
requiredWhat was attempted, as the method and the route pattern.
resource
string · nullable
optionalThe kind of record acted on, as the collection segment of the route, such as returns or legs. null when the route named none.
resource_id
string · nullable
optionalThe id of the record the route named, such as a return's from POST /v1/remittance/returns (remit_authority_rail_return_…) on /v1/remittance/returns/{return_id}. null for an attempt on a collection, such as creating or listing.
outcome
string
requiredHow the attempt ended: succeeded (a status below 400), refused (a 4xx status) or failed (a 5xx status). status carries the exact code.
succeededrefusedfailedstatus
integer
requiredThe HTTP status the caller was given, such as 201, 403 or 500. outcome follows it: below 400 is succeeded, 4xx is refused, 5xx is failed.
has_more
boolean
requiredtrue when there are more records after this page. Pass the last record's id as starting_after to get the next page.
Other responses
Errors it can return
# query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
curl -X GET "https://sandbox.droomwork.io/v1/remittance/audit_entries?action=POST%20%2Fv1%2Fremittance%2Freturns&actor_id=usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&resource=returns&resource_id=remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&outcome=succeeded&recorded_after=2026-01-01T00%3A00%3A00Z&recorded_before=2027-01-01T00%3A00%3A00Z&limit=25" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
// query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
const result = await api.remittanceAuditEntriesList({ action: 'POST /v1/remittance/returns', actorId: 'usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', resource: 'returns', resourceId: 'remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', outcome: 'succeeded', recordedAfter: '2026-01-01T00:00:00Z', recordedBefore: '2027-01-01T00:00:00Z', limit: 25 });// query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/remittance/audit_entries?action=POST%20%2Fv1%2Fremittance%2Freturns&actor_id=usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&resource=returns&resource_id=remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&outcome=succeeded&recorded_after=2026-01-01T00%3A00%3A00Z&recorded_before=2027-01-01T00%3A00%3A00Z&limit=25', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
# query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
result = api.remittance_audit_entries_list(action='POST /v1/remittance/returns', actor_id='usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', resource='returns', resource_id='remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', outcome='succeeded', recorded_after='2026-01-01T00:00:00Z', recorded_before='2027-01-01T00:00:00Z', limit=25)import os
import requests
# query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/audit_entries?action=POST%20%2Fv1%2Fremittance%2Freturns&actor_id=usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&resource=returns&resource_id=remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&outcome=succeeded&recorded_after=2026-01-01T00%3A00%3A00Z&recorded_before=2027-01-01T00%3A00%3A00Z&limit=25',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
# query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
$result = $api->remittanceAuditEntriesList(action: 'POST /v1/remittance/returns', actor_id: 'usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', resource: 'returns', resource_id: 'remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', outcome: 'succeeded', recorded_after: '2026-01-01T00:00:00Z', recorded_before: '2027-01-01T00:00:00Z', limit: 25);<?php
// query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/audit_entries?action=POST%20%2Fv1%2Fremittance%2Freturns&actor_id=usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&resource=returns&resource_id=remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&outcome=succeeded&recorded_after=2026-01-01T00%3A00%3A00Z&recorded_before=2027-01-01T00%3A00%3A00Z&limit=25');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
// query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
var result = api.remittanceAuditEntriesList("POST /v1/remittance/returns", "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "returns", "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "succeeded", "2026-01-01T00:00:00Z", "2027-01-01T00:00:00Z", 25, null);// query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/audit_entries?action=POST%20%2Fv1%2Fremittance%2Freturns&actor_id=usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&resource=returns&resource_id=remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&outcome=succeeded&recorded_after=2026-01-01T00%3A00%3A00Z&recorded_before=2027-01-01T00%3A00%3A00Z&limit=25"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
// query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
var result = api.RemittanceAuditEntriesList(action: "POST /v1/remittance/returns", actorId: "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", resource: "returns", resourceId: "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", outcome: "succeeded", recordedAfter: "2026-01-01T00:00:00Z", recordedBefore: "2027-01-01T00:00:00Z", limit: 25);// query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/audit_entries?action=POST%20%2Fv1%2Fremittance%2Freturns&actor_id=usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&resource=returns&resource_id=remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&outcome=succeeded&recorded_after=2026-01-01T00%3A00%3A00Z&recorded_before=2027-01-01T00%3A00%3A00Z&limit=25");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
// query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
result, _, err := client.REMITAPI.RemittanceAuditEntriesList(ctx).Action("POST /v1/remittance/returns").ActorId("usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Resource("returns").ResourceId("remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Outcome("succeeded").RecordedAfter("2026-01-01T00:00:00Z").RecordedBefore("2027-01-01T00:00:00Z").Limit(25).Execute()// query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/audit_entries?action=POST%20%2Fv1%2Fremittance%2Freturns&actor_id=usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&resource=returns&resource_id=remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&outcome=succeeded&recorded_after=2026-01-01T00%3A00%3A00Z&recorded_before=2027-01-01T00%3A00%3A00Z&limit=25", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"object": "list",
"data": [
{
"id": "audit_entry_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "audit_entry",
"livemode": false,
"mocked": true,
"at": "2026-09-01T09:00:00Z",
"request_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"actor_type": "example",
"actor_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"action": "example",
"outcome": "succeeded",
"status": 1,
"resource": "returns",
"resource_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}
],
"has_more": true
}
/v1/remittance/audit_entries/{audit_entry_id}#Account for one attempt in full
remittance.audit_entries.retrieve
An audit entry is one attempt to change something, or one that was refused, and this reads one back. It names the credential behind the attempt and the exact status it was answered with, so an approval or an override can be traced to one actor and one moment.
Send the entry's id in the path. You get when the attempt was made, which credential made it, what it was aimed at, and how it ended.
An entry never says what changed, or the reason behind a refusal. For what happened to the record itself, read GET /v1/remittance/events.
Where resource_id is set, open that record, such as a return at GET /v1/remittance/returns/{return_id}. An audit_entry_id nothing holds answers not_found.
Path parameters
audit_entry_id
string
requiredThe entry's identifier: the id on an entry from GET /v1/remittance/audit_entries. It starts with audit_entry_.
Returns
The audit entry.
id
string
requiredThe entry's identifier, on every entry from GET /v1/remittance/audit_entries. It starts with audit_entry_ and never changes; pass it as audit_entry_id to GET /v1/remittance/audit_entries/{audit_entry_id} to retrieve one entry.
object
always "audit_entry"
requiredAlways audit_entry. Tells you which kind of record you are looking at, so one handler can read any response.
livemode
boolean
requiredWhich realm the action happened in. False is the sandbox.
mocked
boolean
requiredWhether the route this attempt was aimed at is mocked. It describes the route, not the answer: a refused attempt and a replayed idempotent request against a mocked route both record true. Recorded with the entry, not inferred from the realm beside it.
at
string · date-time
requiredWhen the attempt was recorded, as an RFC 3339 timestamp in UTC. The list is ordered by it, newest first.
request_id
string
requiredThe request this attempt was made in: the Droomwork-Request-Id header on its response, and the request_id on any error body. Quote it when you ask us about one.
actor_type
string
requiredWhat kind of credential made the attempt: client for an API key or OAuth client, user for a signed-in person, staff for a Droomwork staff member under a grant, service when Droomwork acted for you.
actor_id
string
requiredThe id of the credential that made the attempt, of the kind actor_type says: the API key's (key_…) for client, the staff account's for staff. Pass it as actor_id to GET /v1/remittance/audit_entries to follow one credential.
action
string
requiredWhat was attempted, as the method and the route pattern.
resource
string · nullable
optionalThe kind of record acted on, as the collection segment of the route, such as returns or legs. null when the route named none.
resource_id
string · nullable
optionalThe id of the record the route named, such as a return's from POST /v1/remittance/returns (remit_authority_rail_return_…) on /v1/remittance/returns/{return_id}. null for an attempt on a collection, such as creating or listing.
outcome
string
requiredHow the attempt ended: succeeded (a status below 400), refused (a 4xx status) or failed (a 5xx status). status carries the exact code.
succeededrefusedfailedstatus
integer
requiredThe HTTP status the caller was given, such as 201, 403 or 500. outcome follows it: below 400 is succeeded, 4xx is refused, 5xx is failed.
Other responses
Errors it can return
curl -X GET "https://sandbox.droomwork.io/v1/remittance/audit_entries/%7Baudit_entry_id%7D" \
-H "Droomwork-Api-Key: $DROOMWORK_API_KEY"import { Configuration, REMITApi } from '@droomwork/sdk';
const api = new REMITApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));
const result = await api.remittanceAuditEntriesRetrieve({ auditEntryId: '{audit_entry_id}' });const response = await fetch('https://sandbox.droomwork.io/v1/remittance/audit_entries/%7Baudit_entry_id%7D', {
method: 'GET',
headers: {
'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
},
});
const result = await response.json();import os
import droomwork
config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.REMITApi(client)
result = api.remittance_audit_entries_retrieve(audit_entry_id='{audit_entry_id}')import os
import requests
response = requests.request(
'GET',
'https://sandbox.droomwork.io/v1/remittance/audit_entries/%7Baudit_entry_id%7D',
headers={
'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
},
)
result = response.json()<?php
require_once __DIR__ . '/vendor/autoload.php';
$config = DroomworkSdk\Configuration::getDefaultConfiguration()
->setHost('https://sandbox.droomwork.io')
->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\REMITApi(new GuzzleHttp\Client(), $config);
$result = $api->remittanceAuditEntriesRetrieve(audit_entry_id: '{audit_entry_id}');<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/audit_entries/%7Baudit_entry_id%7D');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => [
'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
],
]);
$result = json_decode(curl_exec($ch), true);import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.RemitApi;
ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
RemitApi api = new RemitApi(client);
var result = api.remittanceAuditEntriesRetrieve("{audit_entry_id}");var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/remittance/audit_entries/%7Baudit_entry_id%7D"))
.header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;
var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new REMITApi(config);
var result = api.RemittanceAuditEntriesRetrieve(auditEntryId: "{audit_entry_id}");using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/remittance/audit_entries/%7Baudit_entry_id%7D");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();import droomwork "github.com/fenibofubara/droomwork-sdk-go"
ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)
result, _, err := client.REMITAPI.RemittanceAuditEntriesRetrieve(ctx, "{audit_entry_id}").Execute()req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/audit_entries/%7Baudit_entry_id%7D", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
{
"id": "audit_entry_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"object": "audit_entry",
"livemode": false,
"mocked": true,
"at": "2026-09-01T09:00:00Z",
"request_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"actor_type": "example",
"actor_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
"action": "example",
"outcome": "succeeded",
"status": 1,
"resource": "returns",
"resource_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}