DDroomwork Developers

Version 1.0.0

Droomwork REMIT AUTHORITY RAIL

Statutory remittance to Nigerian authorities, with proof of every payment.

Base URLhttps://sandbox.droomwork.io
AuthenticationDroomwork-Api-Key: dw_test_… or Authorization: Bearer dw_test_…
Events it sends8 webhooks →
Signed in: requests you run on this page use a key made for your account. Your keys →

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?

GET/v1/remittance/instruction_sets#

List instruction sets

remittance.instruction_sets.list

Lists your instruction sets, newest first.

Query parameters

limit integer optional

How 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 optional

The 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 optional

Return 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_acceptanceacceptedrejected
period string optional

Return 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.

object always "list" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of IngestedInstructionSet required

The records on this page, in the order the list promises. Empty when nothing matched.

13 fields of IngestedInstructionSet
id string required

The 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" required

Always ingested_instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

Nothing is committed until accepted.

receivedvalidatingpending_acceptanceacceptedrejected
source string required

Where the set came from. Droomwork payroll or your own, by API or by file. Everything downstream behaves identically whichever it was.

runexternal_apiexternal_file
period string required

The month the set covers, as YYYY-MM, such as 2026-09. Filter the list by it with the period query.

run_id string · nullable optional

The 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 optional

What 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 required

The 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" required

Always instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

The 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 optional

The pay period the amounts are owed for, as year and month, for example 2026-09.

paye array of object required

Grouped by the State IRS of the employee's residence, not the employer's location.

5 fields
authority_id string required

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

payee_count integer optional

How many employees this line's PAYE covers. Optional; when it is present, check it against your own headcount for that state.

reconciliation_reference string required

The 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 required

Grouped by administrator and retirement savings account number.

6 fields
administrator_id string required

The 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 optional

The 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 optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

employer_amount Money optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

reconciliation_reference string required

The 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 required

NHF, NSITF, ITF and NHIA totals, each with a reconciliation reference.

3 fields
code string required

Which 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.

nhfnsitfitfnhia
amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

reconciliation_reference string required

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

validation_report ValidationReport required

The 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 required

How 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 required

How 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 required

How 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 optional

One 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 required

The row in a file, or the line in an instruction set.

severity string required

error means the entry failed and must be fixed. warning means it passed, but points at something you should confirm before you go ahead.

errorwarning
code string required

Why 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 required

What was wrong with the entry, in plain words. Show it beside the row; it may change, so branch on code.

jurisdiction_pack object optional

The 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 optional

Which 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 optional

The 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 optional

Who accepted the set: the actor that called accept. null until the set is accepted.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

has_more boolean required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# 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)
Response
{
  "object": "list",
  "data": [
    {
      "id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "ingested_instruction_set",
      "livemode": true,
      "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": "no_payee_destination",
            "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": true,
        "mocked": true,
        "run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
        "paye": [
          {
            "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
            "jurisdiction": "Rivers State Internal Revenue Service",
            "amount": {
              "amount": 1234567,
              "currency": "NGN"
            },
            "reconciliation_reference": "paye-2026-09-rivers",
            "payee_count": 1
          }
        ],
        "pension": [
          {
            "administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
            "amount": {
              "amount": 1234567,
              "currency": "NGN"
            },
            "reconciliation_reference": "paye-2026-09-rivers",
            "administrator_name": "Rivers State Internal Revenue Service",
            "employee_amount": {
              "amount": 1234567,
              "currency": "NGN"
            },
            "employer_amount": {
              "amount": 1234567,
              "currency": "NGN"
            }
          }
        ],
        "levies": [
          {
            "code": "nhf",
            "amount": {
              "amount": 1234567,
              "currency": "NGN"
            },
            "reconciliation_reference": "paye-2026-09-rivers"
          }
        ],
        "totals": {
          "total": {
            "amount": 1234567,
            "currency": "NGN"
          }
        },
        "period": "2026-09",
        "created_at": "2026-09-01T09:00:00Z"
      },
      "jurisdiction_pack": {
        "pack_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
        "version": "2026.08.1"
      },
      "accepted_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "created_at": "2026-09-01T09:00:00Z"
    }
  ],
  "has_more": true
}
POST/v1/remittance/instruction_sets#

Submit an instruction set

remittance.instruction_sets.create

Send what your payroll says is owed, from Droomwork payroll or from your own system. We recompute every line against the jurisdiction pack the set is pinned to, and you get the result back as a validation report.

Nothing is committed here. The set sits in pending_acceptance until you accept it.

Headers

Idempotency-Key string required

A 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 required

The 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 optional

The 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 required

What 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 required

The 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" required

Always instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

The 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 optional

The pay period the amounts are owed for, as year and month, for example 2026-09.

paye array of object required

Grouped by the State IRS of the employee's residence, not the employer's location.

5 fields
authority_id string required

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

payee_count integer optional

How many employees this line's PAYE covers. Optional; when it is present, check it against your own headcount for that state.

reconciliation_reference string required

The 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 required

Grouped by administrator and retirement savings account number.

6 fields
administrator_id string required

The 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 optional

The 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 optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

employer_amount Money optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

reconciliation_reference string required

The 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 required

NHF, NSITF, ITF and NHIA totals, each with a reconciliation reference.

3 fields
code string required

Which 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.

nhfnsitfitfnhia
amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

reconciliation_reference string required

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Returns

The ingested set, with its validation report.

id string required

The 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" required

Always ingested_instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

Nothing is committed until accepted.

receivedvalidatingpending_acceptanceacceptedrejected
source string required

Where the set came from. Droomwork payroll or your own, by API or by file. Everything downstream behaves identically whichever it was.

runexternal_apiexternal_file
period string required

The month the set covers, as YYYY-MM, such as 2026-09. Filter the list by it with the period query.

run_id string · nullable optional

The 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 optional

What 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 required

The 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" required

Always instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

The 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 optional

The pay period the amounts are owed for, as year and month, for example 2026-09.

paye array of object required

Grouped by the State IRS of the employee's residence, not the employer's location.

5 fields
authority_id string required

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

payee_count integer optional

How many employees this line's PAYE covers. Optional; when it is present, check it against your own headcount for that state.

reconciliation_reference string required

The 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 required

Grouped by administrator and retirement savings account number.

6 fields
administrator_id string required

The 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 optional

The 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 optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

employer_amount Money optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

reconciliation_reference string required

The 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 required

NHF, NSITF, ITF and NHIA totals, each with a reconciliation reference.

3 fields
code string required

Which 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.

nhfnsitfitfnhia
amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

reconciliation_reference string required

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

validation_report ValidationReport required

The 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 required

How 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 required

How 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 required

How 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 optional

One 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 required

The row in a file, or the line in an instruction set.

severity string required

error means the entry failed and must be fixed. warning means it passed, but points at something you should confirm before you go ahead.

errorwarning
code string required

Why 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 required

What was wrong with the entry, in plain words. Show it beside the row; it may change, so branch on code.

jurisdiction_pack object optional

The 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 optional

Which 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 optional

The 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 optional

