Summary
In v2.1.4 (current release), every method in every API class contains a literal duplicate self.api_client.call_api(...) invocation, causing every API call to fire its HTTP request to the FIC server twice. The second response overwrites the first one, so the SDK only returns one — but both hit the server.
Source
In fattureincloud_python_sdk/api/issued_documents_api.py at lines 129–137 (create_issued_document method) and at identical patterns throughout every other method:
https://github.com/fattureincloud/fattureincloud-python-sdk/blob/v2.1.4/fattureincloud_python_sdk/api/issued_documents_api.py#L129-L137
response_data = self.api_client.call_api(
*_param,
_request_timeout=_request_timeout
)
response_data = self.api_client.call_api( # ← identical duplicate; same args, same target variable
*_param,
_request_timeout=_request_timeout
)
response_data.read()
The pattern repeats throughout the SDK:
issued_documents_api.py: 108 call_api( invocations (54 method variants × 2 each)
info_api.py: 96 (48 × 2)
received_documents_api.py: 96 (48 × 2)
settings_api.py: 90 (45 × 2)
receipts_api.py: 42 (21 × 2)
taxes_api.py: 42 (21 × 2)
- … same pattern in every
api/*.py
Reproduction
import logging
logging.basicConfig(level=logging.DEBUG)
import fattureincloud_python_sdk as fic
configuration = fic.Configuration(access_token="<your token>")
with fic.ApiClient(configuration) as client:
fic.UserApi(client).list_user_companies()
urllib3.connectionpool debug output shows two GET /user/companies requests for one method call:
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): api-v2.fattureincloud.it:443
DEBUG:urllib3.connectionpool:https://api-v2.fattureincloud.it:443 "GET /user/companies HTTP/1.1" 200 None
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (2): api-v2.fattureincloud.it:443
DEBUG:urllib3.connectionpool:https://api-v2.fattureincloud.it:443 "GET /user/companies HTTP/1.1" 200 None
Cross-verified against the FIC server-side audit log (Impostazioni → Sviluppatore → app → "Mostra log") — both requests appear there with identical timestamps, confirming this is not a client-side logging artifact.
Impact
| Method type |
Effect of the duplicate call |
| GET (idempotent) |
2× requests; identical 200 responses; wastes quota & bandwidth but no functional bug |
POST create_* |
Creates two resources per script call. Verified for IssuedDocumentsApi.create_issued_document — calling it once produces two issued documents (visible in FIC and via subsequent list) with consecutive doc IDs. |
DELETE delete_* |
First request 200 (deletes the resource); second request 404 (already gone). The SDK returns the 404 to the caller, so user code may log "delete failed" while the resource is actually deleted server-side. Real and confusing failure mode. |
PUT modify_* |
Both succeed; usually idempotent in practice. |
The DELETE behavior is especially confusing because the SDK's response actively misleads callers about what happened on the server.
Suggested fix
This looks like a codegen template issue — the SDK files are clearly generated. The fix is one line in whichever Mustache/Jinja template emits the response_data = self.api_client.call_api(...) block: remove the duplicate emission. Then re-generate.
Happy to send a PR if you point me at the template repo (presumably an openapi-generator config or a custom template repo).
Workaround for users hitting this in the meantime
Monkey-patch ApiClient.call_api to dedupe identical back-to-back invocations on the same instance within a small time window (the duplicates in practice fire ~260 ms apart). Apply at import time, before any Api class is instantiated.
import functools, hashlib, time
from fattureincloud_python_sdk.api_client import ApiClient
_orig = ApiClient.call_api
@functools.wraps(_orig)
def _patched(self, method, url, header_params=None, body=None, post_params=None, _request_timeout=None):
key = (method, url, hashlib.sha1((body or b"") if isinstance(body, (bytes, bytearray)) else str(body or "").encode()).hexdigest())
now = time.monotonic()
cache = getattr(self, "__patch_last", None)
if cache and cache[0] == key and (now - cache[1]) < 2.0:
return cache[2] # collapse SDK's duplicate to one wire request
resp = _orig(self, method, url, header_params, body, post_params, _request_timeout)
self.__patch_last = (key, now, resp)
return resp
ApiClient.call_api = _patched
Thanks for maintaining the SDK!
Summary
In v2.1.4 (current release), every method in every API class contains a literal duplicate
self.api_client.call_api(...)invocation, causing every API call to fire its HTTP request to the FIC server twice. The second response overwrites the first one, so the SDK only returns one — but both hit the server.Source
In
fattureincloud_python_sdk/api/issued_documents_api.pyat lines 129–137 (create_issued_documentmethod) and at identical patterns throughout every other method:https://github.com/fattureincloud/fattureincloud-python-sdk/blob/v2.1.4/fattureincloud_python_sdk/api/issued_documents_api.py#L129-L137
The pattern repeats throughout the SDK:
issued_documents_api.py: 108call_api(invocations (54 method variants × 2 each)info_api.py: 96 (48 × 2)received_documents_api.py: 96 (48 × 2)settings_api.py: 90 (45 × 2)receipts_api.py: 42 (21 × 2)taxes_api.py: 42 (21 × 2)api/*.pyReproduction
urllib3.connectionpooldebug output shows twoGET /user/companiesrequests for one method call:Cross-verified against the FIC server-side audit log (Impostazioni → Sviluppatore → app → "Mostra log") — both requests appear there with identical timestamps, confirming this is not a client-side logging artifact.
Impact
create_*IssuedDocumentsApi.create_issued_document— calling it once produces two issued documents (visible in FIC and via subsequent list) with consecutive doc IDs.delete_*modify_*The DELETE behavior is especially confusing because the SDK's response actively misleads callers about what happened on the server.
Suggested fix
This looks like a codegen template issue — the SDK files are clearly generated. The fix is one line in whichever Mustache/Jinja template emits the
response_data = self.api_client.call_api(...)block: remove the duplicate emission. Then re-generate.Happy to send a PR if you point me at the template repo (presumably an openapi-generator config or a custom template repo).
Workaround for users hitting this in the meantime
Monkey-patch
ApiClient.call_apito dedupe identical back-to-back invocations on the same instance within a small time window (the duplicates in practice fire ~260 ms apart). Apply at import time, before any Api class is instantiated.Thanks for maintaining the SDK!