13 KiB
SoluTax IFS WIT API - Bruno Collection
A Bruno API collection for testing and interacting with the SoluTax IFS WIT API developed by PT Sarana Prima Telematika. This collection provides integration capabilities with Indonesia's tax system (DJP - Direktorat Jenderal Pajak) for electronic withholding tax slips (Bukti Potong).
Overview
| Item | Details |
|---|---|
| API Base URL | https://ifswit-solutax-ctas-dev.spt.co.id |
| Environment | Development (CTAS-DEV) |
| Authentication | JWT Token via Basic Auth |
| Tax Types | PPh 21, PPh A0, PPh A1 |
Tax Slip Types Supported
- PPh 21 - Employee income tax withholding (monthly/non-final)
- PPh A0 - Permanent employee monthly withholding
- PPh A1 - Permanent employee annual withholding
Prerequisites
- Bruno API Client - Download and install
- Valid credentials for SoluTax API (username/password)
- NPWP (Tax ID) for testing transactions
Quick Start
1. Clone and Open in Bruno
# Clone this repository
git clone <repository-url>
cd solutax_api
# Open in Bruno
# File > Open Folder > Select solutax_api directory
2. Configure Environment
- Open Bruno
- Navigate to Environments > solutax
- Configure your credentials:
username- Your API usernamepassword- Your API passwordpassphrase- Electronic signature passphrasenpwp- Your NPWP numbernpwp_pemilik- Employer NPWP
3. Get Authentication Token
- Select
token.bruin the collection - Click Send Request (or press
Ctrl+Enter) - Verify response contains
access_token - Token is automatically stored in environment variable
4. Create Your First Tax Slip
- Select PPh A0 > PPh A0 - Pengesahan Baru.bru
- Click Send Request
- Note the
nomorBupotandidBupotfrom response
5. Verify Status
- Select PPh A0 > ppha0-status.bru
- Click Send Request
- Confirm
statusBupotisNORMAL-DONE
Project Structure
solutax_api/
├── bruno.json # Bruno collection configuration
├── readme.md # This file
├── agents.md # AI agent documentation
├── spesifikasi.md # Full API specification (Indonesian)
├── token.bru # Authentication token request
├── package-lock.json # Node.js lock file
│
├── environments/
│ ├── solutax.bru # Environment variables template
│ ├── solutax.json # Environment configuration
│ └── solutax copy.json # Backup environment
│
├── PPh 21/ # PPh 21 (Monthly/Non-Final)
│ ├── PPh 21 - Pengesahan Baru.bru
│ ├── pph21-edit.bru
│ ├── pph21-cancel.bru
│ ├── pph21-status.bru
│ └── pph21-pdf.bru
│
├── PPh A0/ # PPh A0 (Permanent Employee Monthly)
│ ├── PPh A0 - Pengesahan Baru.bru
│ ├── ppha0-edit.bru
│ ├── ppha0-cancel.bru
│ ├── ppha0-status.bru
│ └── ppha0-pdf.bru
│
├── PPh A1/ # PPh A1 (Permanent Employee Annual)
│ ├── PPh A1 - Pengesahan Baru.bru
│ ├── ppha1-edit.bru
│ ├── ppha1-cancel.bru
│ ├── ppha1-status.bru
│ └── ppha1-pdf.bru
│
└── sample result/ # Sample API responses
├── token_result_sample.json
└── ppha0_new_result_sample.json
API Endpoints
Authentication
| Endpoint | Method | Description |
|---|---|---|
/auth/gettoken |
POST | Get JWT access token using Basic Auth |
PPh 21 (Monthly/Non-Final)
| Endpoint | Method | Description |
|---|---|---|
/ifs/api/wit/bulanan/new |
POST | Create and approve new PPh 21 slip |
/ifs/api/wit/bulanan/edit |
POST | Replace/modify existing PPh 21 slip |
/ifs/api/wit/cancel |
POST | Cancel a PPh 21 slip |
/ifs/api/wit/status |
POST | Check status of PPh 21 slip |
/ifs/api/wit/pdf |
POST | Download PDF of PPh 21 slip |
PPh A0 (Permanent Employee Monthly)
| Endpoint | Method | Description |
|---|---|---|
/ifs/api/wit/bulanan/new |
POST | Create and approve new PPh A0 slip |
/ifs/api/wit/bulanan/edit |
POST | Replace/modify existing PPh A0 slip |
/ifs/api/wit/cancel |
POST | Cancel a PPh A0 slip |
/ifs/api/wit/status |
POST | Check status of PPh A0 slip |
/ifs/api/wit/pdf |
POST | Download PDF of PPh A0 slip |
PPh A1 (Permanent Employee Annual)
| Endpoint | Method | Description |
|---|---|---|
/ifs/api/wit/tahunan/new |
POST | Create and approve new PPh A1 slip |
/ifs/api/wit/tahunan/edit |
POST | Replace/modify existing PPh A1 slip |
/ifs/api/wit/cancel |
POST | Cancel a PPh A1 slip |
/ifs/api/wit/status |
POST | Check status of PPh A1 slip |
/ifs/api/wit/pdf |
POST | Download PDF of PPh A1 slip |
Environment Variables
Configure these in Environments > solutax:
| Variable | Description | Required |
|---|---|---|
accessToken |
JWT authentication token | Yes (auto-generated) |
idpel |
Customer ID | Yes (from token response) |
requestID |
Unique request GUID | Yes (auto-generated) |
username |
API username | Yes |
password |
API password | Yes |
passphrase |
Electronic signature passphrase | Yes |
npwp |
Employee NPWP | Yes |
npwp_pemilik |
Employer NPWP | Yes |
nomorBupot |
Tax slip number | Yes (from create response) |
idBupot |
Tax slip ID (UUID) | Yes (from create response) |
Request/Response Patterns
Request Structure
All requests follow a consistent pattern:
{
"idPel": 12345,
"requestID": "uuid-string",
"dataBpA0": { ... }
}
Response Structure
{
"kodestatus": 200,
"keterangan": "Success",
"data": { ... },
"idPel": 12345
}
Common Status Codes
| Code | Meaning |
|---|---|
| 200 | Success |
| 401 | Unauthorized (invalid/expired token) |
| 500 | Server error (e.g., invalid User ID) |
Slip Status Values
| Status | Meaning |
|---|---|
NORMAL-DONE |
Original slip approved |
AMENDED |
Slip was replaced/modified |
CANCELLED-Done |
Slip was cancelled |
Testing Workflow
Complete Workflow Example
1. Get Token
└─> token.bru
→ accessToken set automatically
2. Create Slip
└─> PPh A0/PPh A0 - Pengesahan Baru.bru
→ nomorBupot and idBupot returned
3. Verify Status
└─> PPh A0/ppha0-status.bru
→ statusBupot = "NORMAL-DONE"
4. Download PDF (optional)
└─> PPh A0/ppha0-pdf.bru
→ Base64 PDF in response
5. Modify Slip (if needed)
└─> PPh A0/ppha0-edit.bru
→ New nomorBupot assigned
6. Cancel Slip (if needed)
└─> PPh A0/ppha0-cancel.bru
→ statusBupot = "CANCELLED-Done"
Happy Flow Diagram
flowchart TD
Start([Start]) --> Auth[Get Authentication Token]
Auth -->|POST /auth/gettoken| TokenAPI[Token API]
TokenAPI -->|Returns: access_token, idpel| TokenOK{Token Received?}
TokenOK -->|Yes| Create[Create Tax Slip]
TokenOK -->|No| Error1[Check Credentials]
Error1 --> Auth
Create --> CreateAPI{Choose Tax Slip Type}
CreateAPI -->|PPh 21| P21[POST /ifs/api/wit/bulanan/new]
CreateAPI -->|PPh A0| PA0[POST /ifs/api/wit/bulanan/new]
CreateAPI -->|PPh A1| PA1[POST /ifs/api/wit/tahunan/new]
P21 -->|Request: monthlyIncome, dataBp21| CreateSuccess{Success?}
PA0 -->|Request: monthlyIncome, dataBpA0| CreateSuccess
PA1 -->|Request: yearlyIncome, dataBpA1| CreateSuccess
CreateSuccess -->|Yes: status=1| Return1[Returns: nomorBupot, idBupot]
CreateSuccess -->|No: status=0| Error2[Handle Error]
Error2 --> Create
Return1 --> Status[Check Tax Slip Status]
Status --> StatusAPI{Choose Tax Slip Type}
StatusAPI -->|PPh 21| S21[POST /ifs/api/wit/status]
StatusAPI -->|PPh A0| SA0[POST /ifs/api/wit/status]
StatusAPI -->|PPh A1| SA1[POST /ifs/api/wit/status]
S21 -->|Request: taxSlipVerification| StatusOK{Status Received?}
SA0 -->|Request: taxSlipVerification| StatusOK
SA1 -->|Request: taxSlipVerification| StatusOK
StatusOK -->|statusBupot=NORMAL-DONE| Decision{What's Next?}
StatusOK -->|statusBupot=AMENDED| Decision
StatusOK -->|statusBupot=CANCELLED-Done| End1([End])
StatusOK -->|Error| Error3[Handle Error]
Error3 --> Status
Decision -->|Download PDF| PDF[Download PDF]
Decision -->|Modify Slip| Edit[Edit Tax Slip]
Decision -->|Cancel Slip| Cancel[Cancel Tax Slip]
Decision -->|Done| End2([End])
PDF --> PDFAPI{Choose Tax Slip Type}
PDFAPI -->|PPh 21| PF21[POST /ifs/api/wit/pdf]
PDFAPI -->|PPh A0| PFA0[POST /ifs/api/wit/pdf]
PDFAPI -->|PPh A1| PFA1[POST /ifs/api/wit/pdf]
PF21 -->|Returns: Base64 PDF| PDFOK{Downloaded?}
PFA0 -->|Returns: Base64 PDF| PDFOK
PFA1 -->|Returns: Base64 PDF| PDFOK
PDFOK -->|Yes| End3([End])
PDFOK -->|No| Error4[Handle Error]
Error4 --> PDF
Edit --> EditAPI{Choose Tax Slip Type}
EditAPI -->|PPh 21| E21[POST /ifs/api/wit/bulanan/edit]
EditAPI -->|PPh A0| EA0[POST /ifs/api/wit/bulanan/edit]
EditAPI -->|PPh A1| EA1[POST /ifs/api/wit/tahunan/edit]
E21 -->|Request: monthlyIncome, nomorBupot, idBupot| EditSuccess{Success?}
EA0 -->|Request: monthlyIncome, nomorBupot, idBupot| EditSuccess
EA1 -->|Request: yearlyIncome, nomorBupot, idBupot| EditSuccess
EditSuccess -->|Yes: status=1| Return2[Returns: new nomorBupot, new idBupot]
EditSuccess -->|No: status=0| Error5[Handle Error]
Error5 --> Edit
Return2 --> Status2[Check Status Again]
Status2 --> Status
Cancel --> CancelAPI{Choose Tax Slip Type}
CancelAPI -->|PPh 21| C21[POST /ifs/api/wit/cancel]
CancelAPI -->|PPh A0| CA0[POST /ifs/api/wit/cancel]
CancelAPI -->|PPh A1| CA1[POST /ifs/api/wit/cancel]
C21 -->|Request: taxSlipCancel| CancelSuccess{Success?}
CA0 -->|Request: taxSlipCancel| CancelSuccess
CA1 -->|Request: taxSlipCancel| CancelSuccess
CancelSuccess -->|Yes: status=1| Return3[Returns: status=1]
CancelSuccess -->|No: status=0| Error6[Handle Error]
Error6 --> Cancel
Return3 --> Status3[Verify Cancellation]
Status3 --> Status
style Start fill:#e1f5fe
style Auth fill:#e1f5fe
style Create fill:#fff3e0
style Status fill:#e8f5e9
style PDF fill:#f3e5f5
style Edit fill:#fff8e1
style Cancel fill:#ffebee
style End1 fill:#c8e6c9
style End2 fill:#c8e6c9
style End3 fill:#c8e6c9
style Error1 fill:#ffcdd2
style Error2 fill:#ffcdd2
style Error3 fill:#ffcdd2
style Error4 fill:#ffcdd2
style Error5 fill:#ffcdd2
style Error6 fill:#ffcdd2
Quick Reference: Happy Flow Steps
| Step | Action | Endpoint | Returns |
|---|---|---|---|
| 1 | Get Token | POST /auth/gettoken |
access_token, idpel |
| 2 | Create Slip | POST /ifs/api/wit/bulanan/new or /tahunan/new |
nomorBupot, idBupot |
| 3 | Check Status | POST /ifs/api/wit/status |
statusBupot |
| 4a | Download PDF | POST /ifs/api/wit/pdf |
Base64 PDF |
| 4b | Edit Slip | POST /ifs/api/wit/bulanan/edit or /tahunan/edit |
New nomorBupot |
| 4c | Cancel Slip | POST /ifs/api/wit/cancel |
Success confirmation |
Status Flow
stateDiagram-v2
[*] --> NORMAL_DONE: Pengesahan (New)
NORMAL_DONE --> AMENDED: Penggantian (Edit)
AMENDED --> AMENDED: Penggantian Lagi
NORMAL_DONE --> CANCELLED_DONE: Pembatalan (Cancel)
AMENDED --> CANCELLED_DONE: Pembatalan (Cancel)
CANCELLED_DONE --> [*]
Important Notes
-
Language: All API documentation and field names are in Indonesian (Bahasa Indonesia)
-
Environment: This is a development/DEV environment (CTAS-DEV) - do not use for production
-
Token Expiration: Monitor
expires_infield; tokens expire and require renewal -
NPWP Validation: Tax ID numbers (NPWP) are validated on all endpoints
-
Electronic Signature: Passphrase required for penandatangan (signatory) on create/edit/cancel operations
-
Pre-request Scripts: Some files auto-generate UUIDs for
requestIDusing JavaScript -
Post-response Scripts: Some files extract and store response values as environment variables
Documentation References
- spesifikasi.md - Complete API specification (Indonesian)
- agents.md - AI agent documentation
- Official Bruno Docs
- SoluTax API - API base URL
Troubleshooting
Token Issues
- 401 Unauthorized: Token expired or invalid → Get new token via
token.bru - 500 Server Error: Check username/password credentials
Slip Creation Issues
- Missing Fields: Ensure all required fields are filled in the request body
- NPWP Invalid: Verify NPWP format (15 digits with dots)
- Signature Error: Check passphrase is correct
PDF Download Issues
- Empty Response: Ensure slip status is
NORMAL-DONEbefore downloading - Invalid Base64: Response data field contains Base64-encoded PDF
License
Copyright © 2026 PT Sarana Prima Telematika. All rights reserved.
Contact
Developer: PT Sarana Prima Telematika
Version: 1.0
Year: 2026