Who accepted the set: the actor that called accept. null until the set is accepted.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.
422A required fact is missing. Call the readiness endpoint to see what.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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":true,"mocked":true,"run_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","paye":[{"authority_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","jurisdiction":"Rivers State Internal Revenue Service","amount":{"amount":1234567,"currency":"NGN"},"reconciliation_reference":"paye-2026-09-rivers","payee_count":1}],"pension":[{"administrator_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","amount":{"amount":1234567,"currency":"NGN"},"reconciliation_reference":"paye-2026-09-rivers","administrator_name":"Rivers State Internal Revenue Service","employee_amount":{"amount":1234567,"currency":"NGN"},"employer_amount":{"amount":1234567,"currency":"NGN"}}],"levies":[{"code":"nhf","amount":{"amount":1234567,"currency":"NGN"},"reconciliation_reference":"paye-2026-09-rivers"}],"totals":{"total":{"amount":1234567,"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":true,"mocked":true,"runId":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","paye":[{"authorityId":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","jurisdiction":"Rivers State Internal Revenue Service","amount":{"amount":1234567,"currency":"NGN"},"reconciliationReference":"paye-2026-09-rivers","payeeCount":1}],"pension":[{"administratorId":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","amount":{"amount":1234567,"currency":"NGN"},"reconciliationReference":"paye-2026-09-rivers","administratorName":"Rivers State Internal Revenue Service","employeeAmount":{"amount":1234567,"currency":"NGN"},"employerAmount":{"amount":1234567,"currency":"NGN"}}],"levies":[{"code":"nhf","amount":{"amount":1234567,"currency":"NGN"},"reconciliationReference":"paye-2026-09-rivers"}],"totals":{"total":{"amount":1234567,"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": true,
      "mocked": true,
      "run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "paye": [
        {
          "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
          "jurisdiction": "Rivers State Internal Revenue Service",
          "amount": {
            "amount": 1234567,
            "currency": "NGN"
          },
          "reconciliation_reference": "paye-2026-09-rivers",
          "payee_count": 1
        }
      ],
      "pension": [
        {
          "administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
          "amount": {
            "amount": 1234567,
            "currency": "NGN"
          },
          "reconciliation_reference": "paye-2026-09-rivers",
          "administrator_name": "Rivers State Internal Revenue Service",
          "employee_amount": {
            "amount": 1234567,
            "currency": "NGN"
          },
          "employer_amount": {
            "amount": 1234567,
            "currency": "NGN"
          }
        }
      ],
      "levies": [
        {
          "code": "nhf",
          "amount": {
            "amount": 1234567,
            "currency": "NGN"
          },
          "reconciliation_reference": "paye-2026-09-rivers"
        }
      ],
      "totals": {
        "total": {
          "amount": 1234567,
          "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": True, "mocked": True, "run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "paye": [{"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "jurisdiction": "Rivers State Internal Revenue Service", "amount": {"amount": 1234567, "currency": "NGN"}, "reconciliation_reference": "paye-2026-09-rivers", "payee_count": 1}], "pension": [{"administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "amount": {"amount": 1234567, "currency": "NGN"}, "reconciliation_reference": "paye-2026-09-rivers", "administrator_name": "Rivers State Internal Revenue Service", "employee_amount": {"amount": 1234567, "currency": "NGN"}, "employer_amount": {"amount": 1234567, "currency": "NGN"}}], "levies": [{"code": "nhf", "amount": {"amount": 1234567, "currency": "NGN"}, "reconciliation_reference": "paye-2026-09-rivers"}], "totals": {"total": {"amount": 1234567, "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": True, "mocked": True, "run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "paye": [{"authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "jurisdiction": "Rivers State Internal Revenue Service", "amount": {"amount": 1234567, "currency": "NGN"}, "reconciliation_reference": "paye-2026-09-rivers", "payee_count": 1}], "pension": [{"administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "amount": {"amount": 1234567, "currency": "NGN"}, "reconciliation_reference": "paye-2026-09-rivers", "administrator_name": "Rivers State Internal Revenue Service", "employee_amount": {"amount": 1234567, "currency": "NGN"}, "employer_amount": {"amount": 1234567, "currency": "NGN"}}], "levies": [{"code": "nhf", "amount": {"amount": 1234567, "currency": "NGN"}, "reconciliation_reference": "paye-2026-09-rivers"}], "totals": {"total": {"amount": 1234567, "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":true,"mocked":true,"run_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","paye":[{"authority_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","jurisdiction":"Rivers State Internal Revenue Service","amount":{"amount":1234567,"currency":"NGN"},"reconciliation_reference":"paye-2026-09-rivers","payee_count":1}],"pension":[{"administrator_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","amount":{"amount":1234567,"currency":"NGN"},"reconciliation_reference":"paye-2026-09-rivers","administrator_name":"Rivers State Internal Revenue Service","employee_amount":{"amount":1234567,"currency":"NGN"},"employer_amount":{"amount":1234567,"currency":"NGN"}}],"levies":[{"code":"nhf","amount":{"amount":1234567,"currency":"NGN"},"reconciliation_reference":"paye-2026-09-rivers"}],"totals":{"total":{"amount":1234567,"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":true,"mocked":true,"run_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","paye":[{"authority_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","jurisdiction":"Rivers State Internal Revenue Service","amount":{"amount":1234567,"currency":"NGN"},"reconciliation_reference":"paye-2026-09-rivers","payee_count":1}],"pension":[{"administrator_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","amount":{"amount":1234567,"currency":"NGN"},"reconciliation_reference":"paye-2026-09-rivers","administrator_name":"Rivers State Internal Revenue Service","employee_amount":{"amount":1234567,"currency":"NGN"},"employer_amount":{"amount":1234567,"currency":"NGN"}}],"levies":[{"code":"nhf","amount":{"amount":1234567,"currency":"NGN"},"reconciliation_reference":"paye-2026-09-rivers"}],"totals":{"total":{"amount":1234567,"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": true,
            "mocked": true,
            "run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
            "paye": [
              {
                "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
                "jurisdiction": "Rivers State Internal Revenue Service",
                "amount": {
                  "amount": 1234567,
                  "currency": "NGN"
                },
                "reconciliation_reference": "paye-2026-09-rivers",
                "payee_count": 1
              }
            ],
            "pension": [
              {
                "administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
                "amount": {
                  "amount": 1234567,
                  "currency": "NGN"
                },
                "reconciliation_reference": "paye-2026-09-rivers",
                "administrator_name": "Rivers State Internal Revenue Service",
                "employee_amount": {
                  "amount": 1234567,
                  "currency": "NGN"
                },
                "employer_amount": {
                  "amount": 1234567,
                  "currency": "NGN"
                }
              }
            ],
            "levies": [
              {
                "code": "nhf",
                "amount": {
                  "amount": 1234567,
                  "currency": "NGN"
                },
                "reconciliation_reference": "paye-2026-09-rivers"
              }
            ],
            "totals": {
              "total": {
                "amount": 1234567,
                "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": true,
        "mocked": true,
        "run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
        "paye": [
          {
            "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
            "jurisdiction": "Rivers State Internal Revenue Service",
            "amount": {
              "amount": 1234567,
              "currency": "NGN"
            },
            "reconciliation_reference": "paye-2026-09-rivers",
            "payee_count": 1
          }
        ],
        "pension": [
          {
            "administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
            "amount": {
              "amount": 1234567,
              "currency": "NGN"
            },
            "reconciliation_reference": "paye-2026-09-rivers",
            "administrator_name": "Rivers State Internal Revenue Service",
            "employee_amount": {
              "amount": 1234567,
              "currency": "NGN"
            },
            "employer_amount": {
              "amount": 1234567,
              "currency": "NGN"
            }
          }
        ],
        "levies": [
          {
            "code": "nhf",
            "amount": {
              "amount": 1234567,
              "currency": "NGN"
            },
            "reconciliation_reference": "paye-2026-09-rivers"
          }
        ],
        "totals": {
          "total": {
            "amount": 1234567,
            "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": true,
    "mocked": true,
    "run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "paye": [
      {
        "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
        "jurisdiction": "Rivers State Internal Revenue Service",
        "amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "reconciliation_reference": "paye-2026-09-rivers",
        "payee_count": 1
      }
    ],
    "pension": [
      {
        "administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
        "amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "reconciliation_reference": "paye-2026-09-rivers",
        "administrator_name": "Rivers State Internal Revenue Service",
        "employee_amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "employer_amount": {
          "amount": 1234567,
          "currency": "NGN"
        }
      }
    ],
    "levies": [
      {
        "code": "nhf",
        "amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "reconciliation_reference": "paye-2026-09-rivers"
      }
    ],
    "totals": {
      "total": {
        "amount": 1234567,
        "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)
Response
{
  "id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "ingested_instruction_set",
  "livemode": true,
  "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": "no_payee_destination",
        "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": true,
    "mocked": true,
    "run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "paye": [
      {
        "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
        "jurisdiction": "Rivers State Internal Revenue Service",
        "amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "reconciliation_reference": "paye-2026-09-rivers",
        "payee_count": 1
      }
    ],
    "pension": [
      {
        "administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
        "amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "reconciliation_reference": "paye-2026-09-rivers",
        "administrator_name": "Rivers State Internal Revenue Service",
        "employee_amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "employer_amount": {
          "amount": 1234567,
          "currency": "NGN"
        }
      }
    ],
    "levies": [
      {
        "code": "nhf",
        "amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "reconciliation_reference": "paye-2026-09-rivers"
      }
    ],
    "totals": {
      "total": {
        "amount": 1234567,
        "currency": "NGN"
      }
    },
    "period": "2026-09",
    "created_at": "2026-09-01T09:00:00Z"
  },
  "jurisdiction_pack": {
    "pack_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "version": "2026.08.1"
  },
  "accepted_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "created_at": "2026-09-01T09:00:00Z"
}
GET/v1/remittance/instruction_sets/{instruction_set_id}#

Retrieve an instruction set

remittance.instruction_sets.retrieve

You get the set with its validation report and any open discrepancies.

Path parameters

instruction_set_id string required

The 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 instruction set.

id string required

The 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" required

Always ingested_instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

Nothing is committed until accepted.

receivedvalidatingpending_acceptanceacceptedrejected
source string required

Where the set came from. Droomwork payroll or your own, by API or by file. Everything downstream behaves identically whichever it was.

runexternal_apiexternal_file
period string required

The month the set covers, as YYYY-MM, such as 2026-09. Filter the list by it with the period query.

run_id string · nullable optional

The 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 optional

What 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 required

The 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" required

Always instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

The 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 optional

The pay period the amounts are owed for, as year and month, for example 2026-09.

paye array of object required

Grouped by the State IRS of the employee's residence, not the employer's location.

5 fields
authority_id string required

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

payee_count integer optional

How many employees this line's PAYE covers. Optional; when it is present, check it against your own headcount for that state.

reconciliation_reference string required

The 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 required

Grouped by administrator and retirement savings account number.

6 fields
administrator_id string required

The 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 optional

The 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 optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

employer_amount Money optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

reconciliation_reference string required

The 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 required

NHF, NSITF, ITF and NHIA totals, each with a reconciliation reference.

3 fields
code string required

Which 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.

nhfnsitfitfnhia
amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

reconciliation_reference string required

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

validation_report ValidationReport required

The 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 required

How 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 required

How 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 required

How 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 optional

One 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 required

The row in a file, or the line in an instruction set.

severity string required

error means the entry failed and must be fixed. warning means it passed, but points at something you should confirm before you go ahead.

errorwarning
code string required

Why 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 required

What was wrong with the entry, in plain words. Show it beside the row; it may change, so branch on code.

jurisdiction_pack object optional

The 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 optional

Which 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 optional

The 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 optional

Who accepted the set: the actor that called accept. null until the set is accepted.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "ingested_instruction_set",
  "livemode": true,
  "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": "no_payee_destination",
        "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": true,
    "mocked": true,
    "run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "paye": [
      {
        "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
        "jurisdiction": "Rivers State Internal Revenue Service",
        "amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "reconciliation_reference": "paye-2026-09-rivers",
        "payee_count": 1
      }
    ],
    "pension": [
      {
        "administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
        "amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "reconciliation_reference": "paye-2026-09-rivers",
        "administrator_name": "Rivers State Internal Revenue Service",
        "employee_amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "employer_amount": {
          "amount": 1234567,
          "currency": "NGN"
        }
      }
    ],
    "levies": [
      {
        "code": "nhf",
        "amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "reconciliation_reference": "paye-2026-09-rivers"
      }
    ],
    "totals": {
      "total": {
        "amount": 1234567,
        "currency": "NGN"
      }
    },
    "period": "2026-09",
    "created_at": "2026-09-01T09:00:00Z"
  },
  "jurisdiction_pack": {
    "pack_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "version": "2026.08.1"
  },
  "accepted_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "created_at": "2026-09-01T09:00:00Z"
}
POST/v1/remittance/instruction_sets/{instruction_set_id}/accept#

Accept an instruction set for remittance

remittance.instruction_sets.accept

Refused while any discrepancy is open. Resolve each one first, or override it with a reason code.

Path parameters

instruction_set_id string required

The 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 required

A 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 accepted set.

id string required

The 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" required

Always ingested_instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

Nothing is committed until accepted.

receivedvalidatingpending_acceptanceacceptedrejected
source string required

Where the set came from. Droomwork payroll or your own, by API or by file. Everything downstream behaves identically whichever it was.

runexternal_apiexternal_file
period string required

The month the set covers, as YYYY-MM, such as 2026-09. Filter the list by it with the period query.

run_id string · nullable optional

The 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 optional

What 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 required

The 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" required

Always instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

The 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 optional

The pay period the amounts are owed for, as year and month, for example 2026-09.

paye array of object required

Grouped by the State IRS of the employee's residence, not the employer's location.

5 fields
authority_id string required

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

payee_count integer optional

How many employees this line's PAYE covers. Optional; when it is present, check it against your own headcount for that state.

reconciliation_reference string required

The 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 required

Grouped by administrator and retirement savings account number.

6 fields
administrator_id string required

The 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 optional

The 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 optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

employer_amount Money optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

reconciliation_reference string required

The 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 required

NHF, NSITF, ITF and NHIA totals, each with a reconciliation reference.

3 fields
code string required

Which 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.

nhfnsitfitfnhia
amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

reconciliation_reference string required

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

validation_report ValidationReport required

The 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 required

How 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 required

How 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 required

How 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 optional

One 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 required

The row in a file, or the line in an instruction set.

severity string required

error means the entry failed and must be fixed. warning means it passed, but points at something you should confirm before you go ahead.

errorwarning
code string required

Why 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 required

What was wrong with the entry, in plain words. Show it beside the row; it may change, so branch on code.

jurisdiction_pack object optional

The 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 optional

Which 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 optional

The 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 optional

Who accepted the set: the actor that called accept. null until the set is accepted.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.
409The record is not in a state that allows this.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "ingested_instruction_set",
  "livemode": true,
  "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": "no_payee_destination",
        "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": true,
    "mocked": true,
    "run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "paye": [
      {
        "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
        "jurisdiction": "Rivers State Internal Revenue Service",
        "amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "reconciliation_reference": "paye-2026-09-rivers",
        "payee_count": 1
      }
    ],
    "pension": [
      {
        "administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
        "amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "reconciliation_reference": "paye-2026-09-rivers",
        "administrator_name": "Rivers State Internal Revenue Service",
        "employee_amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "employer_amount": {
          "amount": 1234567,
          "currency": "NGN"
        }
      }
    ],
    "levies": [
      {
        "code": "nhf",
        "amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "reconciliation_reference": "paye-2026-09-rivers"
      }
    ],
    "totals": {
      "total": {
        "amount": 1234567,
        "currency": "NGN"
      }
    },
    "period": "2026-09",
    "created_at": "2026-09-01T09:00:00Z"
  },
  "jurisdiction_pack": {
    "pack_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "version": "2026.08.1"
  },
  "accepted_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "created_at": "2026-09-01T09:00:00Z"
}
GET/v1/remittance/instruction_sets/{instruction_set_id}/totals#

Retrieve instruction set totals

remittance.instruction_sets.retrieve_totals

You get the totals by authority and whether they reconcile to the originating run. They reconcile to the kobo.

Path parameters

instruction_set_id string required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

by_authority array of object optional

One 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

reconciles_to_run boolean required

True 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 optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "total": {
    "amount": 1234567,
    "currency": "NGN"
  },
  "reconciles_to_run": true,
  "by_authority": [
    {
      "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "amount": {
        "amount": 1234567,
        "currency": "NGN"
      }
    }
  ],
  "difference": {
    "amount": 1234567,
    "currency": "NGN"
  }
}
GET/v1/remittance/instruction_sets/{instruction_set_id}/discrepancies#

