kra-etims-sdk 0.1.0__py3-none-any.whl → 0.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -32,10 +32,11 @@ class BaseClient:
32
32
  def _request(self, method, endpoint, data):
33
33
  url = self.base_url() + endpoint
34
34
  headers = self._headers(endpoint)
35
+ print(url, headers, data)
35
36
  return requests.request(method, url, json=data, headers=headers, timeout=30)
36
37
 
37
38
  def _headers(self, endpoint):
38
- if endpoint.endswith("/initialize"):
39
+ if endpoint.endswith("/selectInitOsdcInfo"):
39
40
  return {
40
41
  "Authorization": f"Bearer {self.auth.token()}",
41
42
  "Content-Type": "application/json",
kra_etims_sdk/client.py CHANGED
@@ -11,12 +11,12 @@ class EtimsClient(BaseClient):
11
11
  def _validate(self, data: dict, schema: str) -> dict:
12
12
  return self.validator.validate(data, schema)
13
13
 
14
- # -----------------------------
15
- # INITIALIZATION (POSTMAN-COMPLIANT)
16
- # -----------------------------
17
- def initialize(self, data: dict) -> dict:
18
- validated = self._validate(data, "initialization")
19
- return self.post("initialize", validated)
14
+ def select_init_osdc_info(self, data: dict) -> dict:
15
+ """
16
+ Initialize the OSCU device with KRA.
17
+ Returns cmcKey and device information.
18
+ """
19
+ return self.post("selectInitOsdcInfo", self._validate(data, "initialization"))
20
20
 
21
21
  # -----------------------------
22
22
  # BASIC DATA ENDPOINTS
kra_etims_sdk/schemas.py CHANGED
@@ -14,7 +14,7 @@ from pydantic import (
14
14
  # =========================================================
15
15
 
16
16
  TIN = Annotated[str, StringConstraints(min_length=1, max_length=20)]
17
- BHF = Annotated[str, StringConstraints(min_length=1, max_length=10)]
17
+ BHF = Annotated[str, StringConstraints(min_length=1, max_length=20)]
18
18
 
19
19
  YN = Annotated[str, StringConstraints(pattern="^[YN]$")]
20
20
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kra-etims-sdk
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: Python SDK for KRA eTIMS OSCU API
5
5
  Author: Emmanuel Bartile
6
6
  License: MIT
@@ -41,7 +41,7 @@ Dynamic: license-file
41
41
 
42
42
  A production-ready **Python SDK** for integrating with the Kenya Revenue Authority (KRA) **eTIMS OSCU** (Online Sales Control Unit) API. Built to match the official Postman collection specifications with strict header compliance, token management, and comprehensive Pydantic validation.
43
43
 
44
- > ⚠️ **Critical Note**: This SDK implements the **new OSCU specification** (KRA-hosted), *not* the legacy eTIMS API. OSCU requires device registration, headers, and `cmcKey` lifecycle management.
44
+ > ⚠️ **Critical Note**: This SDK implements the **new OSCU specification** (KRA-hosted), *not* the VSCU eTIMS API. OSCU requires device registration, headers, and `cmcKey` lifecycle management.
45
45
 
46
46
  ## Author
47
47
  **Bartile Emmanuel**
@@ -73,15 +73,15 @@ A production-ready **Python SDK** for integrating with the Kenya Revenue Authori
73
73
 
74
74
  ## Introduction to eTIMS OSCU
75
75
 
76
- KRA's **Electronic Tax Invoice Management System (eTIMS)** uses **OSCU** (Online Sales Control Unit) – a KRA-hosted software module that validates and signs tax invoices in real-time before issuance. Unlike legacy systems, OSCU requires:
76
+ KRA's **Electronic Tax Invoice Management System (eTIMS)** uses **OSCU** (Online Sales Control Unit) – a KRA-hosted software module that validates and signs tax invoices in real-time before issuance. Unlike VSCU, OSCU requires:
77
77
 
78
78
  - Pre-registered device serial numbers (`dvcSrlNo`)
79
79
  - Communication key (`cmcKey`) lifecycle management
80
80
  - Strict payload schema compliance per KRA specifications
81
81
 
82
- ### OSCU vs Legacy eTIMS
82
+ ### OSCU vs VSCU eTIMS
83
83
 
84
- | Feature | OSCU (This SDK) | Legacy eTIMS |
84
+ | Feature | OSCU (This SDK) | VSCU eTIMS |
85
85
  |---------|-----------------|--------------|
86
86
  | **Hosting** | KRA-hosted (cloud) | Self-hosted (on-premise) |
87
87
  | **Device Registration** | Mandatory pre-registration | Not required |
@@ -191,17 +191,18 @@ flowchart TD
191
191
  Before integration, you **MUST** complete these prerequisites:
192
192
 
193
193
  ### 1. Device Registration (MANDATORY)
194
- - Register OSCU device via [eTIMS Taxpayer Sandbox Portal](https://sbx.kra.go.ke)
194
+ - Register OSCU device via [eTIMS Taxpayer Production Portal](https://etims.kra.go.ke)
195
+ - Register OSCU device via [eTIMS Taxpayer Sandbox Portal](https://etims-sbx.kra.go.ke)
195
196
  - Obtain **approved device serial number** (`dvcSrlNo`)
196
197
  - ⚠️ **Dynamic/unregistered device serials fail with `resultCd: 901`** ("It is not valid device")
197
198
 
198
199
  ### 2. Communication Key Lifecycle
199
200
  ```python
200
201
  # 1. Initialize FIRST (returns cmcKey)
201
- response = etims.initialize({
202
+ response = etims.select_init_osdc_info({
202
203
  "tin": config.oscu["tin"],
203
204
  "bhfId": config.oscu["bhf_id"],
204
- "dvcSrlNo": "dvcv1130", # KRA-approved serial
205
+ "dvcSrlNo": config.oscu["device_serial"], # KRA-approved serial
205
206
  })
206
207
 
207
208
  # 2. Extract cmcKey (sandbox returns at root level)
@@ -304,19 +305,19 @@ config = KraEtimsConfig(
304
305
  },
305
306
 
306
307
  api={
307
- "sandbox": {"base_url": "https://sbx.kra.go.ke/etims-oscu/api/v1".strip()},
308
- "production": {"base_url": "https://api.developer.go.ke/etims-oscu/api/v1".strip()}
308
+ "sandbox": {"base_url": "https://etims-api-sbx.kra.go.ke/etims-api".strip()},
309
+ "production": {"base_url": "https://etims-api.kra.go.ke/etims-api".strip()}
309
310
  },
310
311
 
311
312
  oscu={
312
313
  "tin": os.environ["KRA_TIN"],
313
- "bhf_id": os.environ["KRA_BHF_ID"],
314
- "cmc_key": "", # Set AFTER initialization
314
+ "bhf_id": os.environ["KRA_BHF_ID"],
315
+ "cmc_key": os.environ["CMC_KEY"] # Set AFTER initialization
315
316
  },
316
317
 
317
318
  endpoints={
318
319
  # INITIALIZATION (ONLY endpoint without tin/bhfId/cmcKey headers)
319
- "initialize": "/initialize",
320
+ "selectInitOsdcInfo": "/selectInitOsdcInfo",
320
321
 
321
322
  # DATA MANAGEMENT
322
323
  "selectCodeList": "/selectCodeList",
@@ -355,7 +356,7 @@ config = KraEtimsConfig(
355
356
  ```
356
357
 
357
358
  > 💡 **Production URL Note**:
358
- > Production base URL is `https://api.developer.go.ke/etims-oscu/api/v1` (NOT `kra.go.ke`)
359
+ > Production base URL is `https://etims-api.kra.go.ke/etims-api` (NOT `https://etims-api-sbx.kra.go.ke/etims-api`)
359
360
 
360
361
  ---
361
362
 
@@ -386,12 +387,11 @@ except AuthenticationException as e:
386
387
  try:
387
388
  # ⚠️ MUST use KRA-approved device serial (NOT dynamic!)
388
389
  # Common sandbox test value (if pre-provisioned by KRA):
389
- device_serial = "dvcv1130" # REPLACE with your approved serial
390
390
 
391
- response = etims.initialize({
391
+ response = etims.select_init_info({
392
392
  "tin": config.oscu["tin"],
393
393
  "bhfId": config.oscu["bhf_id"],
394
- "dvcSrlNo": device_serial.strip(),
394
+ "dvcSrlNo": config.oscu["device_serial"],
395
395
  })
396
396
 
397
397
  # Extract cmcKey (sandbox returns at root level)
@@ -506,7 +506,7 @@ except ApiException as e:
506
506
 
507
507
  | Category | Purpose | Endpoints |
508
508
  |----------|---------|-----------|
509
- | **Initialization** | Device registration & cmcKey acquisition | `initialize` |
509
+ | **Initialization** | Device registration & cmcKey acquisition | `select_init_info` |
510
510
  | **Data Management** | Retrieve standard codes & master data | `select_code_list`, `select_item_cls_list`, `select_bhf_list`, `select_taxpayer_info`, `select_customer_list`, `select_notice_list` |
511
511
  | **Branch Management** | Manage branch offices & users | `branch_insurance_info`, `branch_user_account`, `branch_send_customer_info` |
512
512
  | **Item Management** | Item master data | `save_item`, `item_info` |
@@ -720,7 +720,7 @@ KRA mandates successful completion of automated tests before verification:
720
720
  3. Deploy directly to production environment
721
721
  4. No SLA execution required
722
722
 
723
- > 💡 **Production URL**: `https://api.developer.go.ke/etims-oscu/api/v1`
723
+ > 💡 **Production URL**: `https://etims-api.kra.go.ke/etims-api`
724
724
  > ⚠️ **Never use sandbox credentials in production** – KRA monitors environment separation strictly
725
725
 
726
726
  ---
@@ -0,0 +1,12 @@
1
+ kra_etims_sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ kra_etims_sdk/auth.py,sha256=_fRE1QhRWjOsHrd8ds9RAu_0kPrR4XFsl8KYrLf1avk,1812
3
+ kra_etims_sdk/base_client.py,sha256=oWZhLWj7PCECW_tGim6U7venX7_OerkvePIyvXw0OCg,2266
4
+ kra_etims_sdk/client.py,sha256=CEfk-DbVbTmSi-Q6pAgS3MHnofb5ejwnyYN-btXyNHA,3853
5
+ kra_etims_sdk/exceptions.py,sha256=Kcwvh7dbsxZ5X2iHcW9p8bxWai2FiZHL6Jb7904u9HE,630
6
+ kra_etims_sdk/schemas.py,sha256=mZEUAIDwrlG8NaE6rpPMHXFoNU2q2NOLj7YBM-gICAc,4585
7
+ kra_etims_sdk/validator.py,sha256=JDBZo5GXuczibIia3XSE_ytjJ5OzqQ8e7QT9Fh7hmtk,1168
8
+ kra_etims_sdk-0.1.2.dist-info/licenses/LICENSE,sha256=Fl2vp3H5372qSizz8VOT8f3H1bSxSqY-YZ8Qb4N25pM,1067
9
+ kra_etims_sdk-0.1.2.dist-info/METADATA,sha256=4jRq84d05msYleJoxAgkpJYv0kZfwufdRKGqmIUsW2U,29550
10
+ kra_etims_sdk-0.1.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
11
+ kra_etims_sdk-0.1.2.dist-info/top_level.txt,sha256=LRqz__wcOsq5Ds_evpPLZ9yHdxvIDCIu_oGSW3fRcTY,14
12
+ kra_etims_sdk-0.1.2.dist-info/RECORD,,
@@ -1,12 +0,0 @@
1
- kra_etims_sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- kra_etims_sdk/auth.py,sha256=_fRE1QhRWjOsHrd8ds9RAu_0kPrR4XFsl8KYrLf1avk,1812
3
- kra_etims_sdk/base_client.py,sha256=Wn2esjMcjXsw6wPHIdXp0wmvoKSXWfMg7DLFQpsM8PA,2224
4
- kra_etims_sdk/client.py,sha256=3LrzXUupVMKQ3efupWJr6_wpK-RAjCYgEGYQFBoJHNM,3861
5
- kra_etims_sdk/exceptions.py,sha256=Kcwvh7dbsxZ5X2iHcW9p8bxWai2FiZHL6Jb7904u9HE,630
6
- kra_etims_sdk/schemas.py,sha256=InPS4VWmL0ssUKxUvVzpLjbivXARDb_I0iVuCdjiEoA,4585
7
- kra_etims_sdk/validator.py,sha256=JDBZo5GXuczibIia3XSE_ytjJ5OzqQ8e7QT9Fh7hmtk,1168
8
- kra_etims_sdk-0.1.0.dist-info/licenses/LICENSE,sha256=Fl2vp3H5372qSizz8VOT8f3H1bSxSqY-YZ8Qb4N25pM,1067
9
- kra_etims_sdk-0.1.0.dist-info/METADATA,sha256=HgxEf3SEo_Y__2D8maWVDQbZ8u7fs8tEOz3vREV81co,29440
10
- kra_etims_sdk-0.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
11
- kra_etims_sdk-0.1.0.dist-info/top_level.txt,sha256=LRqz__wcOsq5Ds_evpPLZ9yHdxvIDCIu_oGSW3fRcTY,14
12
- kra_etims_sdk-0.1.0.dist-info/RECORD,,