Skip to content
Sawitara

Sawitara API documentation

A read-only, token-based REST API on every Sawitara instance, for systems that need journal or traceability data without manual exports.

Audience

Who the API is for

Access is always granted by the customer who runs the instance, per token and per unit.

ERP and group accounting integrators

Pull POSTED journals and SAP/Accurate export batches, then mark batches received. Endpoints /jurnal and /batch. Not a vendor-certified integration.

Buyers and exporters

Supplier plots with GeoJSON, STDB, legality, monthly TTP and a DDS data pack per DO (Preview). Tokens are issued by the supplier mill that runs Sawitara.

Banks and financing partners

Today: plot, legality, STDB and per-cooperative readiness data through a trace:baca token granted by the customer. Dedicated PSR/KUR files for partners are coming soon.

Provincial and district estate crop offices (Disbun)

STDB register, geolocation and share of plots with STDB per supplier when the customer grants a token. STDBs are still issued by the office; Sawitara only records them.

Authentication

Bearer tokens with abilities and unit scope

The instance admin creates a token under Settings › API Tokens, ticks its abilities, and can limit it to one unit (with its child units) and an expiry in days. The token text is shown once; only its SHA-256 hash is stored. Creating and revoking tokens is recorded in the audit trail.

Send on every request:

Authorization: Bearer <id>|<teks token>
Accept: application/json

The unit scope is always intersected with the units the token owner may see. Tokens do not work for the web app (which uses login sessions). Serve the API over HTTPS only and make sure your reverse proxy forwards the Authorization header.

AbilityMeaning
jurnal:bacaRead journals, export status and batch contents.
batch:konfirmasiMark an export batch as received (needs jurnal:baca).
trace:bacaRead plots, EUDR readiness, TTP and DDS packs.
trace:data-pribadiPlot owner NIK (national ID) sent in full (needs trace:baca). Without it the NIK is masked.

A trace:baca token cannot read journals, and a jurnal:baca token cannot read traceability data. Phone numbers, bank accounts, addresses and file paths are never sent.

Quick start

curl examples

Replace https://erp.contoh.co.id with your instance domain.

Journals not yet exported, with SAP account codes

curl -s "https://erp.contoh.co.id/api/v1/jurnal?periode=2026-07&status=belum&sistem=SAP" \
  -H "Authorization: Bearer 12|swt_xxxxxxxxxxxxxxxx" \
  -H "Accept: application/json"

Plots that are not EUDR-ready yet

curl -s "https://erp.contoh.co.id/api/v1/ketertelusuran/plot?saringan=belum_siap&per_halaman=50" \
  -H "Authorization: Bearer 14|swt_xxxxxxxxxxxxxxxx" \
  -H "Accept: application/json"

Response (shortened):

{
  "data": [ { "kode_plot": "PLS-001-A", "jenis": "PLASMA", "siap_eudr": false, "...": "..." } ],
  "meta": { "halaman": 1, "per_halaman": 50, "total": 1, "halaman_terakhir": 1, "berikutnya": null, "nik": "disamarkan" },
  "ringkasan": { "jumlah_plot": 1, "persen_stdb": 100, "...": "..." },
  "filter": { "unit": null, "jenis": null, "saringan": "belum_siap", "pemasok": null }
}

Mark a batch as received

curl -s -X POST "https://erp.contoh.co.id/api/v1/batch/7/diterima" \
  -H "Authorization: Bearer 12|swt_xxxxxxxxxxxxxxxx" \
  -H "Accept: application/json" -H "Content-Type: application/json" \
  -d '{"referensi": "BKPF 1000/4900000123/2026"}'
Endpoint

All 12 endpoints

Base URL https://erp.contoh.co.id/api/v1. Generated from openapi.yaml at build time.

Jurnal

General ledger journals and SAP/Accurate export batches (Sawitara Finance). Abilities jurnal:baca and batch:konfirmasi.

GET /api/v1/jurnal Available

List POSTED journals with their export status. One journal = one two-line document (debit D and credit K) with equal amounts. Requires periode, or dari and sampai. Ordered by date then id.

Token ability: jurnal:baca

ParameterInTypeDescription
periodequerystringMonth YYYY-MM. Required when dari/sampai are not given.
pattern ^\d{4}-(0[1-9]|1[0-2])$
dariquerystring (date)Start date YYYY-MM-DD (together with sampai).
sampaiquerystring (date)End date YYYY-MM-DD, on or after dari.
statusquerystringJournal export status.
semua belum diekspor diterima · default semua
unitquerystringUnit code within the token's scope (including child units). Outside the scope returns 403.
max 20 chars
sistemquerystringFill akun_eksternal from this system's account mapping (null when unmapped).
SAP ACCURATE
per_halamanqueryintegerRows per page.
min 1 · max 500 · default 100
pagequeryintegerPage number, starting at 1.
min 1 · default 1

Responses: 200 401 403 422 429

Response fields (200), 35 fields
FieldType
dataarray<object>
data[].idinteger
data[].nojurnalstring
data[].tanggalstring (date)
data[].periodestring
data[].periode_ditutupboolean
data[].unitstring | null
data[].keteranganstring | null
data[].nominalnumber
data[].barisarray<object>
data[].baris[].nomor_barisinteger
1 2
data[].baris[].sisistring
D K
data[].baris[].akunstring | null
data[].baris[].akun_eksternalstring | null
data[].baris[].jumlahnumber
data[].eksporobject | null
data[].ekspor.batch_idinteger
data[].ekspor.nobatchstring
data[].ekspor.sistemstring
SAP ACCURATE
data[].ekspor.statusstring
DIEKSPOR DITERIMA
data[].ekspor.diekspor_atstring (date-time) | null
data[].ekspor.diekspor_olehstring | null
data[].ekspor.diterima_atstring (date-time) | null
metaobject
meta.halamaninteger
meta.per_halamaninteger
meta.totalinteger
meta.halaman_terakhirinteger
meta.berikutnyastring (uri) | null
filterobject
filter.daristring (date)
filter.sampaistring (date)
filter.statusstring
semua belum diekspor diterima
filter.unitstring | null
filter.sistemstring | null
SAP ACCURATE