List discrepancies on an instruction set

remittance.discrepancies.list

Lists what's blocking acceptance. A discrepancy is raised where a recomputed line disagrees with what you submitted, and where a residency conflict means PAYE would go to the wrong State Internal Revenue Service.

Path parameters

instruction_set_id string required

The 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 optional

How 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" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of Discrepancy required

The records on this page, in the order the list promises. Empty when nothing matched.

11 fields of Discrepancy
id string required

The 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" required

Always discrepancy. Tells you which kind of record you are looking at, so one handler can read any response.

kind string required
recomputation_mismatchresidency_conflictmissing_identifierunknown_authority
status string required

open 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.

openresolvedoverridden
line integer optional

Which 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 optional

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

recomputed Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

difference Money optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

reason_code string · nullable optional

The reason code you gave when you overrode the discrepancy, kept on the record permanently. null until it is overridden.

overridden_by string · nullable optional

Who overrode the discrepancy: the actor that supplied the reason code, recorded permanently. null until it is overridden.

has_more boolean required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# 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)
Response
{
  "object": "list",
  "data": [
    {
      "id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "discrepancy",
      "kind": "recomputation_mismatch",
      "status": "open",
      "submitted": {
        "amount": 1234567,
        "currency": "NGN"
      },
      "recomputed": {
        "amount": 1234567,
        "currency": "NGN"
      },
      "line": 1,
      "subject_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "difference": {
        "amount": 1234567,
        "currency": "NGN"
      },
      "reason_code": "no_payee_destination",
      "overridden_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
    }
  ],
  "has_more": true
}
GET/v1/remittance/instruction_sets/{instruction_set_id}/discrepancies/{discrepancy_id}#

Retrieve a discrepancy

remittance.discrepancies.retrieve

You get the figure you submitted, the figure we recomputed and the difference.

Path parameters

instruction_set_id string required

The 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 required

The 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 required

The 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" required

Always discrepancy. Tells you which kind of record you are looking at, so one handler can read any response.

kind string required
recomputation_mismatchresidency_conflictmissing_identifierunknown_authority
status string required

open 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.

openresolvedoverridden
line integer optional

Which 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 optional

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

recomputed Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

difference Money optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

reason_code string · nullable optional

The reason code you gave when you overrode the discrepancy, kept on the record permanently. null until it is overridden.

overridden_by string · nullable optional

Who overrode the discrepancy: the actor that supplied the reason code, recorded permanently. null until it is overridden.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "discrepancy",
  "kind": "recomputation_mismatch",
  "status": "open",
  "submitted": {
    "amount": 1234567,
    "currency": "NGN"
  },
  "recomputed": {
    "amount": 1234567,
    "currency": "NGN"
  },
  "line": 1,
  "subject_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "difference": {
    "amount": 1234567,
    "currency": "NGN"
  },
  "reason_code": "no_payee_destination",
  "overridden_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}
POST/v1/remittance/instruction_sets/{instruction_set_id}/discrepancies/{discrepancy_id}/override#

Override a discrepancy with a reason

remittance.discrepancies.override

Keep your submitted figure over the recomputed one. Send a reason code. It is recorded permanently with who supplied it, so a year from now you can show who decided and why.

Path parameters

instruction_set_id string required

The 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 required

The 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 required

A 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 required

Recorded permanently with the actor who supplied it.

note string optional

Anything a reviewer should know beyond the code, in your words. Optional; it goes on the record with the reason code.

Returns

The overridden discrepancy.

id string required

The 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" required

Always discrepancy. Tells you which kind of record you are looking at, so one handler can read any response.

kind string required
recomputation_mismatchresidency_conflictmissing_identifierunknown_authority
status string required

open 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.

openresolvedoverridden
line integer optional

Which 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 optional

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

recomputed Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

difference Money optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

reason_code string · nullable optional

The reason code you gave when you overrode the discrepancy, kept on the record permanently. null until it is overridden.

overridden_by string · nullable optional

Who overrode the discrepancy: the actor that supplied the reason code, recorded permanently. null until it is overridden.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.
409The record is not in a state that allows this.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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":"no_payee_destination","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":"no_payee_destination","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": "no_payee_destination",
    "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": "no_payee_destination", "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": "no_payee_destination", "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":"no_payee_destination","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":"no_payee_destination","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": "no_payee_destination",
          "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": "no_payee_destination",
      "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": "no_payee_destination",
  "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)
Response
{
  "id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "discrepancy",
  "kind": "recomputation_mismatch",
  "status": "open",
  "submitted": {
    "amount": 1234567,
    "currency": "NGN"
  },
  "recomputed": {
    "amount": 1234567,
    "currency": "NGN"
  },
  "line": 1,
  "subject_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "difference": {
    "amount": 1234567,
    "currency": "NGN"
  },
  "reason_code": "no_payee_destination",
  "overridden_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}
GET/v1/remittance/imports#

List file imports

remittance.imports.list

Lists your previous file submissions with their validation reports.

Query parameters

limit integer optional

How 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 optional

The 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.

object always "list" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of Import required

The records on this page, in the order the list promises. Empty when nothing matched.

8 fields of Import
id string required

The 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" required

Always remittance_import. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

validating 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_acceptanceacceptedrejected
instruction_set_id string · nullable optional

The 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 required

The 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 required

How 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 required

How 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 required

