Core API
Essential HTTP methods and configuration for everyday use — every method is synchronous by default
HTTP Methods
AtomHTTP supports all standard HTTP methods with a plain, synchronous interface -- no await required. Each method returns a Response object containing the parsed response body, status code, headers, and original request configuration. The exact same methods exist on AsyncAtomHTTP, just awaited.
GET Request
Retrieve data from a server. GET requests should only retrieve data and should not have any other effect. Returns a Response directly -- no await needed.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| url | str | Required | The endpoint URL |
| params | dict | {} | Query parameters for filtering, pagination, sorting |
| headers | dict | {} | Custom HTTP headers |
| responseType | str | "json" | Response format: json, text, blob, arraybuffer, stream |
| timeout | int/float | 30 | Override client timeout |
Returns
Response — Response object containing data, status, headers, configExample
# Basic GET request
response = client.get('https://api.example.com/users')
# GET with query parameters
response = client.get('/users', params={'page': 1, 'limit': 10, 'sort': 'desc'})
print(response.data)
# GET with custom headers
response = client.get('/protected', headers={'Authorization': 'Bearer token123'})POST Request
Send data to create a new resource. Accepts JSON, FormData, URL-encoded data, or raw bytes. Large file uploads via FormData stream automatically -- the file is never fully loaded into memory.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| url | str | Required | The endpoint URL |
| data | Any | None | Request body (dict, FormData, bytes, str) |
| headers | dict | {} | Custom HTTP headers (Content-Type auto-detected) |
| responseType | str | "json" | Response format |
| onUploadProgress | Callable | None | Progress callback for uploads: fn(loaded, total) |
Returns
Response — Response object with created resource dataExample
# POST with JSON data
user_data = {'name': 'John Doe', 'email': 'john@example.com'}
response = client.post('/users', data=user_data)
print(f"Created ID: {response.data['id']}")
# POST with FormData (file upload -- large files stream automatically)
from atomhttp import FormData
form = FormData()
form.append('name', 'John Doe')
form.append('avatar', open('photo.jpg', 'rb'), filename='photo.jpg')
response = client.post('/users', data=form)
# POST with progress tracking
def on_progress(loaded, total):
print(f"Uploaded: {loaded}/{total} bytes")
response = client.post('/upload', data=large_file, onUploadProgress=on_progress)PUT Request
Completely replace an existing resource. Requires the complete resource data.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| url | str | Required | The endpoint URL with resource ID |
| data | dict | Required | Complete resource data |
| headers | dict | {} | Custom HTTP headers |
Returns
Response — Response object with updated resource dataExample
# Full resource replacement
update_data = {'id': 1, 'name': 'Jane Doe', 'email': 'jane@example.com', 'role': 'admin'}
response = client.put('/users/1', data=update_data)
# Conditional update
response = client.put('/users/1', data=update_data,
headers={'If-Unmodified-Since': 'Wed, 21 Oct 2024 07:28:00 GMT'})PATCH Request
Partially update an existing resource. Only send the fields that need to be changed.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| url | str | Required | The endpoint URL with resource ID |
| data | dict | Required | Fields to update (partial data) |
| headers | dict | {} | Custom HTTP headers |
Returns
Response — Response object with updated resource dataExample
# Partial update
response = client.patch('/users/1', data={'email': 'newemail@example.com'})
# Update multiple fields
response = client.patch('/users/1', data={'email': 'newemail@example.com', 'role': 'editor'})
# JSON Patch operations
response = client.patch('/users/1', data=[
{'op': 'replace', 'path': '/email', 'value': 'new@example.com'}
])DELETE Request
Remove a resource from the server.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| url | str | Required | The endpoint URL with resource ID |
| params | dict | {} | Query parameters for batch delete |
| headers | dict | {} | Custom HTTP headers |
Returns
Response — Response object (status 204 on success)Example
# Delete a single resource
response = client.delete('/users/1')
if response.status == 204:
print("User deleted successfully")
# Batch delete
response = client.delete('/users', params={'ids': '1,2,3'})
# Conditional delete
response = client.delete('/users/1', headers={'If-Match': 'etag123'})HEAD Request
Retrieve headers only, without the response body.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| url | str | Required | The endpoint URL |
| headers | dict | {} | Custom HTTP headers |
Returns
Response — Response object with headers but empty bodyExample
# Check if resource exists
response = client.head('/large-file.pdf')
print(f"Size: {response.headers.get('Content-Length')} bytes")
print(f"Type: {response.headers.get('Content-Type')}")
print(f"Modified: {response.headers.get('Last-Modified')}")
# Check API health
response = client.head('/health')
print(f"Status: {'healthy' if response.ok else 'unhealthy'}")OPTIONS Request
Discover which HTTP methods are supported by a resource.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| url | str | Required | The endpoint URL |
| headers | dict | {} | Custom HTTP headers |
Returns
Response — Response with Allow header listing supported methodsExample
# Discover allowed methods
response = client.options('/users/1')
print(f"Allowed: {response.headers.get('Allow', '')}")
# CORS preflight
response = client.options('/api/data', headers={
'Origin': 'https://myapp.com',
'Access-Control-Request-Method': 'POST'
})Generic Request Method
Unified request method for maximum flexibility.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| method | str | "GET" | HTTP method (GET, POST, etc.) |
| url | str | Required | Request URL |
| data | Any | None | Request body |
| params | dict | {} | Query parameters |
| headers | dict | {} | Custom headers |
| timeout | int | 30 | Request timeout |
Returns
Response — Response objectExample
# Full control over request configuration
response = client.request(
'POST',
'/api/data',
data={'key': 'value'},
headers={'X-Custom': 'header'},
params={'version': 'v2'},
timeout=30,
maxRedirects=0,
responseType='text',
)
# Dynamic method selection
method = 'DELETE' if condition else 'PUT'
response = client.request(method, '/resource/1')Response Object
Every request returns a Response object with the following properties:
| Property | Description | Type | Example |
|---|---|---|---|
| response.data | Parsed response body | dict, list, str, bytes | response.data['id'] |
| response.status | HTTP status code | int | response.status == 200 |
| response.status_text | HTTP status message | str | response.status_text |
| response.headers | Response headers | dict | response.headers['Content-Type'] |
| response.config | Original request config | RequestConfig | response.config.url |
| response.ok | Success indicator (200-299) | bool | if response.ok: ... |
| response.elapsed | Wall-clock request duration | float | None | response.elapsed |
| response.url | Final URL after redirects | str | None | response.url |
response = client.get('https://httpbin.org/get')
print(f"Status: {response.status} {response.status_text}")
print(f"Content-Type: {response.headers.get('Content-Type')}")
print(f"Body: {response.data}")
print(f"URL: {response.config.url}")
# Chainable status check
data = client.get('/users/1').raise_for_status().dataResponse Types
jsonParses as dict/list (default)
textReturns raw text → str
blob / arraybufferReturns binary → bytes
streamRaw urllib3.HTTPResponse — prefer client.stream()
Client Configuration
Configure your client with defaults that apply to every request:
| Option | Type | Default | Description |
|---|---|---|---|
| base_url | str | "" | Base URL prepended to relative paths |
| timeout | int/float | 30 | Request timeout in seconds |
| headers | dict | {} | Default headers sent with every request |
| cookies | bool | True | Enable the client's persistent cookie jar |
| max_workers | int | 10 | Size of the persistent thread pool backing .all()/.submit()/.map() |
| maxRedirects | int | 5 | Maximum number of redirects to follow |
| responseType | str | "json" | Response format: json, text, blob, arraybuffer, stream |
| keepAlive | bool | True | Enable HTTP keep-alive connections |
| verify | bool | str | True | SSL verification: True/False, or a path to a custom CA bundle |
| cert | str | tuple | None | Client cert for mTLS: a path, or (cert_path, key_path) |
| retryConfig | dict | None | Retry settings for transient failures: max_retries, backoff_factor, status_forcelist. Retry-After is honored automatically. |
| decompress | bool | True | Automatically decompress gzip/deflate/brotli responses |
| adapter | BaseAdapter | HTTPAdapter() | Custom transport adapter, e.g. MockAdapter for tests |
client = AtomHTTP(
base_url='https://api.example.com',
timeout=15,
headers={'X-API-Key': 'your-api-key', 'Accept': 'application/json'},
maxRedirects=3,
responseType='json',
keepAlive=True,
verify=True,
max_workers=20,
retryConfig={
'max_retries': 3,
'backoff_factor': 0.3,
'status_forcelist': [408, 429, 500, 502, 503, 504],
},
)
# All requests use these defaults
response = client.get('/users')
# Override for specific request
response = client.get('/slow', timeout=60)Configuration Inheritance
Client-level defaults are merged with request-level options. Headers are deeply merged (request headers override client headers), while other options are replaced entirely.
Headers & Query Parameters
Add custom headers for authentication and metadata. Use query parameters for filtering and pagination.
response = client.get('https://httpbin.org/get',
params={'search': 'python', 'page': 2, 'limit': 20},
headers={'Authorization': 'Bearer token123', 'X-Custom-Header': 'value'}
)Common Headers
AuthorizationBearer token or Basic auth
Content-TypeMedia type of request body
AcceptExpected response media type
User-AgentClient identifier
Query Parameter Best Practices
- Use
paramsfor GET, DELETE requests - Avoid sensitive data in query parameters (they appear in logs)
- Use lists for multi-value parameters
- Auto URL-encoded — no manual encoding needed
Response Types In Depth
responseType controls how the body is parsed. For JSON, if the server claims JSON but the body isn't valid, the raw text is returned instead of raising — the same leniency axios/requests offer.
client.get('/data') # responseType='json' (default)
client.get('/page', responseType='text') # -> str
client.get('/image.png', responseType='arraybuffer') # -> bytes
client.get('/report.pdf', responseType='blob') # -> bytes
# For truly large responses, prefer client.stream() over responseType='stream'
# -- see Advanced Features > Streaming, Download & PaginationError Types
AtomHTTP provides comprehensive error types with standardized error codes. By default, no exception is raised for 4xx/5xx -- use validateStatus or raise_for_status() to opt in.
| Error Type | Description | Error Code |
|---|---|---|
| AtomHTTPRequestError | Bad request (4xx) or malformed request, or rejected by validateStatus | ERR_BAD_{status} |
| AtomHTTPNetworkError | Network connectivity issues, DNS errors, connection refused | ERR_NETWORK |
| AtomHTTPTimeoutError | Request exceeded timeout limit | ECONNABORTED |
| AtomHTTPCancelError | Request was aborted via AbortController | ERR_CANCELED |
from atomhttp.errors import AtomHTTPTimeoutError, AtomHTTPNetworkError, AtomHTTPRequestError
try:
response = client.get('https://api.example.com/data', timeout=5, validateStatus=lambda s: s < 400)
except AtomHTTPTimeoutError as e:
print(f"Timeout: {e.code}") # ECONNABORTED
except AtomHTTPNetworkError as e:
print(f"Network error: {e.code}") # ERR_NETWORK
except AtomHTTPRequestError as e:
print(f"Request failed: {e.code} - Status {e.response.status}") # ERR_BAD_404Error Handling Best Practices
- Catch specific error types before generic Exception
- Use
error.codefor programmatic handling - Check
error.response.datafor server error details - Use
retryConfigfor automatic retry on timeout/network errors instead of manual retry loops