GET /api/v1/batch Available

List journal export batches, newest first. 50 batches per page. Batches outside the token's unit scope are excluded.

Token ability: jurnal:baca

ParameterInTypeDescription
statusquerystringBatch status.
DIEKSPOR DITERIMA DIBATALKAN
sistemquerystringTarget system of the batch.
SAP ACCURATE
pagequeryintegerPage number, starting at 1.
min 1 · default 1

Responses: 200 401 403 422 429

Response fields (200), 22 fields
FieldType
dataarray<object>
data[].idinteger
data[].nobatchstring
data[].sistemstring
SAP ACCURATE
data[].statusstring
DIEKSPOR DITERIMA DIBATALKAN
data[].formatstring
CSV XLSX
data[].tanggal_daristring (date)
data[].tanggal_sampaistring (date)
data[].unitstring | null
data[].jumlah_jurnalinteger
data[].total_nominalnumber
data[].periode_belum_ditutuparray<string>
data[].dibuat_atstring (date-time) | null
data[].dibuat_olehstring | null
data[].diterima_atstring (date-time) | null
data[].diterima_olehstring | null
data[].referensi_penerimastring | null
metaobject
meta.halamaninteger
meta.totalinteger
meta.halaman_terakhirinteger
meta.berikutnyastring (uri) | null

GET /api/v1/batch/{id} Available

Export batch contents (snapshot taken when the batch was created). Documents and lines exactly as when the batch was created; later mapping changes do not alter them. cost_center is only filled on expense account lines.

Token ability: jurnal:baca

ParameterInTypeDescription
idpathinteger requiredBatch id from GET /batch. Batches outside the token's unit scope return 404.
min 1

Responses: 200 401 403 404 429

Response fields (200), 36 fields
FieldType
dataobject
data.idinteger
data.nobatchstring
data.sistemstring
SAP ACCURATE
data.statusstring
DIEKSPOR DITERIMA DIBATALKAN
data.formatstring
CSV XLSX
data.tanggal_daristring (date)
data.tanggal_sampaistring (date)
data.unitstring | null
data.jumlah_jurnalinteger
data.total_nominalnumber
data.periode_belum_ditutuparray<string>
data.dibuat_atstring (date-time) | null
data.dibuat_olehstring | null
data.diterima_atstring (date-time) | null
data.diterima_olehstring | null
data.referensi_penerimastring | null
data.profilstring | null
data.dokumenarray<object>
data.dokumen[].jurnal_idinteger
data.dokumen[].referensistring
data.dokumen[].barisarray<object>
data.dokumen[].baris[].nomor_barisinteger
data.dokumen[].baris[].sisistring
D K
data.dokumen[].baris[].tanggalstring (date)
data.dokumen[].baris[].referensistring
data.dokumen[].baris[].teksstring
data.dokumen[].baris[].unitstring | null
data.dokumen[].baris[].akun_internalstring | null
data.dokumen[].baris[].akunstring | null
data.dokumen[].baris[].jumlahnumber
data.dokumen[].baris[].kode_perusahaanstring | null
data.dokumen[].baris[].profit_centerstring | null
data.dokumen[].baris[].cost_centerstring | null
data.dokumen[].baris[].departemenstring | null
data.dokumen[].baris[].proyekstring | null

POST /api/v1/batch/{id}/diterima Available

Mark a batch as received by the target system. Idempotent: a batch that is already DITERIMA is left unchanged. A DIBATALKAN batch returns 409. Recorded in the audit trail with the token name and owner.

Token ability: batch:konfirmasi

ParameterInTypeDescription
idpathinteger requiredBatch id from GET /batch. Batches outside the token's unit scope return 404.
min 1

Optional JSON body: referensi (string | null, max 100).

Responses: 200 401 403 404 409 422 429

Response fields (200), 17 fields
FieldType
dataobject
data.idinteger
data.nobatchstring
data.sistemstring
SAP ACCURATE
data.statusstring
DIEKSPOR DITERIMA DIBATALKAN
data.formatstring
CSV XLSX
data.tanggal_daristring (date)
data.tanggal_sampaistring (date)
data.unitstring | null
data.jumlah_jurnalinteger
data.total_nominalnumber
data.periode_belum_ditutuparray<string>
data.dibuat_atstring (date-time) | null
data.dibuat_olehstring | null
data.diterima_atstring (date-time) | null
data.diterima_olehstring | null
data.referensi_penerimastring | null

Ketertelusuran

Supplier plots, EUDR readiness, TTP, DDS data packs, EUDR screening reference layers and results, and DDS GeoJSON for the EUDR Information System (Sawitara Trace). Abilities trace:baca and trace:data-pribadi.

GET /api/v1/ketertelusuran/plot Available

Supplier plots with geolocation, STDB, legality and EUDR checklist. Owner NIK (national ID) is masked (1401********0001) unless the token also has trace:data-pribadi. Phone numbers, bank accounts, addresses and file paths are never sent. ringkasan covers all filtered results, not just this page.

Token ability: trace:baca