How 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 optional

One 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 required

The row in a file, or the line in an instruction set.

severity string required

error means the entry failed and must be fixed. warning means it passed, but points at something you should confirm before you go ahead.

errorwarning
code string required

Why 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 required

What 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 optional

When the record was created, as an RFC 3339 timestamp in UTC.

has_more boolean required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# 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)
Response
{
  "object": "list",
  "data": [
    {
      "id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "remittance_import",
      "livemode": true,
      "mocked": true,
      "status": "validating",
      "validation_report": {
        "entry_count": 0,
        "error_count": 0,
        "warning_count": 0,
        "entries": [
          {
            "index": 1,
            "severity": "error",
            "code": "no_payee_destination",
            "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
}
POST/v1/remittance/imports#

Submit an instruction set as a file

remittance.imports.create

For a payroll system that can't call an API. Send a CSV or XLSX file and you get the same validation report the API route returns. Everything from here on behaves the same whichever way you submitted.

Headers

Idempotency-Key string required

A 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, with its validation report.

id string required

The 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" required

Always remittance_import. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

validating 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_acceptanceacceptedrejected
instruction_set_id string · nullable optional

The 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 required

The 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 required

How 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 required

How 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 required

How 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 optional

One 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 required

The row in a file, or the line in an instruction set.

severity string required

error means the entry failed and must be fixed. warning means it passed, but points at something you should confirm before you go ahead.

errorwarning
code string required

Why 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 required

What 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 optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "remittance_import",
  "livemode": true,
  "mocked": true,
  "status": "validating",
  "validation_report": {
    "entry_count": 0,
    "error_count": 0,
    "warning_count": 0,
    "entries": [
      {
        "index": 1,
        "severity": "error",
        "code": "no_payee_destination",
        "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"
}
GET/v1/remittance/imports/{import_id}#

Retrieve an import

remittance.imports.retrieve

You get the import with a report naming every row that failed and why.

Path parameters

import_id string required

The 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.

id string required

The 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" required

Always remittance_import. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

validating 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_acceptanceacceptedrejected
instruction_set_id string · nullable optional

The 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 required

The 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 required

How 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 required

How 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 required

How 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 optional

One 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 required

The row in a file, or the line in an instruction set.

severity string required

error means the entry failed and must be fixed. warning means it passed, but points at something you should confirm before you go ahead.

errorwarning
code string required

Why 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 required

What 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 optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "remittance_import",
  "livemode": true,
  "mocked": true,
  "status": "validating",
  "validation_report": {
    "entry_count": 0,
    "error_count": 0,
    "warning_count": 0,
    "entries": [
      {
        "index": 1,
        "severity": "error",
        "code": "no_payee_destination",
        "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"
}
GET/v1/remittance/obligations#

List statutory obligations

remittance.obligations.list

What you owe, to which authority, for which period, and what's left to pay after everything settled so far.

Query parameters

limit integer optional

How 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 optional

The 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 optional

Return 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 optional

Return only obligations for this month, as YYYY-MM, such as 2026-09. Leave it out to get every period.

settled boolean optional

true 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" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of Obligation required

The records on this page, in the order the list promises. Empty when nothing matched.

12 fields of Obligation
id string required

The 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" required

Always obligation. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

The 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 optional

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

settled Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

balance Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

deadline string · date required

Derived from the pack calendar rules, never entered by hand.

receipt_ids array of string optional

The 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 required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# 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)
Response
{
  "object": "list",
  "data": [
    {
      "id": "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "obligation",
      "livemode": true,
      "mocked": true,
      "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "period": "2026-09",
      "amount": {
        "amount": 1234567,
        "currency": "NGN"
      },
      "settled": {
        "amount": 1234567,
        "currency": "NGN"
      },
      "balance": {
        "amount": 1234567,
        "currency": "NGN"
      },
      "deadline": "2026-09-01",
      "authority_name": "Rivers State Internal Revenue Service",
      "receipt_ids": [
        "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
      ]
    }
  ],
  "has_more": true
}
POST/v1/remittance/obligations#

Record an obligation

remittance.obligations.create

Record what you owe, to whom, for which period. Obligations normally arise from an accepted instruction set. Use this to record one directly, for a liability that predates your use of Droomwork.

Headers

Idempotency-Key string required

A 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 optional

The authority the amount is owed to.

period string optional

The period the obligation arises from, as YYYY-MM.

Returns

The recorded obligation.

id string required

The 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" required

Always obligation. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

The 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 optional

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

settled Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

balance Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

deadline string · date required

Derived from the pack calendar rules, never entered by hand.

receipt_ids array of string optional

The 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

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.
409The record is not in a state that allows this.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "obligation",
  "livemode": true,
  "mocked": true,
  "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "period": "2026-09",
  "amount": {
    "amount": 1234567,
    "currency": "NGN"
  },
  "settled": {
    "amount": 1234567,
    "currency": "NGN"
  },
  "balance": {
    "amount": 1234567,
    "currency": "NGN"
  },
  "deadline": "2026-09-01",
  "authority_name": "Rivers State Internal Revenue Service",
  "receipt_ids": [
    "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
  ]
}
GET/v1/remittance/obligations/{obligation_id}#

Retrieve an obligation

remittance.obligations.retrieve

You get the liability, what has settled against it, and the balance.

Path parameters

obligation_id string required

The 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 required

The 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" required

Always obligation. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

The 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 optional

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

settled Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

balance Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

deadline string · date required

Derived from the pack calendar rules, never entered by hand.

receipt_ids array of string optional

The 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

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "obligation",
  "livemode": true,
  "mocked": true,
  "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "period": "2026-09",
  "amount": {
    "amount": 1234567,
    "currency": "NGN"
  },
  "settled": {
    "amount": 1234567,
    "currency": "NGN"
  },
  "balance": {
    "amount": 1234567,
    "currency": "NGN"
  },
  "deadline": "2026-09-01",
  "authority_name": "Rivers State Internal Revenue Service",
  "receipt_ids": [
    "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
  ]
}
GET/v1/remittance/calendar_entries#

List filing deadlines

remittance.calendar_entries.list

Amounts, deadlines and the penalty formula for each, taken from the jurisdiction pack and never entered by hand. Due soon alerts reach you as webhooks at the lead time you configure.

Query parameters

limit integer optional

How 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 optional

Return 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 optional

Return 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.

object always "list" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of CalendarEntry required

The records on this page, in the order the list promises. Empty when nothing matched.

10 fields of CalendarEntry
id string required

The 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" required

Always calendar_entry. Tells you which kind of record you are looking at, so one handler can read any response.

authority_id string required

The 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 optional

The 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 required

The month the filing covers, as YYYY-MM, such as 2026-09. The deadline and amount are for this period alone.

deadline string · date required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

penalty_formula string optional

Published from the pack as a formula rather than a computed figure, because the amount depends on when you actually file.

lead_time_days integer optional

How far ahead the due soon alert fires.

pack_version string optional

The 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 required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# 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=Fri%20Jan%2001%202027%2001%3A00%3A00%20GMT%2B0100%20(West%20Africa%20Time)&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: 'Fri Jan 01 2027 01:00:00 GMT+0100 (West Africa Time)', 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=Fri%20Jan%2001%202027%2001%3A00%3A00%20GMT%2B0100%20(West%20Africa%20Time)&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='Fri Jan 01 2027 01:00:00 GMT+0100 (West Africa Time)', 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=Fri%20Jan%2001%202027%2001%3A00%3A00%20GMT%2B0100%20(West%20Africa%20Time)&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: 'Fri Jan 01 2027 01:00:00 GMT+0100 (West Africa Time)', 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=Fri%20Jan%2001%202027%2001%3A00%3A00%20GMT%2B0100%20(West%20Africa%20Time)&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, "Fri Jan 01 2027 01:00:00 GMT+0100 (West Africa Time)", "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=Fri%20Jan%2001%202027%2001%3A00%3A00%20GMT%2B0100%20(West%20Africa%20Time)&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: "Fri Jan 01 2027 01:00:00 GMT+0100 (West Africa Time)", 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=Fri%20Jan%2001%202027%2001%3A00%3A00%20GMT%2B0100%20(West%20Africa%20Time)&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("Fri Jan 01 2027 01:00:00 GMT+0100 (West Africa Time)").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=Fri%20Jan%2001%202027%2001%3A00%3A00%20GMT%2B0100%20(West%20Africa%20Time)&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)
Response
{
  "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": 1234567,
        "currency": "NGN"
      },
      "authority_name": "Rivers 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
}
GET/v1/remittance/calendar_entries/{calendar_entry_id}#

Retrieve a filing deadline

remittance.calendar_entries.retrieve

You get the deadline with its penalty formula and the pack version it came from.

Path parameters

calendar_entry_id string required

The 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 calendar entry.

id string required

The 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" required

Always calendar_entry. Tells you which kind of record you are looking at, so one handler can read any response.

authority_id string required

The 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 optional

The 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 required

The month the filing covers, as YYYY-MM, such as 2026-09. The deadline and amount are for this period alone.

deadline string · date required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

penalty_formula string optional

Published from the pack as a formula rather than a computed figure, because the amount depends on when you actually file.

lead_time_days integer optional

How far ahead the due soon alert fires.

pack_version string optional

The 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

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_obligation_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "calendar_entry",
  "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "period": "2026-09",
  "deadline": "2026-09-01",
  "amount": {
    "amount": 1234567,
    "currency": "NGN"
  },
  "authority_name": "Rivers 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"
}
GET/v1/remittance/authorities#

List statutory authorities and what each supports

remittance.authorities.list

All 37 tax jurisdictions, plus the pension commission and administrators, NHF, NSITF, ITF and NHIA. Each shows you a capability flag and a tier.

Read the tier to know what to expect on timing. Never code against it: all three tiers present the same request, the same states, the same webhooks and the same evidence class.

Query parameters

limit integer optional

How 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 optional

Return 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_administratornhfnsitfitfnhia
tier string optional

Return 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_manual

Returns

A page of authorities.

object always "list" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of Authority required

The records on this page, in the order the list promises. Empty when nothing matched.

9 fields of Authority
id string required

The 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" required

Always authority. Tells you which kind of record you are looking at, so one handler can read any response.

kind string required
state_irsfederal_irspension_commissionpension_administratornhfnsitfitfnhia
tier string required

How 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_manual
name string required

The 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 optional

Which 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 required

What this authority supports. Absent a capability, the endpoint refuses rather than pretends.

4 fields
file_return boolean optional

true 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 optional

true 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 optional

true 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 optional

true 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 optional

Whether you have supplied credentials for this authority.

expected_completion string optional

Typical time to a vaulted receipt at this tier.

has_more boolean required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# 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)
Response
{
  "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": "Rivers State Internal Revenue Service",
      "credentials_held": true,
      "expected_completion": "under 5 minutes"
    }
  ],
  "has_more": true
}
GET/v1/remittance/authorities/{authority_id}#

Retrieve an authority

remittance.authorities.retrieve

You get the authority with its tier and capabilities. When an authority moves from an assisted tier to a direct one, nothing changes on your side.

Path parameters

authority_id string required

The 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

The authority.

id string required

The 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" required

Always authority. Tells you which kind of record you are looking at, so one handler can read any response.

kind string required
state_irsfederal_irspension_commissionpension_administratornhfnsitfitfnhia
tier string required

How 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_manual
name string required

The 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 optional

Which 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 required

What this authority supports. Absent a capability, the endpoint refuses rather than pretends.

4 fields
file_return boolean optional

true 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 optional

true 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 optional

true 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 optional

true 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 optional

Whether you have supplied credentials for this authority.

expected_completion string optional

Typical time to a vaulted receipt at this tier.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "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": "Rivers State Internal Revenue Service",
  "credentials_held": true,
  "expected_completion": "under 5 minutes"
}
GET/v1/remittance/remittances#

List remittances

remittance.remittances.list

Lists your remittances, newest first.

Query parameters

limit integer optional

How 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 optional

The 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 optional

Return 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_completedfailed

Returns

A page of remittances.

object always "list" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of Remittance required

The records on this page, in the order the list promises. Empty when nothing matched.

11 fields of Remittance
id string required

The 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" required

Always remittance. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required
draftapprovedexecutingcompletedpartially_completedfailed
instruction_set_id string required

The 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 optional

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

legs array of Leg required

One 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 required

The 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" required

Always remittance_leg. Tells you which kind of record you are looking at, so one handler can read any response.

remittance_id string optional

The 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 required

The 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 optional

The 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 optional

How 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_manual
status string required

A leg reaches completed only once its receipt is vaulted. quarantined means a receipt arrived but disagreed with the leg.

pendingexecutingawaiting_receiptcompletedquarantinedfailed
amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

receipt_id string · nullable optional

The 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 optional

How 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 optional

Why 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 optional

Who 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 optional

When the record was created, as an RFC 3339 timestamp in UTC.

has_more boolean required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# 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)
Response
{
  "object": "list",
  "data": [
    {
      "id": "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "remittance",
      "livemode": true,
      "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": 1234567,
            "currency": "NGN"
          },
          "remittance_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
          "authority_name": "Rivers 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": 1234567,
        "currency": "NGN"
      },
      "period": "2026-09",
      "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "created_at": "2026-09-01T09:00:00Z"
    }
  ],
  "has_more": true
}
POST/v1/remittance/remittances#

