The World Bank · DEC · Enterprise Surveys
suso is a safety-first Stata command that wraps the World Bank Survey Solutions
REST API. A small Java backend (suso.jar) performs the authenticated HTTPS calls
(every verb, including PATCH/DELETE), list endpoints load directly into a Stata
dataset, and destructive operations are guarded at two independent layers. It is built
for the WBES / B-READY / ISES fieldwork workflow and has zero third-party dependencies.
suso.ado Stata frontend (commands, options, safety, pagination)
suso.sthlp Stata help file (help suso)
suso.jar Java backend (HTTP + JSON, no dependencies)
src/ Java source (Json.java, Http.java, Stata.java)
build.sh Rebuild the jar (macOS / Linux)
build.bat Rebuild the jar (Windows)
- Stata with Java integration enabled, running on a Java 11+ runtime.
Verify with
suso doctor(it prints the JVM version and flags anything older). Java 11+ is required because Survey Solutions usesPATCHextensively (approve / reject / assign / archive / change-quantity / audio / criticality). suso.jarreachable on the adopath, or set explicitly withsuso config , jar().
The easy way, straight from GitHub inside Stata:
net install suso, from("https://raw.githubusercontent.com/arehman10/survey_solutions_api/main/install") replaceThis installs suso.ado, suso.sthlp and suso.jar in one step. If you are upgrading and Stata
complains or keeps running the old version, run ado uninstall suso and discard first.
Alternatively, install by hand: copy the three files to your Stata PLUS or PERSONAL folder (find them in Stata with
display c(sysdir_plus) and display c(sysdir_personal)):
suso.ado -> e.g. .../ado/plus/s/suso.ado
suso.sthlp -> e.g. .../ado/plus/s/suso.sthlp
suso.jar -> same folder, OR anywhere, then: suso config , jar("C:/path/suso.jar")
Then in Stata:
suso config , server(https://decpm11-surveys.worldbank.org) workspace(srilankainf) user(myapiuser)
suso doctor // environment + Java check
suso ping // connectivity + auth checkThe password can be typed (password()), or — better — exported as the
SUSO_PASSWORD environment variable before launching Stata, so it never enters your
command history. Configuration is held in this Stata session only and is never written
to disk. Survey Solutions' convention is to create an API user account and use
Basic auth (the default; auth(bearer) token() is also supported).
suso assignment list , all // -> dataset of assignments
suso interview list , status(Completed) all // -> dataset of interviews
suso export start , type(STATA) questionnaire(<guid>) qver(3) istatus(ApprovedBySupervisor)
suso export status , id(`=r(jobid)')
suso export download , id(`=r(jobid)') saving(ises.zip) replace
suso export get , type(STATA) saving(ises.zip) unzipw("pw") unzipto("data") replace // one-shot
suso interview reject , id(<uuid>) comment("GPS off-square; please revisit")
suso paradata get // pull the event log ...
suso paradata flags // ... and flag suspicious interviewsList commands replace the current dataset and return r(nobs), r(nvars) and (when the
server reports it) r(totalcount). ISO-8601 date columns are auto-converted to Stata
%tc. Single-object commands flatten JSON fields into r() (e.g. r(jobid),
r(exportstatus), r(canbedeleted)). All commands return r(http).
suso paradata turns the Survey Solutions event log into fieldwork-quality
intelligence, fully vectorized for multi-million-row files:
suso paradata get // export type(Paradata) -> poll -> download -> unzip -> load
suso paradata load , file("para.zip") // or reload a saved export offline (unzipw() if protected)
suso config , exportpw("...") // set the export-archive password once; all unzips use it
suso paradata report , saving("qc.html") // interactive one-page QC report: filter by enumerator,
// search questions, adjust night window + all flag thresholds live
suso paradata flags // per-interview red flags + interviewer league table
suso paradata skips , qx("qx.html") messages("review.txt") html("review.html") // supervisor action list: which gate
suso paradata check , qx("qx.html") data("main.dta") html("qc.html") status(approved) // audit the skip logic
suso paradata suite , qx("qx.html") data("main.dta") saving("qc_suite.html") // ALL THREE in one tabbed HTML
suso paradata check if lf_responsive==1, qx("qx.html") data("main.dta") ///
filters(lf_responsive region) html("qc.html") // restrict by any expression; live variable filters
// answers on disabled questions, item nonresponse, bad values
// was flipped, what it erased, what to do - email-ready
suso paradata timing , by(question) // slowest questions first (instrument diagnostics)
suso paradata skips // gate flips: skip-triggered answer-removal cascadestiming collapses events to one row per interview (or question/interviewer):
active time with inter-event gaps capped at gapmins(30) and Paused→Resumed
intervals zeroed, work sessions, median/p90 seconds per answer, fast-answer
share (< fastsecs(2)), night-work share (22:00–05:59 device-local time),
answer churn and pace. Supervisor/HQ events are excluded from timing when the
role column identifies interviewers (counts like rejections still use all
events). flags raises six screening flags per interview — S sustained
speeding, B answer bursts, T too short, N night work, C answer
churn, Z robust duration outlier (modified z on log active time) — prints
the worst offenders and an interviewer league table, and leaves a mergeable
one-row-per-interview dataset in memory. Both paradata layouts are handled
(timestamp_utc/tz_offset and the legacy timestamp/offset). Flags are
screening signals for review, not proof of fabrication.
skips is the skip check paradata supports: SuSo enforces enablement at
capture time, so instead of "answered while disabled" it detects gate
flips — runs of ≥ cascade(3) consecutive AnswerRemoved events within
window(60) seconds of an AnswerSet — names the trigger variable, ranks
the gates wiping the most answers, and merges 1:1 with the flags table.
Defense in depth — the Stata layer requires explicit opt-in, and the Java backend independently refuses any destructive request unless the Stata layer set its internal allow-flag. A bug on either side cannot silently destroy data.
| Operation | Guard |
|---|---|
interview delete, export cancel, assignment archive, user archive, workspace disable |
require , confirm |
workspace delete |
retype the exact name in iknowthis(name), plus an automatic pre-flight status check that refuses unless the server says the workspace can be deleted (override with force) |
Every destructive action is appended to an audit log
(default <PERSONAL>/suso_audit.log; change with suso config , auditfile()),
recording timestamp, user, server/workspace, action, target and HTTP status.
Pagination is automatic (, all) but capped at SUSO_MAXROWS rows (default 100,000) to
avoid accidental mega-pulls; raise it with suso config , maxrows() or use
suso export for bulk data.
Preferred: import the corporate root CA into the trust store of the Java runtime that
Stata uses. Find that runtime with suso doctor (it prints Java home), then:
keytool -importcert -alias wbg-root -file wbg-root.crt -cacerts
# (older layout: -keystore "<java.home>/lib/security/cacerts" -storepass changeit)Proxy:
suso config , proxyhost(proxy.worldbank.org) proxyport(8080)
suso config , proxyhost(...) proxyport(...) proxyuser(...) proxypass(...)Escape hatch (use with care): suso config , insecure disables TLS certificate and
hostname verification for the session. Each request then prints a warning. Prefer
importing the CA over running insecure.
suso raw /api/v1/settings/globalnotice // GET, flatten to r()
suso raw /api/v1/assignments , query(Limit=5&Offset=0) todata arraykey(Assignments)
suso raw /api/v1/interviews/<uuid> , method(DELETE) allowdestructiveA prebuilt dist/suso.jar ships with the package and works on any Stata with a Java 11+
runtime. Rebuild only if the prebuilt jar errors at runtime (e.g. a
NoSuchMethodError, which would indicate a different SFI on your Stata). You need a JDK
11+ and your Stata's sfi-api.jar (find your Stata folder with display c(sysdir_stata)):
./build.sh /path/to/sfi-api.jar # macOS / Linux
build.bat "C:\Program Files\Stata18\...\sfi-api.jar" # WindowsThe jar is compiled to Java 11 bytecode with no external dependencies and contains only
org/worldbank/suso/* (it relies on Stata's own com.stata.sfi at runtime).
- The REST interview-list endpoints are deprecated by Survey Solutions; for very large
interview pulls, GraphQL or
suso exportis recommended.susostill supports them and prints a one-line reminder. - Workspace-management endpoints are server-level on a standard Survey Solutions
deployment, so workspace commands default to the server root. If your server scopes
them under the workspace, add
, usews. - Questionnaire identities are passed as separate
questionnaire(<guid>)andqver(#)options; the backend assembles theguid$versionform internally.
If suso supports your research or fieldwork, please cite it:
Rehman, A. U. (2026). suso: A Survey Solutions API client for Stata (v1.6.0) [Computer software]. https://github.com/arehman10/survey_solutions_api
Issues and pull requests are welcome. For backend changes, please rebuild the jar from
src/ and confirm suso doctor / suso ping pass against a test workspace.
Thanks to Fahad Mirza (World Bank / CERP) for his insights and guidance, and for his self-contained Stata tooling (sparkta, wordcloud2), which helped shape the design of this package.
MIT © 2026 Attique Ur Rehman (The World Bank, Development Economics).
suso.ado sets SUSO_* globals → javacall org.worldbank.suso.Stata … → Http
(java.net.http) executes → Json parses → results are written back into the Stata
dataset / r() via the SFI, and the password global is scrubbed after every call.
suso.ado sets SUSO_* globals → javacall org.worldbank.suso.Stata run → Http
(java.net.http) executes → Json parses → results are written back into the Stata
dataset / r() via the SFI, and the password global is scrubbed after every call.