ParameterInTypeDescription
unitquerystringUnit code within the token's scope (including child units). Outside the scope returns 403.
max 20 chars
jenisquerystringPlot type. Independent smallholders = PIHAK3 linked to a SWADAYA supplier.
INTI PLASMA PIHAK3
saringanquerystringOnly plots that do not yet meet a given checklist item.
tanpa_stdb belum_terverifikasi geolokasi_belum_lengkap belum_siap
pemasokquerystringSupplier key (pemasok.kunci from this endpoint or pemasok_kunci from /ketertelusuran/kesiapan).
max 200 chars
per_halamanqueryintegerRows per page.
min 1 · max 500 · default 100
pagequeryintegerPage number, starting at 1.
min 1 · default 1

Responses: 200 401 403 422 429

Response fields (200), 85 fields
FieldType
dataarray<object>
data[].kode_plotstring
data[].jenisstring
INTI PLASMA PIHAK3
data[].unitstring | null
data[].luas_hanumber
data[].tanggal_tanamstring (date) | null
data[].pemasokobject
data[].pemasok.kuncistring
data[].pemasok.namastring | null
data[].pemasok.jenisstring
INTI KOPERASI PIHAK3 SWADAYA
data[].pemilikobject | null
data[].pemilik.namastring | null
data[].pemilik.nikstring | null
data[].geolokasiobject
data[].geolokasi.tipestring | null
Point Polygon
data[].geolokasi.wajib_poligonboolean
data[].geolokasi.lengkapboolean
data[].geolokasi.galatarray<string>
data[].geolokasi.geometriGeoJSON Point | Polygon | null
data[].stdbobject
data[].stdb.statusstring
ADA BELUM TIDAK_BERLAKU
data[].stdb.nomorstring | null
data[].stdb.tanggal_terbitstring (date) | null
data[].stdb.penerbitstring | null
data[].stdb.ada_berkasboolean
data[].legalitasobject
data[].legalitas.status_dokumenstring | null
LENGKAP DALAM_PROSES BELUM_LENGKAP
data[].legalitas.alas_hakobject
data[].legalitas.alas_hak.jenisstring | null
SHM SKT HGU LAINNYA
data[].legalitas.alas_hak.nomorstring | null
data[].legalitas.alas_hak.keteranganstring | null
data[].legalitas.alas_hak.berlaku_sampaistring (date) | null
data[].legalitas.alas_hak.kedaluwarsaboolean
data[].legalitas.alas_hak.ada_berkasboolean
data[].legalitas.verifikasiobject
data[].legalitas.verifikasi.statusstring
BELUM TERVERIFIKASI DITOLAK
data[].legalitas.verifikasi.alasanstring | null
data[].legalitas.verifikasi.olehstring | null
data[].legalitas.verifikasi.padastring (date-time) | null
data[].sertifikasiobject
data[].sertifikasi.skemastring | null
ISPO RSPO TIDAK_ADA
data[].sertifikasi.nomorstring | null
data[].sertifikasi.berlaku_sampaistring (date) | null
data[].skrining_deforestasiobject
data[].skrining_deforestasi.hasilstring | null
BELUM LOLOS TIDAK_LOLOS
data[].skrining_deforestasi.tanggalstring (date) | null
data[].skrining_deforestasi.sumberstring | null
MANUAL LAPISAN
data[].skrining_deforestasi.indikasistring | null
TIDAK_TERINDIKASI PERLU_DITINJAU TERINDIKASI
data[].skrining_deforestasi.tinjauanstring | null
BELUM DITERIMA DITOLAK
data[].checklistobject
data[].checklist.geolokasi_lengkapboolean
data[].checklist.stdbboolean
data[].checklist.legalitas_terverifikasiboolean
data[].checklist.skrining_lolosboolean
data[].siap_eudrboolean
metaobject
meta.halamaninteger
meta.per_halamaninteger
meta.totalinteger
meta.halaman_terakhirinteger
meta.berikutnyastring (uri) | null
meta.nikstring
utuh disamarkan
ringkasanobject
ringkasan.jumlah_plotinteger
ringkasan.luas_hanumber
ringkasan.plot_wajib_stdbinteger
ringkasan.plot_ber_stdbinteger
ringkasan.persen_stdbnumber | null
ringkasan.plot_terverifikasiinteger
ringkasan.persen_terverifikasinumber | null
ringkasan.plot_wajib_poligoninteger
ringkasan.persen_poligon_wajibnumber | null
ringkasan.persen_poligonnumber | null
ringkasan.persen_geolokasi_lengkapnumber | null
ringkasan.plot_siapinteger
ringkasan.persen_siapnumber | null
ringkasan.plot_tidak_terindikasiinteger
ringkasan.plot_perlu_ditinjauinteger
ringkasan.plot_terindikasiinteger
ringkasan.plot_belum_diskrininginteger
filterobject
filter.unitstring | null
filter.jenisstring | null
filter.saringanstring | null
filter.pemasokstring | null

GET /api/v1/ketertelusuran/kesiapan Available

EUDR readiness checklist per supplier or cooperative. Groups: plasma plots per cooperative (KOPERASI:), third-party plots per supplier master (PEMASOK:) or reference name (REF:), nucleus plots per division (INTI:). A null percentage means the denominator is zero, not 0% or 100%.

Token ability: trace:baca

ParameterInTypeDescription
unitquerystringUnit code within the token's scope (including child units). Outside the scope returns 403.
max 20 chars

Responses: 200 401 403 422 429