Create a remittance from an accepted instruction set

remittance.remittances.create

You get one leg per authority. Each leg executes on its own, so a single authority being unreachable never blocks the rest.

Headers

Idempotency-Key string required

A 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 required

The 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 optional

Defaults to every authority named in the instruction set.

Returns

The remittance, in draft, with a leg per authority.

id string required

The 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" required

Always remittance. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required
draftapprovedexecutingcompletedpartially_completedfailed
instruction_set_id string required

The 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 optional

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

legs array of Leg required

One 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 required

The 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" required

Always remittance_leg. Tells you which kind of record you are looking at, so one handler can read any response.

remittance_id string optional

The 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 required

The 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 optional

The 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 optional

How 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_manual
status string required

A leg reaches completed only once its receipt is vaulted. quarantined means a receipt arrived but disagreed with the leg.

pendingexecutingawaiting_receiptcompletedquarantinedfailed
amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

receipt_id string · nullable optional

The 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 optional

How 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 optional

Why 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 optional

Who 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 optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.
409The record is not in a state that allows this.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "remittance",
  "livemode": true,
  "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": 1234567,
        "currency": "NGN"
      },
      "remittance_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "authority_name": "Rivers 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": 1234567,
    "currency": "NGN"
  },
  "period": "2026-09",
  "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "created_at": "2026-09-01T09:00:00Z"
}
GET/v1/remittance/remittances/{remittance_id}#

Retrieve a remittance

remittance.remittances.retrieve

You get the remittance with the state of every leg.

Path parameters

remittance_id string required

The 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

The remittance.

id string required

The 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" required

Always remittance. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required
draftapprovedexecutingcompletedpartially_completedfailed
instruction_set_id string required

The 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 optional

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

legs array of Leg required

One 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 required

The 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" required

Always remittance_leg. Tells you which kind of record you are looking at, so one handler can read any response.

remittance_id string optional

The 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 required

The 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 optional

The 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 optional

How 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_manual
status string required

A leg reaches completed only once its receipt is vaulted. quarantined means a receipt arrived but disagreed with the leg.

pendingexecutingawaiting_receiptcompletedquarantinedfailed
amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

receipt_id string · nullable optional

The 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 optional

How 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 optional

Why 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 optional

Who 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 optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "remittance",
  "livemode": true,
  "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": 1234567,
        "currency": "NGN"
      },
      "remittance_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "authority_name": "Rivers 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": 1234567,
    "currency": "NGN"
  },
  "period": "2026-09",
  "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "created_at": "2026-09-01T09:00:00Z"
}
POST/v1/remittance/remittances/{remittance_id}/approve#

Approve a remittance and release every leg

remittance.remittances.approve

One approval releases every leg. Each then executes on its own against its own authority.

Path parameters

remittance_id string required

The 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 required

A 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

Approved. Legs begin executing.

id string required

The 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" required

Always remittance. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required
draftapprovedexecutingcompletedpartially_completedfailed
instruction_set_id string required

The 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 optional

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

legs array of Leg required

One 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 required

The 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" required

Always remittance_leg. Tells you which kind of record you are looking at, so one handler can read any response.

remittance_id string optional

The 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 required

The 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 optional

The 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 optional

How 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_manual
status string required

A leg reaches completed only once its receipt is vaulted. quarantined means a receipt arrived but disagreed with the leg.

pendingexecutingawaiting_receiptcompletedquarantinedfailed
amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

receipt_id string · nullable optional

The 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 optional

How 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 optional

Why 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 optional

Who 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 optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.
409The record is not in a state that allows this.
422A required fact is missing. Call the readiness endpoint to see what.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "remittance",
  "livemode": true,
  "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": 1234567,
        "currency": "NGN"
      },
      "remittance_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "authority_name": "Rivers 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": 1234567,
    "currency": "NGN"
  },
  "period": "2026-09",
  "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "created_at": "2026-09-01T09:00:00Z"
}
GET/v1/remittance/remittances/{remittance_id}/legs#

List the legs of a remittance

remittance.legs.list

You get one leg per authority, each with its own state and its own receipt.

Path parameters

remittance_id string required

The 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 optional

How 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 optional

Return 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_receiptcompletedquarantinedfailed

Returns

A page of legs.

object always "list" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of Leg required

The records on this page, in the order the list promises. Empty when nothing matched.

11 fields of Leg
id string required

The 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" required

Always remittance_leg. Tells you which kind of record you are looking at, so one handler can read any response.

remittance_id string optional

The 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 required

The 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 optional

The 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 optional

How 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_manual
status string required

A leg reaches completed only once its receipt is vaulted. quarantined means a receipt arrived but disagreed with the leg.

pendingexecutingawaiting_receiptcompletedquarantinedfailed
amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

receipt_id string · nullable optional

The 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 optional

How 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 optional

Why 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 required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# 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)
Response
{
  "object": "list",
  "data": [
    {
      "id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "remittance_leg",
      "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "status": "pending",
      "amount": {
        "amount": 1234567,
        "currency": "NGN"
      },
      "remittance_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "authority_name": "Rivers 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
}
GET/v1/remittance/remittances/{remittance_id}/legs/{leg_id}#

Retrieve a leg

remittance.legs.retrieve

You get the leg with its state. A leg reaches completed only once its receipt is vaulted; a filing reported as successful is not enough on its own.

Path parameters

remittance_id string required

The 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 required

The 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

The leg.

id string required

The 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" required

Always remittance_leg. Tells you which kind of record you are looking at, so one handler can read any response.

remittance_id string optional

The 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 required

The 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 optional

The 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 optional

How 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_manual
status string required

A leg reaches completed only once its receipt is vaulted. quarantined means a receipt arrived but disagreed with the leg.

pendingexecutingawaiting_receiptcompletedquarantinedfailed
amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

receipt_id string · nullable optional

The 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 optional

How 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 optional

Why 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

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "remittance_leg",
  "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "status": "pending",
  "amount": {
    "amount": 1234567,
    "currency": "NGN"
  },
  "remittance_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "authority_name": "Rivers State Internal Revenue Service",
  "tier": "direct_api",
  "receipt_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "attempts": 0,
  "last_fault": "The register did not answer within the timeout."
}
POST/v1/remittance/remittances/{remittance_id}/legs/{leg_id}/retry#

Retry a failed leg

remittance.legs.retry

Retries one authority without touching the others. A retry after a timeout cannot file twice.

Path parameters

remittance_id string required

The 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 required

The 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 required

A 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

Retry accepted.

id string required

The 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" required

Always remittance_leg. Tells you which kind of record you are looking at, so one handler can read any response.

remittance_id string optional

The 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 required

The 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 optional

The 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 optional

How 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_manual
status string required

A leg reaches completed only once its receipt is vaulted. quarantined means a receipt arrived but disagreed with the leg.

pendingexecutingawaiting_receiptcompletedquarantinedfailed
amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

receipt_id string · nullable optional

The 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 optional

How 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 optional

Why 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

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.
409The record is not in a state that allows this.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "remittance_leg",
  "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "status": "pending",
  "amount": {
    "amount": 1234567,
    "currency": "NGN"
  },
  "remittance_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "authority_name": "Rivers State Internal Revenue Service",
  "tier": "direct_api",
  "receipt_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "attempts": 0,
  "last_fault": "The register did not answer within the timeout."
}
GET/v1/remittance/receipts#

