✅ Recommended practices

1. Manage access_token efficiently

It’s crucial to manage the access_token obtained from /auth efficiently to avoid rate limiting and IP bans. This is especially important when processing high volumes of documents.

Best practice: Store the access_token for 60 minutes and reuse it for all subsequent document issuances. Do not request a new token for each document creation.

Example: Token management

1// Request to /auth endpoint
2POST https://api-billing.koywe.com/V1/auth
3Content-Type: application/json
4
5{
6 "grant_type": "password",
7 "client_id": "your_client_id",
8 "client_secret": "your_client_secret",
9 "username": "your_username",
10 "password": "your_password"
11}

Response:

1{
2 "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
3 "token_type": "Bearer",
4 "expires_in": 3600
5}

Implementation recommendation:

  • Cache the access_token with a TTL of 60 minutes (3600 seconds)
  • Reuse the same token for all API calls within this period
  • Only request a new token when the current one expires or is about to expire
  • This prevents excessive authentication requests that could trigger rate limiting on your IP

2. IP whitelisting (for high volumes)

If your system processes more than 5 documents per second, you should provide us your IP addresses for whitelisting to prevent potential blocks.

Why this is important:

  • High-volume traffic may trigger security measures
  • Whitelisting ensures your IPs are not blocked
  • Contact support to add your IPs to the whitelist

Action required: Contact your sales representative with:

  • Your production IP addresses
  • Expected volume (documents per second)
  • Account information

3. Respect rate limits and handle 429 errors

Always respect the rate limits defined in your contract. If you exceed the rate limit, you will receive a 429 Too Many Requests error.

Best practices:

  1. Monitor your request rate: Do not exceed the rate limit specified in your contract
  2. Implement exponential backoff: When receiving a 429 error, wait at least 30 seconds before retrying
  3. Handle retries gracefully: Implement a retry mechanism with proper delays

Example: Handling 429 errors

1// Error response when rate limit is exceeded
2HTTP/1.1 429 Too Many Requests
3Content-Type: application/json

Implementation recommendation:

1# Pseudo-code example
2def create_document_with_retry(document_data, access_token):
3 max_retries = 3
4 backoff_seconds = 30
5
6 for attempt in range(max_retries):
7 try:
8 response = post_document(document_data, access_token)
9 return response
10 except HTTPError as e:
11 if e.status_code == 429:
12 if attempt < max_retries - 1:
13 time.sleep(backoff_seconds)
14 continue
15 else:
16 raise Exception("Rate limit exceeded after retries")
17 else:
18 raise

4. Prevent duplicates using reference field

To avoid duplicate document creation when retrying requests, use the reference field with reference_code 5 (reference to other non-tax documents) containing your internal transaction ID.

Sending a document with reference

When creating a document, include the references array with your internal transaction ID:

1{
2 "header": {
3 "account_id": 16268,
4 "document_type_id": "96",
5 "received_issued_flag": 0,
6 "issue_date": "2025-02-03",
7 "issuer_tax_id_code": "20610383727",
8 "issuer_tax_id_type": "PE-RUC",
9 "issuer_legal_name": "Your Company Name",
10 "issuer_address": "Your Address",
11 "issuer_district": "Your District",
12 "issuer_city": "Your City",
13 "issuer_department": "Your Department",
14 "issuer_country_id": "83",
15 "issuer_phone": "Your Phone",
16 "issuer_activity": "Your Activity",
17 "issuer_postalcode": "12345456",
18 "receiver_tax_id_code": "20473731828",
19 "receiver_tax_id_type": "PE-RUC",
20 "receiver_legal_name": "Receiver Name",
21 "receiver_address": "Receiver Address",
22 "receiver_district": "Receiver District",
23 "receiver_city": "Receiver City",
24 "receiver_department": "Receiver Department",
25 "receiver_country_id": "83",
26 "receiver_phone": "Receiver Phone",
27 "receiver_activity": "Receiver Activity",
28 "receiver_postalcode": "12343456",
29 "payment_conditions": "0",
30 "currency_id": 7,
31 "additional": {
32 "pe_header": {
33 "signature_id": "ASDFG",
34 "operation_type": "0101"
35 }
36 }
37 },
38 "details": [
39 {
40 "quantity": 1,
41 "line_description": "Product Description",
42 "unit_measure": "NIU",
43 "unit_price": 1000,
44 "long_description": "Detailed description",
45 "modifier_amount": 0,
46 "total_taxes": 180,
47 "modifier_percentage": 0,
48 "total_amount_line": 1180,
49 "sku": "SKU001",
50 "taxes": [
51 {
52 "tax_type_id": "413",
53 "tax_percentage": 18,
54 "tax_amount": 180
55 }
56 ]
57 }
58 ],
59 "references": [
60 {
61 "reference_number": "TXN-2025-001234",
62 "reference_code": 5,
63 "description": "Internal transaction ID"
64 }
65 ],
66 "totals": {
67 "net_amount": 1000,
68 "taxes_amount": 180,
69 "total_amount": 1180
70 }
71}

Key points:

  • reference_number: Your internal transaction ID (e.g., “TXN-2025-001234”)
  • reference_code: 5 (reference to other non-tax documents)

Searching documents by reference

To check if a document with a specific reference already exists, use the GET /documents endpoint with query parameters:

Endpoint: GET https://api-billing.koywe.com/V1/documents

Query parameters:

  • reference_code: 5 (to filter by reference code)
  • reference_number: Your internal transaction ID (e.g., TXN-2025-001234)

Example request:

$GET https://api-billing.koywe.com/V1/documents?reference_code=5&reference_number=TXN-2025-001234
>Authorization: Bearer <your_access_token>
>Accept: */*

Example response:

1{
2 "data": [
3 {
4 "document_id": 12345,
5 "header": {
6 "document_number": "F001-000123",
7 "issue_date": "2025-02-03",
8 ...
9 },
10 "references": [
11 {
12 "reference_number": "TXN-2025-001234",
13 "reference_code": 5,
14 "description": "Internal transaction ID"
15 }
16 ],
17 ...
18 }
19 ],
20 "pagination": {
21 "total": 1,
22 "per_page": 20,
23 "current_page": 1
24 }
25}

Implementation recommendation when you are retrying to issue:

  1. Before creating a document, check if a document with your internal transaction ID already exists (DO NOT include this validation on every common issuance or you will face performance issues)
  2. If found, use the existing document_id instead of creating a duplicate
  3. If not found, proceed with document creation including the reference field
  4. This ensures idempotency and prevents duplicate documents

Summary: Follow these best practices for reliable document issuance: cache your access token, whitelist your IPs (if processing high volumes), respect rate limits with proper backoff, and use reference fields to prevent duplicates.