Response fields (200), 41 fields
FieldType
dataarray<object>
data[].jumlah_plotinteger
data[].luas_hanumber
data[].plot_wajib_stdbinteger
data[].plot_ber_stdbinteger
data[].persen_stdbnumber | null
data[].plot_terverifikasiinteger
data[].persen_terverifikasinumber | null
data[].plot_wajib_poligoninteger
data[].persen_poligon_wajibnumber | null
data[].persen_poligonnumber | null
data[].persen_geolokasi_lengkapnumber | null
data[].plot_siapinteger
data[].persen_siapnumber | null
data[].plot_tidak_terindikasiinteger
data[].plot_perlu_ditinjauinteger
data[].plot_terindikasiinteger
data[].plot_belum_diskrininginteger
data[].pemasok_kuncistring
data[].pemasok_namastring | null
data[].pemasok_jenisstring
INTI KOPERASI PIHAK3 SWADAYA
totalobject
total.jumlah_plotinteger
total.luas_hanumber
total.plot_wajib_stdbinteger
total.plot_ber_stdbinteger
total.persen_stdbnumber | null
total.plot_terverifikasiinteger
total.persen_terverifikasinumber | null
total.plot_wajib_poligoninteger
total.persen_poligon_wajibnumber | null
total.persen_poligonnumber | null
total.persen_geolokasi_lengkapnumber | null
total.plot_siapinteger
total.persen_siapnumber | null
total.plot_tidak_terindikasiinteger
total.plot_perlu_ditinjauinteger
total.plot_terindikasiinteger
total.plot_belum_diskrininginteger
filterobject
filter.unitstring | null

GET /api/v1/ketertelusuran/ttp Available

Monthly TTP (traceability to plantation) summary. TTP = kg of FFB from completed weighbridge tickets linked to plots with screening LOLOS (passed), divided by all FFB kg in the period. Requires periode, or dari and sampai (at most 12 months).

Token ability: trace:baca

ParameterInTypeDescription
periodequerystringA single month YYYY-MM.
pattern ^\d{4}-(0[1-9]|1[0-2])$
dariquerystringFirst month YYYY-MM (together with sampai).
pattern ^\d{4}-(0[1-9]|1[0-2])$
sampaiquerystringLast month YYYY-MM, at most 11 months after dari.
pattern ^\d{4}-(0[1-9]|1[0-2])$
unitquerystringUnit code within the token's scope (including child units). Outside the scope returns 403.
max 20 chars

Responses: 200 401 403 422 429

Response fields (200), 43 fields
FieldType
dataarray<object>
data[].jumlah_tiketinteger
data[].total_kgnumber
data[].terhubung_plot_kgnumber
data[].lolos_kgnumber
data[].persen_ttpnumber | null
data[].periodestring
data[].per_kelompokobject
data[].per_kelompok.INTIobject
data[].per_kelompok.INTI.jumlah_tiketinteger
data[].per_kelompok.INTI.total_kgnumber
data[].per_kelompok.INTI.terhubung_plot_kgnumber
data[].per_kelompok.INTI.lolos_kgnumber
data[].per_kelompok.INTI.persen_ttpnumber | null
data[].per_kelompok.PLASMAobject
data[].per_kelompok.PLASMA.jumlah_tiketinteger
data[].per_kelompok.PLASMA.total_kgnumber
data[].per_kelompok.PLASMA.terhubung_plot_kgnumber
data[].per_kelompok.PLASMA.lolos_kgnumber
data[].per_kelompok.PLASMA.persen_ttpnumber | null
data[].per_kelompok.PIHAK3object
data[].per_kelompok.PIHAK3.jumlah_tiketinteger
data[].per_kelompok.PIHAK3.total_kgnumber
data[].per_kelompok.PIHAK3.terhubung_plot_kgnumber
data[].per_kelompok.PIHAK3.lolos_kgnumber
data[].per_kelompok.PIHAK3.persen_ttpnumber | null
data[].per_kelompok.TIDAK_DIKETAHUIobject
data[].per_kelompok.TIDAK_DIKETAHUI.jumlah_tiketinteger
data[].per_kelompok.TIDAK_DIKETAHUI.total_kgnumber
data[].per_kelompok.TIDAK_DIKETAHUI.terhubung_plot_kgnumber
data[].per_kelompok.TIDAK_DIKETAHUI.lolos_kgnumber
data[].per_kelompok.TIDAK_DIKETAHUI.persen_ttpnumber | null
data[].stdbobject
data[].stdb.plot_wajib_stdbinteger
data[].stdb.plot_ber_stdbinteger
data[].stdb.persen_plot_ber_stdbnumber | null
data[].stdb.kg_wajib_stdbnumber
data[].stdb.kg_ber_stdbnumber
data[].stdb.persen_kg_ber_stdbnumber | null
filterobject
filter.daristring
filter.sampaistring
filter.unitstring | null

GET /api/v1/ketertelusuran/dds Preview

Due diligence (DDS) data pack per delivery order or contract. Preview: it contains the plots that supplied FFB to the mill during the production period (from weighbridge tickets), not physical segregation per shipment. Production period: the periode parameter; otherwise active mass-balance claim periods; otherwise the DO loading month or contract date. Requires nodo or nokontrak. For each plot's share and allocation within one shipment, use GET /ketertelusuran/dds-pengiriman.

Token ability: trace:baca

ParameterInTypeDescription
nodoquerystringShipping DO number. Required when nokontrak is not given.
max 35 chars
nokontrakquerystringSales contract number (used when nodo is empty).
max 35 chars
periodequerystringForce the production period YYYY-MM.
pattern ^\d{4}-(0[1-9]|1[0-2])$
unitquerystringUnit code within the token's scope (including child units). Outside the scope returns 403.
max 20 chars

Responses: 200 401 403 404 422 429