List vaulted receipts

remittance.receipts.list

Your receipts, in a vault that is append only and hash chained. Every receipt links to its obligation, its leg, the schedule lines it covers and the payroll trace references behind them.

Query parameters

limit integer optional

How 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 optional

The 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 optional

Return 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 optional

Return 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.

object always "list" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of Receipt required

The records on this page, in the order the list promises. Empty when nothing matched.

17 fields of Receipt
id string required

The 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" required

Always remittance_receipt. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 optional

The 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 optional

The 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 required

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

authority_reference string optional

The reference the authority itself issued.

evidence_class string required

The 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_attested
document_url string · uri · nullable optional

Where 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 required

This receipt position in the append only chain.

previous_hash string required

The 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 optional

The payroll trace references this receipt covers.

attested_by array of string optional

Two actors for an assisted manual filing, under dual control.

vaulted_at string · date-time optional

When 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 required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# 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)
Response
{
  "object": "list",
  "data": [
    {
      "id": "remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "remittance_receipt",
      "livemode": true,
      "mocked": true,
      "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "amount": {
        "amount": 1234567,
        "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
}
POST/v1/remittance/receipts#

Record a receipt from an assisted manual filing

remittance.receipts.create

For authorities with no machine interface. Send the receipt reference, a scan of the document and an operator attestation under dual control. It carries the same evidence class as an API filing.

Dual control means two actors. A single credential is not enough on this endpoint.

Headers

Idempotency-Key string required

A 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 required

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

document_url string · uri required

A scan of the receipt the authority issued.

attested_by array of string required

Two distinct actors. Dual control, so one credential is not enough.

Returns

The vaulted receipt.

id string required

The 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" required

Always remittance_receipt. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 optional

The 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 optional

The 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 required

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

authority_reference string optional

The reference the authority itself issued.

evidence_class string required

The 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_attested
document_url string · uri · nullable optional

Where 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 required

This receipt position in the append only chain.

previous_hash string required

The 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 optional

The payroll trace references this receipt covers.

attested_by array of string optional

Two actors for an assisted manual filing, under dual control.

vaulted_at string · date-time optional

When 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

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.
409The record is not in a state that allows this.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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":1234567,"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":1234567,"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": 1234567,
      "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": 1234567, "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": 1234567, "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":1234567,"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":1234567,"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": 1234567,
            "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": 1234567,
        "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": 1234567,
    "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)
Response
{
  "id": "remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "remittance_receipt",
  "livemode": true,
  "mocked": true,
  "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "amount": {
    "amount": 1234567,
    "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"
}
GET/v1/remittance/receipts/{receipt_id}#

Retrieve a receipt

remittance.receipts.retrieve

You get the receipt with its hash chain position. There is no update and no delete; a receipt is never changed once vaulted.

Path parameters

receipt_id string required

The 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.

id string required

The 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" required

Always remittance_receipt. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 optional

The 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 optional

The 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 required

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

authority_reference string optional

The reference the authority itself issued.

evidence_class string required

The 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_attested
document_url string · uri · nullable optional

Where 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 required

This receipt position in the append only chain.

previous_hash string required

The 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 optional

The payroll trace references this receipt covers.

attested_by array of string optional

Two actors for an assisted manual filing, under dual control.

vaulted_at string · date-time optional

When 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

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_receipt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "remittance_receipt",
  "livemode": true,
  "mocked": true,
  "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "amount": {
    "amount": 1234567,
    "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"
}
POST/v1/remittance/audit_exports#

Produce an audit pack

remittance.audit_exports.create

Name a period, an authority or an employee. The pack carries its own signature, so whoever receives it can verify it without trusting where it came from.

Headers

Idempotency-Key string required

A 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 optional

Scope 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 optional

Scope 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 optional

Scope 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 required

The 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" required

Always audit_export. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

generating 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.

generatingreadyfailed
scope object required

What 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 optional

The 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 optional

The 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 optional

The 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 optional

Where 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 optional

Verify the pack against this without trusting the system that made it.

verification_instructions_url string · uri · nullable optional

Where 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 optional

How 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

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "audit_export",
  "livemode": true,
  "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
}
GET/v1/remittance/audit_exports/{audit_export_id}#

Retrieve an audit pack

remittance.audit_exports.retrieve

You get the pack with the instructions for verifying its signature.

Path parameters

audit_export_id string required

The 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 required

The 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" required

Always audit_export. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

generating 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.

generatingreadyfailed
scope object required

What 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 optional

The 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 optional

The 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 optional

The 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 optional

Where 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 optional

Verify the pack against this without trusting the system that made it.

verification_instructions_url string · uri · nullable optional

Where 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 optional

How 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

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "audit_export",
  "livemode": true,
  "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
}
GET/v1/remittance/reconciliations#

List daily reconciliations

remittance.reconciliations.list

Your statutory funds move through ring fenced accounts. This is your daily proof that every kobo debited is a kobo credited and that nothing is commingled.

Query parameters

limit integer optional

How 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 optional

Return 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.

object always "list" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of Reconciliation required

The records on this page, in the order the list promises. Empty when nothing matched.

9 fields of Reconciliation
id string required

The 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" required

Always reconciliation. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

The 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 required

Every kobo debited is a kobo credited, with no commingling.

opening_balance Money optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

closing_balance Money optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

breaks array of object required

Empty when balanced is true.

3 fields
code string required

Which 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 required

What 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

has_more boolean required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# query parameters: limit (optional), on (optional)
curl -X GET "https://sandbox.droomwork.io/v1/remittance/reconciliations?limit=25&on=Tue%20Sep%2001%202026%2001%3A00%3A00%20GMT%2B0100%20(West%20Africa%20Time)" \
  -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: 'Tue Sep 01 2026 01:00:00 GMT+0100 (West Africa Time)' });
// query parameters: limit (optional), on (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/remittance/reconciliations?limit=25&on=Tue%20Sep%2001%202026%2001%3A00%3A00%20GMT%2B0100%20(West%20Africa%20Time)', {
  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='Tue Sep 01 2026 01:00:00 GMT+0100 (West Africa Time)')
import os

import requests

# query parameters: limit (optional), on (optional)
response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/remittance/reconciliations?limit=25&on=Tue%20Sep%2001%202026%2001%3A00%3A00%20GMT%2B0100%20(West%20Africa%20Time)',
    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: 'Tue Sep 01 2026 01:00:00 GMT+0100 (West Africa Time)');
<?php
// query parameters: limit (optional), on (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/remittance/reconciliations?limit=25&on=Tue%20Sep%2001%202026%2001%3A00%3A00%20GMT%2B0100%20(West%20Africa%20Time)');
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, "Tue Sep 01 2026 01:00:00 GMT+0100 (West Africa Time)");
// 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=Tue%20Sep%2001%202026%2001%3A00%3A00%20GMT%2B0100%20(West%20Africa%20Time)"))
    .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: "Tue Sep 01 2026 01:00:00 GMT+0100 (West Africa Time)");
// 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=Tue%20Sep%2001%202026%2001%3A00%3A00%20GMT%2B0100%20(West%20Africa%20Time)");
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("Tue Sep 01 2026 01:00:00 GMT+0100 (West Africa Time)").Execute()
// query parameters: limit (optional), on (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/remittance/reconciliations?limit=25&on=Tue%20Sep%2001%202026%2001%3A00%3A00%20GMT%2B0100%20(West%20Africa%20Time)", 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)
Response
{
  "object": "list",
  "data": [
    {
      "id": "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "reconciliation",
      "livemode": true,
      "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": 1234567,
            "currency": "NGN"
          }
        }
      ],
      "opening_balance": {
        "amount": 1234567,
        "currency": "NGN"
      },
      "closing_balance": {
        "amount": 1234567,
        "currency": "NGN"
      }
    }
  ],
  "has_more": true
}
GET/v1/remittance/reconciliations/{reconciliation_id}#

Retrieve a reconciliation

remittance.reconciliations.retrieve

You get the day with every break found, if any.

Path parameters

reconciliation_id string required

The 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.

id string required

The 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" required

Always reconciliation. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

The 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 required

Every kobo debited is a kobo credited, with no commingling.

opening_balance Money optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

closing_balance Money optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

breaks array of object required

Empty when balanced is true.

3 fields
code string required

Which 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 required

What 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "reconciliation",
  "livemode": true,
  "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": 1234567,
        "currency": "NGN"
      }
    }
  ],
  "opening_balance": {
    "amount": 1234567,
    "currency": "NGN"
  },
  "closing_balance": {
    "amount": 1234567,
    "currency": "NGN"
  }
}
GET/v1/remittance/returns#

