I’m integrating ERPNext (Frappe Framework) with the Pakistan FBR DI API.
I’m facing a strange issue:
When I send the request using cURL, the invoice is accepted successfully.
When I send the exact same payload through ERPNext using Python requests, the API returns:
500 Internal Server Error
1. Working cURL Command
This request succeeds and FBR accepts the invoice:
curl -X POST "https://gw.fbr.gov.pk/di_data/v1/di/postinvoicedata_sb" \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-H "Accept: */*" \
-H "Accept-Encoding: gzip, deflate, br" \
-H "User-Agent: Mozilla/5.0" \
-d '{
"invoiceType": "",
"invoiceDate": "",
"sellerNTNCNIC": "",
"sellerBusinessName": "",
"sellerAddress": "",
"sellerProvince": "",
"buyerNTNCNIC": "",
"buyerBusinessName": "",
"buyerAddress": "",
"buyerProvince": "",
"invoiceRefNo": "",
"scenarioId": "SN001",
"buyerRegistrationType": "",
"items": [{
"hsCode": "4819.1000",
"productDescription": "2Sum 2g Injection TP New 2D R#06",
"rate": "18%",
"uoM": "Numbers,pieces,units",
"quantity": 2500.0,
"totalValues": 2767.1,
"valueSalesExcludingST": 2345.0,
"fixedNotifiedValueOrRetailPrice": 0,
"salesTaxApplicable": 422.1,
"salesTaxWithheldAtSource": 0,
"extraTax": "",
"furtherTax": 0.0,
"sroScheduleNo": "",
"fedPayable": 0,
"discount": 0.0,
"saleType": "Goods at standard rate (default)",
"sroItemSerialNo": ""
}]
}'
This works perfectly.
2. Failing ERPNext / Python requests code
Inside ERPNext custom app (fbr_api.py), this block is used:
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate, br",
"User-Agent": "Mozilla/5.0"
}
payload = {... same JSON structure as curl ...}
response = requests.post(
api_url,
headers=headers,
json=payload,
verify=False
)
response.raise_for_status()
This results in:
500 Server Error: Internal Server Error
4. The payload logged inside ERPNext is IDENTICAL to the working cURL payload
The headers also match.
Yet ERPNext → FBR always gives a 500 error, while cURL → FBR works.
Question:
Why does the API accept the exact same request via cURL but produces 500 error when sent using Python requests inside ERPNext (Frappe)?
Is there something different about:
encoding?
gzip handling?
SSL?
how Python constructs the raw body?
any hidden headers FBR expects?
Any insight would be greatly appreciated.
✔ Additional notes:
ERPNext is running Python 3.10
API endpoint is the official DI API sandbox
Token is valid
Same token + same payload always work in curl