Response fields (200), 88 fields
FieldType
dataobject
data.dokumenobject
data.dokumen.jenisstring
DO KONTRAK
data.dokumen.nodostring | null
data.dokumen.nokontrakstring
data.dokumen.pembelistring | null
data.dokumen.komoditasstring | null
data.dokumen.kode_hsstring | null
1511.10 1207.10
data.dokumen.negara_produksistring = ID
data.dokumen.kuantum_kgnumber
data.dokumen.tanggal_muatstring (date) | null
data.dokumen.pelabuhan_muatstring | null
data.dokumen.pelabuhan_bongkarstring | null
data.dokumen.statusstring | null
data.periode_produksiarray<string>
data.dasar_periodestring
parameter klaim_mass_balance tanggal_muat tanggal_kontrak
data.catatanstring
data.klaim_mass_balancearray<object>
data.klaim_mass_balance[].tanggalstring (date) | null
data.klaim_mass_balance[].periodestring
data.klaim_mass_balance[].skemastring | null
data.klaim_mass_balance[].produkstring | null
data.klaim_mass_balance[].kgnumber
data.ttparray<object>
data.ttp[].jumlah_tiketinteger
data.ttp[].total_kgnumber
data.ttp[].terhubung_plot_kgnumber
data.ttp[].lolos_kgnumber
data.ttp[].persen_ttpnumber | null
data.ttp[].periodestring
data.ttp[].per_kelompokobject
data.ttp[].per_kelompok.INTIobject
data.ttp[].per_kelompok.INTI.jumlah_tiketinteger
data.ttp[].per_kelompok.INTI.total_kgnumber
data.ttp[].per_kelompok.INTI.terhubung_plot_kgnumber
data.ttp[].per_kelompok.INTI.lolos_kgnumber
data.ttp[].per_kelompok.INTI.persen_ttpnumber | null
data.ttp[].per_kelompok.PLASMAobject
data.ttp[].per_kelompok.PLASMA.jumlah_tiketinteger
data.ttp[].per_kelompok.PLASMA.total_kgnumber
data.ttp[].per_kelompok.PLASMA.terhubung_plot_kgnumber
data.ttp[].per_kelompok.PLASMA.lolos_kgnumber
data.ttp[].per_kelompok.PLASMA.persen_ttpnumber | null
data.ttp[].per_kelompok.PIHAK3object
data.ttp[].per_kelompok.PIHAK3.jumlah_tiketinteger
data.ttp[].per_kelompok.PIHAK3.total_kgnumber
data.ttp[].per_kelompok.PIHAK3.terhubung_plot_kgnumber
data.ttp[].per_kelompok.PIHAK3.lolos_kgnumber
data.ttp[].per_kelompok.PIHAK3.persen_ttpnumber | null
data.ttp[].per_kelompok.TIDAK_DIKETAHUIobject
data.ttp[].per_kelompok.TIDAK_DIKETAHUI.jumlah_tiketinteger
data.ttp[].per_kelompok.TIDAK_DIKETAHUI.total_kgnumber
data.ttp[].per_kelompok.TIDAK_DIKETAHUI.terhubung_plot_kgnumber
data.ttp[].per_kelompok.TIDAK_DIKETAHUI.lolos_kgnumber
data.ttp[].per_kelompok.TIDAK_DIKETAHUI.persen_ttpnumber | null
data.ttp[].stdbobject
data.ttp[].stdb.plot_wajib_stdbinteger
data.ttp[].stdb.plot_ber_stdbinteger
data.ttp[].stdb.persen_plot_ber_stdbnumber | null
data.ttp[].stdb.kg_wajib_stdbnumber
data.ttp[].stdb.kg_ber_stdbnumber
data.ttp[].stdb.persen_kg_ber_stdbnumber | null
data.plotobject
data.plot.typestring = FeatureCollection
data.plot.featuresarray<object>
data.plot.features[].typestring = Feature
data.plot.features[].geometryGeoJSON Point | Polygon | null
data.plot.features[].propertiesobject
data.plot.features[].properties.kode_plotstring
data.plot.features[].properties.jenisstring
INTI PLASMA PIHAK3
data.plot.features[].properties.luas_hanumber
data.plot.features[].properties.tanggal_tanamstring (date) | null
data.plot.features[].properties.status_legalitasstring | null
data.plot.features[].properties.no_stdbstring | null
data.plot.features[].properties.jenis_alas_hakstring | null
data.plot.features[].properties.status_verifikasi_legalitasstring | null
data.plot.features[].properties.sertifikasistring | null
data.plot.features[].properties.nomor_sertifikatstring | null
data.plot.features[].properties.hasil_skrining_deforestasistring | null
data.plot.features[].properties.tanggal_skriningstring (date) | null
data.plot.features[].properties.produksi_tbs_kgnumber
data.plot.features[].properties.periodearray<string>
data.plot.features[].properties.status_stdbstring | null
ADA BELUM TIDAK_BERLAKU
data.plot.features[].properties.geolokasi_lengkapboolean | null
data.plot.features[].properties.legalitas_terverifikasiboolean | null
data.plot.features[].properties.siap_eudrboolean | null
filterobject
filter.unitstring | null

GET /api/v1/ketertelusuran/dds-pengiriman Preview

Per-shipment DDS pack with a mass balance allocation. Preview, mass balance (not physical segregation). For one CPO or palm kernel DO: the lot's production window (dari/sampai parameters; otherwise the DO's active mass-balance claim periods; otherwise the shipping mill's latest LHP production days up to the loading date that cover the shipment volume; if the LHP is insufficient, TRACE_JENDELA_PRODUKSI_HARI days up to the loading date), then each plot's share = FFB kg of that plot from completed weighbridge tickets in the window divided by all FFB kg in the window. Product allocated to a plot = share x shipment volume; FFB allocated = allocated product / window extraction rate. Readiness is SIAP (ready) only if all FFB kg in the window came from EUDR-ready plots. DOs other than CPO/PALM_KERNEL return 422; a DO whose shipping mill is outside the token's scope returns 404.

Token ability: trace:baca