List employer returns

remittance.returns.list

Lists the filings you owe each authority, not the payments.

Query parameters

limit integer optional

How 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 optional

The 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 optional

Restricts 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_approvalapprovedsubmittedacceptedrejected

Returns

A page of returns.

object always "list" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of EmployerReturn required

The records on this page, in the order the list promises. Empty when nothing matched.

13 fields of EmployerReturn
id string required

The 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" required

Always employer_return. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required
monthly_payeannual_payepension_schedulenhf_schedulensitf_returnitf_returnnhia_schedule
status string required
draftpending_approvalapprovedsubmittedacceptedrejected
authority_id string required

The 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 required

The 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 optional

The vaulted receipts this return was generated from.

totals object optional

What the return declares, summed from the vaulted receipts it was generated from: how many employees and the total amount.

2 fields
employee_count integer optional

How many employees the return declares for the period.

total Money optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

approved_by string · nullable optional

A named person. Required before submission.

submitted_at string · date-time · nullable optional

When the return was filed with the authority, as an RFC 3339 timestamp in UTC. null until you submit it.

authority_reference string · nullable optional

The reference the authority gave your filing, such as paye-2026-09-rivers. null until the authority has issued one.

has_more boolean required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# 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)
Response
{
  "object": "list",
  "data": [
    {
      "id": "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "employer_return",
      "livemode": true,
      "mocked": true,
      "kind": "monthly_paye",
      "status": "draft",
      "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "period": "2026-09",
      "generated_from": [
        "example"
      ],
      "totals": {
        "employee_count": 1,
        "total": {
          "amount": 1234567,
          "currency": "NGN"
        }
      },
      "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "submitted_at": "2026-09-01T09:00:00Z",
      "authority_reference": "paye-2026-09-rivers"
    }
  ],
  "has_more": true
}
POST/v1/remittance/returns#

Generate an employer return

remittance.returns.create

Name the period and the authority, not the numbers. The return is generated from vaulted receipts, so it and the receipts behind it cannot disagree.

Headers

Idempotency-Key string required

A 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 required
monthly_payeannual_payepension_schedulenhf_schedulensitf_returnitf_returnnhia_schedule
authority_id string required

The 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 required

The 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 generated return, awaiting approval.

id string required

The 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" required

Always employer_return. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required
monthly_payeannual_payepension_schedulenhf_schedulensitf_returnitf_returnnhia_schedule
status string required
draftpending_approvalapprovedsubmittedacceptedrejected
authority_id string required

The 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 required

The 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 optional

The vaulted receipts this return was generated from.

totals object optional

What the return declares, summed from the vaulted receipts it was generated from: how many employees and the total amount.

2 fields
employee_count integer optional

How many employees the return declares for the period.

total Money optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

approved_by string · nullable optional

A named person. Required before submission.

submitted_at string · date-time · nullable optional

When the return was filed with the authority, as an RFC 3339 timestamp in UTC. null until you submit it.

authority_reference string · nullable optional

The reference the authority gave your filing, such as paye-2026-09-rivers. null until the authority has issued one.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.
422A required fact is missing. Call the readiness endpoint to see what.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "employer_return",
  "livemode": true,
  "mocked": true,
  "kind": "monthly_paye",
  "status": "draft",
  "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "period": "2026-09",
  "generated_from": [
    "example"
  ],
  "totals": {
    "employee_count": 1,
    "total": {
      "amount": 1234567,
      "currency": "NGN"
    }
  },
  "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "submitted_at": "2026-09-01T09:00:00Z",
  "authority_reference": "paye-2026-09-rivers"
}
GET/v1/remittance/returns/{return_id}#

Retrieve an employer return

remittance.returns.retrieve

You get the filing with the vaulted facts it was generated from.

Path parameters

return_id string required

The 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 return.

id string required

The 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" required

Always employer_return. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required
monthly_payeannual_payepension_schedulenhf_schedulensitf_returnitf_returnnhia_schedule
status string required
draftpending_approvalapprovedsubmittedacceptedrejected
authority_id string required

The 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 required

The 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 optional

The vaulted receipts this return was generated from.

totals object optional

What the return declares, summed from the vaulted receipts it was generated from: how many employees and the total amount.

2 fields
employee_count integer optional

How many employees the return declares for the period.

total Money optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

approved_by string · nullable optional

A named person. Required before submission.

submitted_at string · date-time · nullable optional

When the return was filed with the authority, as an RFC 3339 timestamp in UTC. null until you submit it.

authority_reference string · nullable optional

The reference the authority gave your filing, such as paye-2026-09-rivers. null until the authority has issued one.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "employer_return",
  "livemode": true,
  "mocked": true,
  "kind": "monthly_paye",
  "status": "draft",
  "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "period": "2026-09",
  "generated_from": [
    "example"
  ],
  "totals": {
    "employee_count": 1,
    "total": {
      "amount": 1234567,
      "currency": "NGN"
    }
  },
  "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "submitted_at": "2026-09-01T09:00:00Z",
  "authority_reference": "paye-2026-09-rivers"
}
POST/v1/remittance/returns/{return_id}/approve#

Approve a return for submission

remittance.returns.approve

A named person approves before anything is filed. Approval records who; submission records when.

Path parameters

return_id string required

The 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 required

A 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 approved return.

id string required

The 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" required

Always employer_return. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required
monthly_payeannual_payepension_schedulenhf_schedulensitf_returnitf_returnnhia_schedule
status string required
draftpending_approvalapprovedsubmittedacceptedrejected
authority_id string required

The 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 required

The 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 optional

The vaulted receipts this return was generated from.

totals object optional

What the return declares, summed from the vaulted receipts it was generated from: how many employees and the total amount.

2 fields
employee_count integer optional

How many employees the return declares for the period.

total Money optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

approved_by string · nullable optional

A named person. Required before submission.

submitted_at string · date-time · nullable optional

When the return was filed with the authority, as an RFC 3339 timestamp in UTC. null until you submit it.

authority_reference string · nullable optional

The reference the authority gave your filing, such as paye-2026-09-rivers. null until the authority has issued one.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.
409The record is not in a state that allows this.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "employer_return",
  "livemode": true,
  "mocked": true,
  "kind": "monthly_paye",
  "status": "draft",
  "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "period": "2026-09",
  "generated_from": [
    "example"
  ],
  "totals": {
    "employee_count": 1,
    "total": {
      "amount": 1234567,
      "currency": "NGN"
    }
  },
  "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "submitted_at": "2026-09-01T09:00:00Z",
  "authority_reference": "paye-2026-09-rivers"
}
POST/v1/remittance/returns/{return_id}/submit#

Submit an approved return to the authority

remittance.returns.submit

Files the return with the authority. Refused unless a named person has approved it.

Path parameters

return_id string required

The 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 required

A 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 required

The 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" required

Always employer_return. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required
monthly_payeannual_payepension_schedulenhf_schedulensitf_returnitf_returnnhia_schedule
status string required
draftpending_approvalapprovedsubmittedacceptedrejected
authority_id string required

The 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 required

The 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 optional

The vaulted receipts this return was generated from.

totals object optional

What the return declares, summed from the vaulted receipts it was generated from: how many employees and the total amount.

2 fields
employee_count integer optional

How many employees the return declares for the period.

total Money optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

approved_by string · nullable optional

A named person. Required before submission.

submitted_at string · date-time · nullable optional

When the return was filed with the authority, as an RFC 3339 timestamp in UTC. null until you submit it.

authority_reference string · nullable optional

The reference the authority gave your filing, such as paye-2026-09-rivers. null until the authority has issued one.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.
409The record is not in a state that allows this.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_return_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "employer_return",
  "livemode": true,
  "mocked": true,
  "kind": "monthly_paye",
  "status": "draft",
  "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "period": "2026-09",
  "generated_from": [
    "example"
  ],
  "totals": {
    "employee_count": 1,
    "total": {
      "amount": 1234567,
      "currency": "NGN"
    }
  },
  "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "submitted_at": "2026-09-01T09:00:00Z",
  "authority_reference": "paye-2026-09-rivers"
}
GET/v1/remittance/readiness#

What REMIT needs, what you have, and what is missing

remittance.readiness.retrieve

Tells you whether instruction sets are arriving from Droomwork payroll or being supplied by you, and which authorities you hold credentials for.

Call it before your first filing rather than discover a missing credential on a deadline.

Returns

The readiness report.

object always "readiness_report" required

Always readiness_report. Tells you which kind of record you are looking at, so one handler can read any response.

module string required

The 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).

anchorproofrailflowmatchrunremitroute
mode string required

integrated 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.

integratedstandalone
ready boolean required

true 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 required

One 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 required

Named for what it is, not for who supplies it.

owner string required

The sibling module that owns this fact when running integrated.

contract_row string optional
required string required

How 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.

attestedverified
held one of required
Assuranceor
source string · nullable optional
integratedstandalonenull
satisfied boolean required
missing_because string · nullable optional
not_suppliedassurance_too_lownull
always_enforced array of string optional

Gates 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 optional

Filing cannot proceed for these until credentials are supplied.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "object": "readiness_report",
  "module": "anchor",
  "mode": "integrated",
  "ready": true,
  "rows": [
    {
      "fact": "anchored_subject",
      "owner": "anchor",
      "required": "attested",
      "held": "attested",
      "satisfied": true,
      "contract_row": "6.1.13",
      "source": "integrated",
      "missing_because": "not_supplied"
    }
  ],
  "always_enforced": [
    "example"
  ],
  "authorities_without_credentials": [
    "example"
  ]
}
POST/v1/remittance/instruction_sets/{instruction_set_id}/reject#

Reject an ingested instruction set

remittance.instruction_sets.reject

