# 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](https://www.usebruno.com/) - Download and install - Valid credentials for SoluTax API (username/password) - NPWP (Tax ID) for testing transactions ## Quick Start ### 1. Clone and Open in Bruno ```bash # Clone this repository git clone cd solutax_api # Open in Bruno # File > Open Folder > Select solutax_api directory ``` ### 2. Configure Environment 1. Open Bruno 2. Navigate to **Environments** > **solutax** 3. Configure your credentials: - `username` - Your API username - `password` - Your API password - `passphrase` - Electronic signature passphrase - `npwp` - Your NPWP number - `npwp_pemilik` - Employer NPWP ### 3. Get Authentication Token 1. Select `token.bru` in the collection 2. Click **Send Request** (or press `Ctrl+Enter`) 3. Verify response contains `access_token` 4. Token is automatically stored in environment variable ### 4. Create Your First Tax Slip 1. Select **PPh A0** > **PPh A0 - Pengesahan Baru.bru** 2. Click **Send Request** 3. Note the `nomorBupot` and `idBupot` from response ### 5. Verify Status 1. Select **PPh A0** > **ppha0-status.bru** 2. Click **Send Request** 3. Confirm `statusBupot` is `NORMAL-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: ```json { "idPel": 12345, "requestID": "uuid-string", "dataBpA0": { ... } } ``` ### Response Structure ```json { "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" ``` ## Important Notes 1. **Language**: All API documentation and field names are in Indonesian (Bahasa Indonesia) 2. **Environment**: This is a development/DEV environment (CTAS-DEV) - do not use for production 3. **Token Expiration**: Monitor `expires_in` field; tokens expire and require renewal 4. **NPWP Validation**: Tax ID numbers (NPWP) are validated on all endpoints 5. **Electronic Signature**: Passphrase required for penandatangan (signatory) on create/edit/cancel operations 6. **Pre-request Scripts**: Some files auto-generate UUIDs for `requestID` using JavaScript 7. **Post-response Scripts**: Some files extract and store response values as environment variables ## Documentation References - [spesifikasi.md](spesifikasi.md) - Complete API specification (Indonesian) - [agents.md](agents.md) - AI agent documentation - [Official Bruno Docs](https://docs.usebruno.com/) - [SoluTax API](https://ifswit-solutax-ctas-dev.spt.co.id) - 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-DONE` before 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