ParameterInTypeDescription
nodoquerystring requiredShipping DO number for CPO or palm kernel.
max 35 chars
dariquerystring (date)Force the start of the production window YYYY-MM-DD (together with sampai, at most 92 days).
sampaiquerystring (date)Force the end of the production window YYYY-MM-DD.
unitquerystringUnit code within the token's scope (including child units). Outside the scope returns 403.
max 20 chars

Responses: 200 401 403 404 422 429

Response fields (200), 93 fields
FieldType
dataobject
data.pengirimanobject
data.pengiriman.nodostring
data.pengiriman.nokontrakstring
data.pengiriman.pembelistring | null
data.pengiriman.komoditasstring
CPO PALM_KERNEL
data.pengiriman.produkstring
CPO PK
data.pengiriman.kode_hsstring
1511.10 1207.10
data.pengiriman.negara_produksistring = ID
data.pengiriman.pksobject | null
data.pengiriman.pks.kodestring
data.pengiriman.pks.namastring | null
data.pengiriman.volume_kgnumber
data.pengiriman.basis_volumestring
REALISASI TARGET
data.pengiriman.tanggal_muatstring (date)
data.pengiriman.pelabuhan_muatstring | null
data.pengiriman.pelabuhan_bongkarstring | null
data.pengiriman.statusstring | null
data.metodeobject
data.metode.modelstring = MASS_BALANCE
data.metode.alokasistring = PROPORSIONAL_JENDELA_PRODUKSI
data.metode.segregasi_fisikboolean = false
data.metode.statusstring = PRATINJAU
data.metode.catatanstring
data.jendela_produksiobject
data.jendela_produksi.daristring (date)
data.jendela_produksi.sampaistring (date)
data.jendela_produksi.hariinteger
data.jendela_produksi.dasarstring
parameter klaim_mass_balance produksi_lhp jendela_hari
data.jendela_produksi.produksi_produk_kgnumber | null
data.jendela_produksi.tbs_diolah_kgnumber | null
data.jendela_produksi.rendemen_persennumber | null
data.jendela_produksi.sumber_rendemenstring | null
LHP KONFIGURASI
data.jendela_produksi.cakupan_volume_persennumber | null
data.input_tbsobject
data.input_tbs.jumlah_tiketinteger
data.input_tbs.total_kgnumber
data.input_tbs.terhubung_plot_kgnumber
data.input_tbs.lolos_kgnumber
data.input_tbs.siap_eudr_kgnumber
data.input_tbs.persen_tertelusur_plotnumber | null
data.input_tbs.persen_ttpnumber | null
data.input_tbs.persen_siap_eudrnumber | null
data.alokasiobject
data.alokasi.tertelusur_plot_kgnumber | null
data.alokasi.tidak_tertelusur_kgnumber | null
data.alokasi.siap_eudr_kgnumber | null
data.kesiapan_eudrobject
data.kesiapan_eudr.statusstring
SIAP BELUM_SIAP TIDAK_ADA_DATA
data.kesiapan_eudr.plot_kontributorinteger
data.kesiapan_eudr.plot_siapinteger
data.kesiapan_eudr.alasanarray<string>
data.klaim_mass_balancearray<object>
data.klaim_mass_balance[].tanggalstring (date) | null
data.klaim_mass_balance[].periodestring
data.klaim_mass_balance[].skemastring | null
data.klaim_mass_balance[].produkstring | null
data.klaim_mass_balance[].kgnumber
data.verifikasiobject | null
data.verifikasi.kodestring
data.verifikasi.urlstring (uri)
data.plotobject
data.plot.typestring = FeatureCollection
data.plot.featuresarray<object>
data.plot.features[].typestring = Feature
data.plot.features[].geometryGeoJSON Point | Polygon | null
data.plot.features[].propertiesobject
data.plot.features[].properties.kode_plotstring
data.plot.features[].properties.jenisstring
INTI PLASMA PIHAK3
data.plot.features[].properties.luas_hanumber
data.plot.features[].properties.tanggal_tanamstring (date) | null
data.plot.features[].properties.status_legalitasstring | null
data.plot.features[].properties.no_stdbstring | null
data.plot.features[].properties.jenis_alas_hakstring | null
data.plot.features[].properties.status_verifikasi_legalitasstring | null
data.plot.features[].properties.sertifikasistring | null
data.plot.features[].properties.nomor_sertifikatstring | null
data.plot.features[].properties.hasil_skrining_deforestasistring | null
data.plot.features[].properties.tanggal_skriningstring (date) | null
data.plot.features[].properties.sumber_skriningstring | null
MANUAL LAPISAN
data.plot.features[].properties.indikasi_skriningstring | null
TIDAK_TERINDIKASI PERLU_DITINJAU TERINDIKASI
data.plot.features[].properties.tbs_jendela_kgnumber
data.plot.features[].properties.porsi_persennumber
data.plot.features[].properties.alokasi_produk_kgnumber
data.plot.features[].properties.alokasi_tbs_kgnumber | null
data.plot.features[].properties.status_stdbstring | null
ADA BELUM TIDAK_BERLAKU
data.plot.features[].properties.geolokasi_lengkapboolean | null
data.plot.features[].properties.legalitas_terverifikasiboolean | null
data.plot.features[].properties.siap_eudrboolean | null
filterobject
filter.unitstring | null
filter.daristring (date) | null
filter.sampaistring (date) | null

GET /api/v1/ketertelusuran/lapisan Preview

EUDR screening reference layers (metadata). Preview. Layers uploaded by staff for EUDR screening: forest cover as of 31 Dec 2020, forest/protected areas, and peat, with source, licence, reference date, version, SHA-256 of the original file, and vertex counts before/after simplification. Geometry is not returned. Only active layers by default; semua=1 includes archived versions.