The counterpart of accept. A rejected set is never remitted against and never silently corrected: whoever submitted it submits a new one. Refused unless the set is pending acceptance; a set already accepted has obligations standing against it.

Path parameters

instruction_set_id string required

The 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 required

A 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 rejected instruction set.

id string required

The 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" required

Always ingested_instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

Nothing is committed until accepted.

receivedvalidatingpending_acceptanceacceptedrejected
source string required

Where the set came from. Droomwork payroll or your own, by API or by file. Everything downstream behaves identically whichever it was.

runexternal_apiexternal_file
period string required

The month the set covers, as YYYY-MM, such as 2026-09. Filter the list by it with the period query.

run_id string · nullable optional

The 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 optional

What 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 required

The 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" required

Always instruction_set. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required

The 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 optional

The pay period the amounts are owed for, as year and month, for example 2026-09.

paye array of object required

Grouped by the State IRS of the employee's residence, not the employer's location.

5 fields
authority_id string required

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

payee_count integer optional

How many employees this line's PAYE covers. Optional; when it is present, check it against your own headcount for that state.

reconciliation_reference string required

The 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 required

Grouped by administrator and retirement savings account number.

6 fields
administrator_id string required

The 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 optional

The 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 optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

employer_amount Money optional
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

reconciliation_reference string required

The 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 required

NHF, NSITF, ITF and NHIA totals, each with a reconciliation reference.

3 fields
code string required

Which 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.

nhfnsitfitfnhia
amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

reconciliation_reference string required

The 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 required

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

validation_report ValidationReport required

The 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 required

How 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 required

How 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 required

How 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 optional

One 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 required

The row in a file, or the line in an instruction set.

severity string required

error means the entry failed and must be fixed. warning means it passed, but points at something you should confirm before you go ahead.

errorwarning
code string required

Why 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 required

What was wrong with the entry, in plain words. Show it beside the row; it may change, so branch on code.

jurisdiction_pack object optional

The 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 optional

Which 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 optional

The 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 optional

Who accepted the set: the actor that called accept. null until the set is accepted.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.
409The record is not in a state that allows this.
422A required fact is missing. Call the readiness endpoint to see what.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_instruction_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "ingested_instruction_set",
  "livemode": true,
  "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": "no_payee_destination",
        "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": true,
    "mocked": true,
    "run_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "paye": [
      {
        "authority_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
        "jurisdiction": "Rivers State Internal Revenue Service",
        "amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "reconciliation_reference": "paye-2026-09-rivers",
        "payee_count": 1
      }
    ],
    "pension": [
      {
        "administrator_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
        "amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "reconciliation_reference": "paye-2026-09-rivers",
        "administrator_name": "Rivers State Internal Revenue Service",
        "employee_amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "employer_amount": {
          "amount": 1234567,
          "currency": "NGN"
        }
      }
    ],
    "levies": [
      {
        "code": "nhf",
        "amount": {
          "amount": 1234567,
          "currency": "NGN"
        },
        "reconciliation_reference": "paye-2026-09-rivers"
      }
    ],
    "totals": {
      "total": {
        "amount": 1234567,
        "currency": "NGN"
      }
    },
    "period": "2026-09",
    "created_at": "2026-09-01T09:00:00Z"
  },
  "jurisdiction_pack": {
    "pack_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "version": "2026.08.1"
  },
  "accepted_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "created_at": "2026-09-01T09:00:00Z"
}
POST/v1/remittance/remittances/{remittance_id}/execute#

Execute an approved remittance

remittance.remittances.execute

Runs every leg. A leg that fails leaves the others alone, so the remittance can come back partially completed rather than failed. Refused unless the remittance has been approved: approval is a person, and execution moves money.

Path parameters

remittance_id string required

The 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 required

A 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, executing.

id string required

The 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" required

Always remittance. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where 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 required
draftapprovedexecutingcompletedpartially_completedfailed
instruction_set_id string required

The 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 optional

The 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 required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

legs array of Leg required

One 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 required

The 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" required

Always remittance_leg. Tells you which kind of record you are looking at, so one handler can read any response.

remittance_id string optional

The 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 required

The 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 optional

The 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 optional

How 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_manual
status string required

A leg reaches completed only once its receipt is vaulted. quarantined means a receipt arrived but disagreed with the leg.

pendingexecutingawaiting_receiptcompletedquarantinedfailed
amount Money required
2 fields of Money
amount integer · int64 required

A 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 required

ISO 4217 code.

receipt_id string · nullable optional

The 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 optional

How 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 optional

Why 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 optional

Who 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 optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.
409The record is not in a state that allows this.
422A required fact is missing. Call the readiness endpoint to see what.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "remit_authority_rail_remittance_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "remittance",
  "livemode": true,
  "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": 1234567,
        "currency": "NGN"
      },
      "remittance_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "authority_name": "Rivers 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": 1234567,
    "currency": "NGN"
  },
  "period": "2026-09",
  "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "created_at": "2026-09-01T09:00:00Z"
}
GET/v1/remittance/events#

List events

remittance.events.list

The append only record of everything REMIT is the authority for, oldest first. Every event here is one the webhook catalogue declares, so the code that handles a delivery handles a replay too.

Two ways to read it. Pass stream with after to replay one stream from the sequence you last handled; that is exact and needs no cursor, because the sequence counts per organisation and per stream. Without stream, you get events across streams in the order they were recorded, paged with starting_after.

Query parameters

stream string optional

The 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 optional

The 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 optional

How 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 optional

The 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.

object always "list" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of StoredEvent required

The records on this page, in the order the list promises. Empty when nothing matched.

13 fields of StoredEvent
id string required

The 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 required

What 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 required

The 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 required

The 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 required

Per 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 required

When the event happened, as an RFC 3339 timestamp in UTC. Not when it was delivered: a redelivery carries the original value.

request_id string optional

The 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 required

Which realm the event happened in. False is the sandbox.

mocked boolean required

Whether 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 required

Which 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.

anchorproofrailflowmatchrunremitroutegatewayiamledgerregistrydeliverydocumentsintelligence
object always "event" required

Always event. Tells you which kind of record you are looking at, so one handler can read any response.

stream string required

The 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 required

The 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 required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# 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)
Response
{
  "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": true,
      "mocked": true,
      "source": "anchor",
      "request_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "event",
      "stream": "example",
      "data": {}
    }
  ],
  "has_more": true
}
GET/v1/remittance/events/{event_id}#

Retrieve an event

remittance.events.retrieve

You get one event. An identifier belonging to another organisation comes back not found rather than refused.

Path parameters

event_id string required

The 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.

id string required

The 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 required

What 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 required

The 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 required

The 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 required

Per 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 required

When the event happened, as an RFC 3339 timestamp in UTC. Not when it was delivered: a redelivery carries the original value.

request_id string optional

The 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 required

Which realm the event happened in. False is the sandbox.

mocked boolean required

Whether 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 required

Which 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.

anchorproofrailflowmatchrunremitroutegatewayiamledgerregistrydeliverydocumentsintelligence
object always "event" required

Always event. Tells you which kind of record you are looking at, so one handler can read any response.

stream string required

The 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 required

The 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

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "evt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "type": "run.payslip.calculated",
  "schema_version": 1,
  "org_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "sequence": 0,
  "occurred_at": "2026-09-01T09:00:00Z",
  "livemode": true,
  "mocked": true,
  "source": "anchor",
  "request_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "event",
  "stream": "example",
  "data": {}
}
GET/v1/remittance/audit_entries#

List audit entries

remittance.audit_entries.list

Who did what, newest first. You get one row per attempt, not per success, so refusals are here too: repeated forbidden answers on one credential is what an attack looks like.

A read that succeeded is not recorded.

Query parameters

action string optional

Restricts 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 optional

Restricts 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 optional

Restricts 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 optional

Restricts 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 optional

Restricts 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.

succeededrefusedfailed
recorded_after string optional

Only 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 optional

Only 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 optional

How 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 optional

The 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" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of AuditEntry required

The records on this page, in the order the list promises. Empty when nothing matched.

13 fields of AuditEntry
id string required

The 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" required

Always audit_entry. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm the action happened in. False is the sandbox.

mocked boolean required

Whether 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 required

When the attempt was recorded, as an RFC 3339 timestamp in UTC. The list is ordered by it, newest first.

request_id string required

The 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 required

What 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 required

The 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 required

What was attempted, as the method and the route pattern.

resource string · nullable optional

The 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 optional

The 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 required

How the attempt ended: succeeded (a status below 400), refused (a 4xx status) or failed (a 5xx status). status carries the exact code.

succeededrefusedfailed
status integer required

The 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 required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# 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)
Response
{
  "object": "list",
  "data": [
    {
      "id": "audit_entry_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "audit_entry",
      "livemode": true,
      "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": "example",
      "resource_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
    }
  ],
  "has_more": true
}
GET/v1/remittance/audit_entries/{audit_entry_id}#

Retrieve an audit entry

remittance.audit_entries.retrieve

You get one entry. An identifier belonging to another organisation comes back not found rather than refused.

Path parameters

audit_entry_id string required

The 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 required

The 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" required

Always audit_entry. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm the action happened in. False is the sandbox.

mocked boolean required

Whether 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 required

When the attempt was recorded, as an RFC 3339 timestamp in UTC. The list is ordered by it, newest first.

request_id string required

The 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 required

What 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 required

The 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 required

What was attempted, as the method and the route pattern.

resource string · nullable optional

The 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 optional

The 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 required

How the attempt ended: succeeded (a status below 400), refused (a 4xx status) or failed (a 5xx status). status carries the exact code.

succeededrefusedfailed
status integer required

The 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

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
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)
Response
{
  "id": "audit_entry_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "audit_entry",
  "livemode": true,
  "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": "example",
  "resource_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}