python
Python requests sample
A Python example using the requests library to call a sandbox endpoint securely, with guidance on environment variables, session reuse, timeouts, retries and structured error handling.
Why requests
requests remains the most widely used HTTP client in the Python ecosystem and integrates cleanly with the os.environ-based configuration pattern most fintech and data teams already use for credentials. If you are building an async service, httpx is a drop-in-flavored alternative with the same design philosophy.
Environment variables
Load secrets from the environment rather than hard-coding them, and keep a .env.example (with placeholder values only) alongside a real .env that is git-ignored:
PROCESSOR_BASE_URL=https://sandbox.example.com
PROCESSOR_API_KEY=sk_sandbox_xxxxxxxxxxxxxxxx
Python example
import os
import requests
from requests.adapters import HTTPAdapter, Retry
session = requests.Session()
retries = Retry(total=3, backoff_factor=0.5, status_forcelist=[502, 503, 504])
session.mount("https://", HTTPAdapter(max_retries=retries))
base_url = os.environ["PROCESSOR_BASE_URL"]
api_key = os.environ["PROCESSOR_API_KEY"]
try:
response = session.get(
f"{base_url}/v1/ping",
headers={
"Authorization": f"Bearer {api_key}",
"Accept": "application/json",
},
timeout=10,
)
response.raise_for_status()
except requests.exceptions.Timeout:
raise RuntimeError("Processor request timed out after 10s") from None
except requests.exceptions.HTTPError as exc:
raise RuntimeError(f"Processor returned {response.status_code}: {response.text}") from exc
except requests.exceptions.ConnectionError as exc:
raise RuntimeError("Could not reach processor — check DNS/TLS/network") from exc
data = response.json()
Session reuse
Creating a requests.Session() once and reusing it (as above) keeps TCP/TLS connections alive across calls via connection pooling, which noticeably reduces latency for services making frequent calls to the same processor host — avoid constructing a new session per request in hot paths.
Error handling
raise_for_status() turns any 4xx/5xx into a requests.exceptions.HTTPError, which you can catch alongside Timeout and ConnectionError to cover the three practical failure classes: request/auth errors, processor-side errors, and network-level failures. Always inspect response.status_code and the JSON error body (most processors include a stable error_code field) rather than pattern-matching on human-readable error text.
Security notes
- Never log the raw
Authorizationheader or full request/response bodies containing card or account data — mask or omit sensitive fields before anylogging.info(...)call. - Pin a reasonable
timeouton every call; a synchronous script with no timeout can hang a worker process indefinitely on a stalled connection. - Rotate
PROCESSOR_API_KEYthrough your secrets manager (not by editing.envon a running server) so rotations are auditable.