Token ability: trace:baca

ParameterInTypeDescription
unitquerystringUnit code within the token's scope (including child units). Outside the scope returns 403.
max 20 chars
semuaqueryboolean1 = include archived layers (old versions).

Responses: 200 401 403 422 429

Response fields (200), 22 fields
FieldType
dataarray<object>
data[].idinteger
data[].jenisstring
HUTAN_2020 KAWASAN_HUTAN GAMBUT
data[].namastring
data[].sumberstring
data[].lisensistring | null
data[].tanggal_datastring (date) | null
data[].seristring | null
data[].versiinteger
data[].aktifboolean
data[].unitstring | null
data[].formatstring | null
GEOJSON KML SHP
data[].sha256string | null
data[].jumlah_poligoninteger
data[].jumlah_titikinteger | null
data[].jumlah_titik_asalinteger | null
data[].toleransi_mnumber | null
data[].luas_hanumber | null
data[].diunggah_padastring (date-time) | null
filterobject
filter.unitstring | null
filter.semuaboolean

GET /api/v1/ketertelusuran/skrining Preview

Latest EUDR screening result per plot. Preview. Overlap of each plot with every active reference layer (area, percent of plot area, nearest distance to the layer boundary), indication status (TIDAK_TERINDIKASI = no indication, PERLU_DITINJAU = needs review, TERINDIKASI = overlap indicated, by threshold), layer versions used, screening time, and staff review. This is an INDICATION based on uploaded layers, not a deforestation-free statement. Unscreened plots appear with skrining null.

Token ability: trace:baca

ParameterInTypeDescription
unitquerystringUnit code within the token's scope (including child units). Outside the scope returns 403.
max 20 chars
statusquerystringTIDAK_TERINDIKASI, PERLU_DITINJAU, TERINDIKASI, or BELUM_DISKRINING (not screened).
TIDAK_TERINDIKASI PERLU_DITINJAU TERINDIKASI BELUM_DISKRINING
tinjauanquerystringBELUM (not reviewed), DITERIMA (accepted), or DITOLAK (rejected).
BELUM DITERIMA DITOLAK
per_halamanqueryintegerRows per page.
min 1 · max 500 · default 100
pagequeryintegerPage number, starting at 1.
min 1 · default 1

Responses: 200 401 403 422 429

Response fields (200), 51 fields
FieldType
dataarray<object>
data[].kode_plotstring
data[].jenisstring
INTI PLASMA PIHAK3
data[].unitstring | null
data[].luas_hanumber
data[].hasil_skriningstring | null
BELUM LOLOS TIDAK_LOLOS
data[].sumber_skriningstring | null
MANUAL LAPISAN
data[].skriningobject | null
data[].skrining.idinteger
data[].skrining.statusstring
TIDAK_TERINDIKASI PERLU_DITINJAU TERINDIKASI
data[].skrining.tinjauanstring
BELUM DITERIMA DITOLAK
data[].skrining.hasil_efektifstring
LOLOS TIDAK_LOLOS BELUM
data[].skrining.metodestring
POLIGON TITIK_RADIUS
data[].skrining.dijalankan_padastring (date-time) | null
data[].skrining.ditinjau_padastring (date-time) | null
data[].skrining.kedaluwarsaboolean
data[].skrining.catatanarray<string>
data[].skrining.lapisanarray<object>
data[].skrining.lapisan[].lapisan_idinteger
data[].skrining.lapisan[].jenisstring
data[].skrining.lapisan[].namastring
data[].skrining.lapisan[].versiinteger
data[].skrining.lapisan[].luas_tumpang_hanumber
data[].skrining.lapisan[].persennumber
data[].skrining.lapisan[].jarak_mnumber | null
data[].skrining.lapisan[].statusstring
TIDAK_TERINDIKASI PERLU_DITINJAU TERINDIKASI
data[].skrining.radius_mnumber | null
data[].skrining.luas_plot_hanumber
data[].skrining.alasan_tinjauanstring | null
data[].skrining.ada_buktiboolean
metaobject
meta.halamaninteger
meta.per_halamaninteger
meta.totalinteger
meta.halaman_terakhirinteger
meta.berikutnyastring (uri) | null
ringkasanobject
ringkasan.TIDAK_TERINDIKASIinteger
ringkasan.PERLU_DITINJAUinteger
ringkasan.TERINDIKASIinteger
ringkasan.BELUM_DISKRININGinteger
ambangobject
ambang.persennumber
ambang.hanumber
ambang.jarak_mnumber
ambang.radius_titik_mnumber | null
ambang.jarak_cari_mnumber
filterobject
filter.unitstring | null
filter.statusstring | null
filter.tinjauanstring | null

GET /api/v1/ketertelusuran/dds-pengiriman/eudr Preview

Per-shipment DDS GeoJSON for the EUDR Information System, with a validation report. Preview. One CPO or palm kernel DO becomes one FeatureCollection (one commodity/HS) per the EUDR GeoJSON File Description: one Feature per contributing plot (from the mass balance allocation of GET /ketertelusuran/dds-pengiriman), properties ProducerCountry "ID", ProductionPlace (plot code), Area (ha), and ProducerName (supplier name; tanpa_nama=1 to omit it). Plots <= 4 ha may be Points, > 4 ha must be Polygons. Validation: geometry type, closed ring, no self-intersection, no holes, no coinciding vertices after truncation to 6 decimals, polygon area matching the recorded area (EUDR_TOLERANSI_LUAS_PERSEN tolerance), all window FFB linked to plots, size <= 25 MB. geojson is null when validation fails. The official specification is listed in ringkasan.spesifikasi; test an upload to the EUDR Information System before relying on it.

Token ability: trace:baca

