SIMPLE EFD / DEVELOPER SANDBOX / V2
Build your integration
with the modern API.
Test the same authentication, validation, exact decimal calculations and receipt writer used by the modern Simple EFD API.
Synthetic test data only. TRA is disabled. Receipts remain pending and are NOT A FISCAL RECEIPT. No real acceptance or verification code is generated.
Start in five steps
- Request sandbox access from your Simple EFD integration representative. You will receive a test email, password and branch ID for your own test company.
- Sign in with
POST /sessionusing your issued email and password. Save the returned bearer token for subsequent requests. - Discover your branch with
GET /branches, then preview a sale withPOST /receipts/preview. Save the returnedreview_hash. - Create the sale with
POST /receipts, anIdempotency-Keyand the preview hash. Repeat the same request with the same key to test safe replay. - Read the saved receipt and print snapshot, then revoke the token.
Sandbox base URL: https://sandbox.efdsimple.co.tz/api/v2
Use this HTTPS address from your application or API client. Your test credentials and data are separate from production.
Authenticate
Modern sign-in uses the test user's email and password. Subsequent requests use Authorization: Bearer TOKEN. The API returns real HTTP status codes and JSON errors.
POST /api/v2/session
Content-Type: application/json
Accept: application/json
{
"email": "YOUR_SANDBOX_EMAIL",
"password": "YOUR_SANDBOX_PASSWORD",
"device_name": "My API client"
}
A successful 201 reply contains token, token_type, expires_at, company_id and abilities. Tokens expire after 30 days. DELETE /session revokes the current token.
Preview, then create a receipt
Send sale facts to POST /receipts/preview. Replace the example branch ID with one from GET /branches. Prices include tax; money and quantity are decimal strings.
{
"branch_id": 1,
"customer_id_type": 6,
"customer_name": "SANDBOX BUYER",
"payment_type": "CASH",
"items": [{
"name": "SANDBOX ITEM",
"quantity": "1.00",
"unit_price": "118.00",
"discount": "0.00",
"tax_code": "A"
}]
}
Allowed sale values
Customer ID type
Send customer_id_type as an integer using this mapping:
| Value | Identification |
|---|---|
1 | TIN (Taxpayer Identification Number) |
2 | Driving licence |
3 | Voter ID |
4 | Passport |
5 | National identity (NID) |
6 | No ID |
For types 1–5, also send customer_id as a string of 5–30 characters. For type 6, omit it or send null. The example uses 6 because the test buyer has no ID.
Payment type
Send one of these exact, uppercase strings in payment_type:
| Value | Payment method |
|---|---|
CASH | Cash |
CHEQUE | Cheque |
CCARD | Credit card |
EMONEY | Electronic money, including mobile money |
INVOICE | Invoice |
Item tax code
Each item's tax_code accepts one of these exact strings. These rates describe the sandbox test registration:
| Value | Sandbox rate |
|---|---|
A | 18% for VAT-enabled test accounts |
C | 0% |
D | 0% |
E | 0% |
The server uses the account's registration and item code to calculate tax; a non-VAT test account does not charge VAT. Production tax classification and rates must follow the business's configured registration. Use the preview response for the calculated amounts.
GET /bootstrap?branch_id=YOUR_BRANCH_ID also returns id_types, payment_types and tax_codes for populating your application's choices.
The example produces 118.00 inclusive, 100.00 exclusive and 18.00 tax. Preview returns data.review_hash without saving a receipt.
Submit the same body to POST /receipts with these headers:
Authorization: Bearer TOKEN Content-Type: application/json Idempotency-Key: my-sandbox-sale-000001 X-Receipt-Review-Hash: HASH_FROM_PREVIEW
First create: 201, Idempotent-Replayed: false. Same key and facts: 200, same receipt ID, Idempotent-Replayed: true. Changed facts or review: 409. After a timeout, retry the original key and facts.
Available operations
| Resource | Operations |
|---|---|
/session | POST sign-in · GET identity · DELETE logout |
/branches/bootstrap?branch_id=… | GET assigned branches and sale readiness |
/customers/items | GET list/detail · POST create · PUT update · POST deactivate |
/receipts/preview/receipts | POST preview · POST create · GET history |
/receipts/{receipt}/receipts/{receipt}/print | GET saved detail and print snapshot |
/zreports/zreports/{zreport} | GET history/detail; initially empty |
Paths are relative to /api/v2. See the complete integration guide for request fields, pagination and responses.
Things to verify
- Invalid amounts return
422; duplicate sale retries never create a second receipt. - Another company's branch, buyer, item or receipt is inaccessible.
- Directory creates require a retry key. Updates/deactivation require the current
version; stale versions return409. - Expired or revoked tokens return
401. Rate limits return429; honorRetry-After.
History uses before_id; branches and directories use after_id. Follow the returned cursor while has_more is true. Limits are 1–100, default 50.
Sandbox boundaries
Registration, password reset, account changes, daily-close creation and TRA submission are unavailable. Every response is marked X-EFD-Environment: sandbox and X-TRA-Submitted: false. See the complete integration guide for request fields and error handling.
Moving to production
Once your integration has passed testing and your business has completed onboarding, Simple EFD will provide the production API address and separate credentials. Update your configuration to those issued values. Sandbox credentials and tokens do not grant production access. Submit only real business transactions to the production API.
Simple EFD · API integration sandbox