ParameterInTypeDescription
nodoquerystring requiredShipping DO number for CPO or palm kernel.
max 35 chars
tanpa_namaqueryboolean1 = omit ProducerName (smallholder personal data).
unitquerystringUnit code within the token's scope (including child units). Outside the scope returns 403.
max 20 chars

Responses: 200 401 403 404 422 429

Response fields (200), 40 fields
FieldType
dataobject
data.ringkasanobject
data.ringkasan.nodostring
data.ringkasan.komoditasstring
data.ringkasan.kode_hsstring
data.ringkasan.negara_produksistring = ID
data.ringkasan.volume_kgnumber
data.ringkasan.tanggal_muatstring (date)
data.ringkasan.pksstring | null
data.ringkasan.jendela_produksiobject
data.ringkasan.persen_tertelusur_plotnumber | null
data.ringkasan.persen_siap_eudrnumber | null
data.ringkasan.jumlah_fiturinteger
data.ringkasan.jumlah_plotinteger
data.ringkasan.indikasiobject
data.ringkasan.lapisanarray<string>
data.ringkasan.ukuran_bitainteger
data.ringkasan.statusstring = PRATINJAU
data.ringkasan.catatanstring
data.ringkasan.spesifikasiarray<object>
data.ringkasan.spesifikasi[].judulstring
data.ringkasan.spesifikasi[].urlstring (uri)
data.validasiobject
data.validasi.lolosboolean
data.validasi.galatarray<string>
data.validasi.peringatanarray<string>
data.validasi.galat_plotinteger
data.geojsonobject | null
data.geojson.typestring = FeatureCollection
data.geojson.featuresarray<object>
data.geojson.features[].typestring = Feature
data.geojson.features[].propertiesobject
data.geojson.features[].properties.ProducerNamestring
data.geojson.features[].properties.ProducerCountrystring = ID
data.geojson.features[].properties.ProductionPlacestring
data.geojson.features[].properties.Areanumber
data.geojson.features[].geometryGeoJSON Point | Polygon
filterobject
filter.unitstring | null
filter.tanpa_namaboolean
Rules

Paging, rate limits and errors

Paging

List endpoints are page-based: page starts at 1 and per_halaman is 1–500 (default 100; /batch has a fixed 50). meta holds halaman, total, halaman_terakhir and berikutnya (the next page URL, null on the last page).

Rate limits

INTEGRASI_API_PER_MENIT requests per minute per token (default 60), plus twice that per IP address including attempts with a wrong token. Every response carries X-RateLimit-Limit and X-RateLimit-Remaining; over the limit you get 429 with Retry-After in seconds.

Formats

Dates are YYYY-MM-DD, months YYYY-MM, timestamps ISO 8601 in Asia/Jakarta, amounts in rupiah with 2 decimals. Field names are Indonesian and stable within v1.

Status codes

CodeMeaning
200Success
401Token missing, wrong, revoked or expired
403Missing ability, unit outside scope, owner inactive or module switched off
404Not found or outside the token scope
405Method not allowed (e.g. POST to /jurnal)
409Batch already cancelled
422Invalid parameters; per-field details in errors
429Rate limit exceeded; wait for Retry-After

Errors are JSON with message; 422 adds errors per parameter. Messages follow the instance language.

Versioning

Versioning policy

  • The major version is in the path: /api/v1. Within v1 we only make compatible changes: new endpoints, new optional parameters and new response fields. Your client must ignore fields it does not know.
  • Incompatible changes (removing or renaming a field, changing its type or meaning) only ship as a new path such as /api/v2, running side by side with v1. Any retirement date for v1 is announced in the release notes before it takes effect.
  • Endpoints labelled Preview may still change within v1; every change is written in the CHANGELOG.
  • info.version in openapi.yaml (now 1.2.0) versions the document itself. Because each customer updates their own instance, the API on an instance matches the Sawitara version installed there.
Status

Honest status per endpoint

EndpointStatusNote
GET /jurnalAvailableIn the code and covered by contract tests.
GET /batchAvailableIn the code and covered by contract tests.
GET /batch/{id}AvailableIn the code and covered by contract tests.
POST /batch/{id}/diterimaAvailableIn the code and covered by contract tests.
GET /ketertelusuran/plotAvailableIn the code and covered by contract tests.
GET /ketertelusuran/kesiapanAvailableIn the code and covered by contract tests.
GET /ketertelusuran/ttpAvailableIn the code and covered by contract tests.
GET /ketertelusuran/ddsPreviewPeriod-based: the plots that supplied the mill in the production period, not physical segregation per shipment.
GET /ketertelusuran/dds-pengirimanPreviewPeriod-based: the plots that supplied the mill in the production period, not physical segregation per shipment.
GET /ketertelusuran/lapisanPreviewPeriod-based: the plots that supplied the mill in the production period, not physical segregation per shipment.
GET /ketertelusuran/skriningPreviewPeriod-based: the plots that supplied the mill in the production period, not physical segregation per shipment.
GET /ketertelusuran/dds-pengiriman/eudrPreviewPeriod-based: the plots that supplied the mill in the production period, not physical segregation per shipment.

Roadmap (not available yet)

These are plans, not endpoints. They are not in openapi.yaml paths and cannot be called.

  • Coming soon
    Tandan portal API for Sawitara Hub GET /api/v1/portal/*

    The Hub reads Tandan portal data per link without storing mill transactions (docs/EKOSISTEM.md, wave 2 item 2.2).

  • Coming soon
    PSR/KUR files for banks and financing partners

    Grower plot and legality data packs for submission through licensed partners. Endpoint shape not decided yet.

Download openapi.yaml (OpenAPI 3.1)

Need a test token?

Contact us to try the API on a demo instance with sample data before your IT team commits.