imazeo 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,16 @@
1
+ node_modules/
2
+ dist/
3
+ *.tgz
4
+ .DS_Store
5
+ coverage/
6
+ __pycache__/
7
+ *.py[cod]
8
+ *.egg-info/
9
+ .eggs/
10
+ .pytest_cache/
11
+ .mypy_cache/
12
+ .ruff_cache/
13
+ .venv/
14
+ venv/
15
+ build/
16
+ *.whl
@@ -0,0 +1,34 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0
4
+
5
+ ### Added
6
+
7
+ - Initial official Python SDK (`imazeo`)
8
+ - Resources: `context`, `images`, `transforms`, `qr`, `barcodes`, `pdf`
9
+ - Typed errors mapped from Imazeo API envelopes
10
+ - API version allowlist (`v1`) separate from SDK SemVer
11
+ - Multipart uploads with required `X-Upload-Length`
12
+ - Binary response helpers for images/PDF/QR/barcode
13
+ - Image list `q` filename-prefix filter
14
+ - Transform download `If-None-Match` → HTTP 304 as `BinaryResult.not_modified`
15
+ - Default HTTP transport refuses redirects so `X-API-Key` stays on the configured origin
16
+ - Reviewed API-key-only OpenAPI snapshot bundled as `openapi/backend.json`
17
+ - Native CI verification and independent SemVer/tag checks
18
+
19
+ ### Media contract
20
+
21
+ - Barcode: required `type` and `content`; optional `format` (`png`/`svg`) and `includeText`
22
+ - PDF merge uses repeated multipart `file` parts in order
23
+ - Integer model types for barcode scale and image hue where applicable
24
+
25
+ ### Deferred (API-key routes exist; not in SDK_BEHAVIOR §1)
26
+
27
+ - Tool artifacts CRUD/download
28
+ - Project outputs list
29
+
30
+ ### API compatibility
31
+
32
+ - Default API: `v1`
33
+ - Supported API versions: `v1`
34
+ - Default base URL: `https://api.imazeo.com`
imazeo-1.0.0/GUIDE.md ADDED
@@ -0,0 +1,141 @@
1
+ # Imazeo Python integration guide
2
+
3
+ ## 1. Prepare a server integration
4
+
5
+ Install the package:
6
+
7
+ ```bash
8
+ pip install imazeo
9
+ ```
10
+
11
+ Package: [`imazeo`](https://pypi.org/project/imazeo/) on PyPI.
12
+ Source: [manishbalodia/imazeo-python](https://github.com/manishbalodia/imazeo-python).
13
+ Use the package README for runtime details.
14
+
15
+ Create a Customer account, complete required verification, create a project and
16
+ issue a project key. Set IMAZEO_API_KEY in protected server configuration and
17
+ IMAZEO_API_ORIGIN to the supplied API origin (no /v1 suffix; production default
18
+ `https://api.imazeo.com`). Use HTTPS outside loopback development. A key can
19
+ resolve its project through GET /v1/api-key/context; that response has projectId
20
+ and keyId, not plan limits or the secret key.
21
+
22
+ The Main site's documentation paths, served by your configured Main origin, are:
23
+ /docs/getting-started/, /docs/authentication/ and /docs/projects/.
24
+ These paths are site-relative; this guide does not assume a live production domain.
25
+
26
+ ## 2. Generate a QR code and render a delivery note
27
+
28
+ The following example uses the `imazeo` package. Obtain the original two-page synthetic
29
+ delivery-note.pdf from the Main site's /examples/assets/delivery-note.pdf and put it
30
+ in the working directory. The event URL is fictional. Run only against your configured
31
+ API deployment with the required entitlements and credits.
32
+
33
+ ```python
34
+ import os
35
+ import base64
36
+ from pathlib import Path
37
+ from imazeo import Imazeo, PdfMultiPageResult
38
+
39
+ # Context manager closes the underlying HTTP client.
40
+ with Imazeo(api_key=os.environ['IMAZEO_API_KEY'],
41
+ base_url=os.environ['IMAZEO_API_ORIGIN']) as client:
42
+ qr = client.qr.generate({
43
+ 'content': 'https://example.com/events/studio-open-day',
44
+ 'format': 'svg', 'size': 384,
45
+ })
46
+ Path('event-check-in.svg').write_bytes(qr.data)
47
+ result = client.pdf.render(Path('delivery-note.pdf').read_bytes(), {
48
+ 'pages': '1,2', 'format': 'png',
49
+ })
50
+ if isinstance(result, PdfMultiPageResult):
51
+ for page in result.pages:
52
+ Path(f"delivery-page-{page['pageNumber']}.png").write_bytes(
53
+ base64.b64decode(page['data'], validate=True))
54
+ else:
55
+ Path('delivery-page.png').write_bytes(result.data)
56
+ ```
57
+
58
+ All six SDK default transports refuse HTTP redirects so project credentials stay
59
+ on the configured API origin. The examples also set safe redirect policies where
60
+ custom client hooks are used. Custom fetch functions, Java HttpClient instances,
61
+ .NET HttpClient/message handlers and Python/PHP handlers must preserve this rule.
62
+ Never forward project credentials to a redirected host.
63
+
64
+ QR success is binary SVG. A one-page PDF render returns binary image bytes; multiple
65
+ selected pages return base64 page data. This SDK's render result is:
66
+ BinaryResult or PdfMultiPageResult. Decode base64 exactly once; use each page's contentType if you
67
+ change the selected format. The example uses PNG and .png filenames deliberately.
68
+
69
+ ## 3. Upload and transform images
70
+
71
+ Use the image upload method with file bytes and explicit filename/content type
72
+ as documented in the README. It sends multipart field file and the exact
73
+ X-Upload-Length file byte count. Filenames are metadata, not paths or resource IDs.
74
+ Keep the returned image ID, then create a transform with imageId and transform.
75
+ REST uses _id; use the native ID accessor shown in the README.
76
+
77
+ CACHE and PERSIST retain derivatives according to their mode rules. EPHEMERAL
78
+ only returns immediate bytes. All transform success bodies are binary. Image
79
+ originals preserve original metadata; generated derivatives strip metadata.
80
+ The HTTP guides are /docs/images/, /docs/transforms/ and /docs/quickstart/.
81
+
82
+ ## 4. Choose PDF and code inputs
83
+
84
+ PDF info returns parsed JSON and costs one credit. Render costs one per selected
85
+ page; merge costs two; extract costs one. Page numbers are one-based. Select
86
+ pages, a complete rangeStart/rangeEnd pair, or render-only all=true; do not combine
87
+ selectors. Render defaults to page 1; extract requires an explicit selection.
88
+ Merge upload order determines document order. Encrypted/invalid PDFs are rejected.
89
+
90
+ QR and barcode generation each cost one credit and return PNG or SVG. Barcode
91
+ content must be a string, including numeric identifiers with leading zeros.
92
+ Send numbers and booleans as native values, and omit unused optional fields instead
93
+ of null. A barcode renderer does not assign registered retail identifiers; QR
94
+ generation does not provide dynamic redirect hosting.
95
+ Detailed guides: /docs/pdf/, /docs/qr/, /docs/barcodes/ and /docs/workflows/.
96
+
97
+ ## 5. Handle pagination, downloads and errors
98
+
99
+ Image/transform lists return a Page wrapper with items and page/limit/total/pages.
100
+ Pagination is explicit; clients do not silently fetch all pages. Only image lists
101
+ accept q as a filename-prefix filter; transformation lists accept page and limit.
102
+ This is not unrestricted full-text search.
103
+ Binary results contain bytes, content type, headers and request ID. Derivative
104
+ downloads support conditional ETags. A not-modified result has no new bytes:
105
+ retain your cached file instead of replacing it with an empty body.
106
+
107
+ SDK errors expose status, code, request ID and details using native language names
108
+ listed in the README. Network errors do not guarantee an HTTP status. Log only
109
+ sanitized diagnostics; never log a key, source media or base64 PDF pages. Fix
110
+ validation/authentication/entitlement failures. For temporary 429 or busy responses,
111
+ use bounded backoff only when replay is safe and honor Retry-After if supplied.
112
+ No general idempotency-key mechanism is promised. A timed-out mutation may already
113
+ have completed; reconcile known IDs/state before repeating it. SDKs do not
114
+ automatically retry mutations.
115
+ See /docs/errors/ and /docs/troubleshooting/.
116
+
117
+ ## 6. Retain outputs and operate in production
118
+
119
+ PDF/code output is transient unless you retain the bytes or separately save a
120
+ private artifact through HTTP. Saved artifacts, unified output inventory, usage,
121
+ account/project/key management and Admin APIs are outside the SDK's core media
122
+ scope. Use Customer Bearer authentication for management, not a project key.
123
+ Do not combine Bearer and X-API-Key in one request.
124
+
125
+ There is no public CDN or customer signed-delivery URL in this contract. Deliver
126
+ bytes through your own authorized server. Never bundle a project key into browser,
127
+ mobile or end-user applications. Your server must enforce its own per-user access.
128
+
129
+ Bound source sizes, output bytes, page counts and concurrency: these SDKs buffer
130
+ media and base64 pages require extra memory. Default client timeouts are 30 seconds
131
+ for light operations, 60 seconds for images and 120 seconds for PDFs; they do not
132
+ extend backend worker deadlines. Check assigned account limits, not just public
133
+ pricing templates. Cache hits still consume output bandwidth; an authenticated
134
+ derivative 304 consumes no output bandwidth. Deletion refunds storage, not past
135
+ credits/bandwidth. Expiry and physical cleanup are separate.
136
+
137
+ Production and reference paths: /docs/outputs/, /docs/limits/, /docs/security/,
138
+ /docs/production/ and /docs/api-reference/. The developer OpenAPI download is
139
+ /openapi/imazeo-developer.json. It is a curated development snapshot and excludes
140
+ Admin/account operations and the known defective unified Outputs list; use
141
+ resource-specific lists to enumerate inventory.
imazeo-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Imazeo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
imazeo-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,210 @@
1
+ Metadata-Version: 2.5
2
+ Name: imazeo
3
+ Version: 1.0.0
4
+ Summary: Official Imazeo Python SDK for server-side image, transform, PDF, QR, and barcode APIs
5
+ Project-URL: Homepage, https://pypi.org/project/imazeo/
6
+ Project-URL: Documentation, https://github.com/manishbalodia/imazeo-python#readme
7
+ Project-URL: Repository, https://github.com/manishbalodia/imazeo-python
8
+ Project-URL: Issues, https://github.com/manishbalodia/imazeo-python/issues
9
+ Author: Imazeo
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: barcode,images,imazeo,pdf,qr,sdk,transforms
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.10
23
+ Requires-Dist: httpx>=0.27
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest>=8.0; extra == 'dev'
26
+ Description-Content-Type: text/markdown
27
+
28
+ # imazeo
29
+
30
+ Official **server-side** Python SDK for Imazeo.
31
+
32
+ | | |
33
+ | -------------- | ------------------------------- |
34
+ | Package | `imazeo` |
35
+ | SDK version | `1.0.0` |
36
+ | Default API | `v1` |
37
+ | Supported APIs | `v1` |
38
+ | Runtime | Python **3.10+** (sync `httpx`) |
39
+ | Registry | [PyPI](https://pypi.org/project/imazeo/) |
40
+ | Source | [GitHub](https://github.com/manishbalodia/imazeo-python) |
41
+
42
+ > **Security:** Secret API keys (`X-API-Key`) are for trusted servers only.
43
+ > Do **not** ship this client with a secret key in browsers or client apps.
44
+
45
+ Integration contract and learning path: [GUIDE.md](GUIDE.md).
46
+
47
+ ## Install
48
+
49
+ ```bash
50
+ pip install imazeo
51
+ ```
52
+
53
+ Requires Python 3.10+. Create a project API key in the Imazeo customer portal.
54
+ Default API origin is `https://api.imazeo.com` (override with `base_url` when needed).
55
+
56
+ ## Learning path
57
+
58
+ Read the self-contained [integration guide](GUIDE.md) for project/key setup,
59
+ language examples, PDF response types, pagination, output retention, troubleshooting
60
+ and production practices.
61
+
62
+ The default HTTP client refuses redirects so credentials stay on the configured
63
+ API origin.
64
+
65
+ ## Quick start
66
+
67
+ ```python
68
+ from pathlib import Path
69
+ from imazeo import Imazeo
70
+ import os
71
+
72
+ client = Imazeo(
73
+ api_key=os.environ["IMAZEO_API_KEY"],
74
+ base_url=os.environ["IMAZEO_API_ORIGIN"], # supplied API origin
75
+ # project_id="…", # optional; otherwise resolved via /v1/api-key/context
76
+ )
77
+
78
+ qr = client.qr.generate({
79
+ "content": "https://imazeo.com",
80
+ "format": "png",
81
+ "size": 256,
82
+ })
83
+ Path("qr.png").write_bytes(qr.data)
84
+ client.close()
85
+ ```
86
+
87
+ Or use as a context manager:
88
+
89
+ ```python
90
+ with Imazeo(api_key=os.environ["IMAZEO_API_KEY"]) as client:
91
+ ctx = client.context.get()
92
+ print(ctx["projectId"], ctx["keyId"])
93
+ ```
94
+
95
+ ## Authentication
96
+
97
+ ```python
98
+ Imazeo(api_key=os.environ["IMAZEO_API_KEY"])
99
+ ```
100
+
101
+ Sends `X-API-Key` only. Never send `Authorization` together with an API key
102
+ (backend rejects that combination).
103
+
104
+ ## Resources
105
+
106
+ | Resource | Methods |
107
+ | ------------------- | -------------------------------------------------------------------------------- |
108
+ | `client.context` | `get()` → project/key IDs |
109
+ | `client.images` | `upload`, `list` (`page`/`limit`/`q`), `get`, `delete`, `download` |
110
+ | `client.transforms` | `create`, `list`, `get`, `download` (`if_none_match` → `not_modified`), `delete` |
111
+ | `client.qr` | `generate` |
112
+ | `client.barcodes` | `generate` |
113
+ | `client.pdf` | `info`, `render`, `merge`, `extract` |
114
+
115
+ ### Upload + transform
116
+
117
+ ```python
118
+ image = client.images.upload(
119
+ photo_bytes,
120
+ filename="photo.jpg",
121
+ content_type="image/jpeg",
122
+ )
123
+
124
+ out = client.transforms.create({
125
+ "imageId": image["_id"],
126
+ "mode": "EPHEMERAL",
127
+ "transform": {"width": 1200, "format": "webp", "quality": 85},
128
+ })
129
+ # out.data → bytes
130
+ ```
131
+
132
+ ### Remote URL transform
133
+
134
+ ```python
135
+ out = client.transforms.create({
136
+ "url": "https://example.com/image.jpg",
137
+ "transform": {"width": 640, "format": "jpeg"},
138
+ })
139
+ ```
140
+
141
+ ### PDF
142
+
143
+ ```python
144
+ info = client.pdf.info(pdf_bytes)
145
+ page = client.pdf.render(pdf_bytes, {"pages": "1", "format": "png"})
146
+ merged = client.pdf.merge([pdf_a, pdf_b])
147
+ extracted = client.pdf.extract(pdf_bytes, {"pages": "1,2"})
148
+ ```
149
+
150
+ ## Errors
151
+
152
+ ```python
153
+ from imazeo import ImazeoError, RateLimitError
154
+
155
+ try:
156
+ client.images.get(image_id)
157
+ except RateLimitError as error:
158
+ print(error.code, error.request_id)
159
+ except ImazeoError as error:
160
+ print(error.status, error.code, error.message)
161
+ ```
162
+
163
+ ## Configuration
164
+
165
+ | Option | Default | Notes |
166
+ | ------------- | ------------------------ | -------------------------------------- |
167
+ | `api_key` | required | Secret key |
168
+ | `project_id` | from context | Path project |
169
+ | `base_url` | `https://api.imazeo.com` | Origin only; `/v1` stripped if present |
170
+ | `api_version` | `v1` | Allowlisted |
171
+ | `timeout_ms` | `60000` | PDF uses 120s; QR/barcode 30s |
172
+ | `app_name` | — | Appended to User-Agent |
173
+ | `transport` | — | Optional `httpx.BaseTransport` (tests) |
174
+
175
+ ## API version vs package version
176
+
177
+ - **API** path version: `v1` (configured via `api_version`)
178
+ - **SDK** SemVer: `1.0.0`
179
+
180
+ `Imazeo.api_compatibility()` reports supported API versions.
181
+
182
+ ## Not included
183
+
184
+ Portal JWT APIs (projects CRUD, API-key management, usage, plans, tickets, auth),
185
+ admin APIs, tool-artifacts, outputs, and browser secret-key usage.
186
+
187
+ ## Development
188
+
189
+ ```bash
190
+ pip install -e ".[dev]"
191
+ pytest
192
+ ```
193
+
194
+ ## License
195
+
196
+ MIT
197
+
198
+ ## Media contract update — 2026-10-02
199
+
200
+ Barcode generation requires `type` and string `content`; optional `format` is
201
+ `png` or `svg` (default `png`), and `includeText` is a boolean (default `true`).
202
+ The old `data`, `output` and `includetext` fields are removed before release.
203
+ PDF merge sends repeated `file` parts in order. Omit optional fields for defaults;
204
+ JSON numbers/booleans are not coerced and top-level optional nulls are rejected.
205
+ Barcode scale and image hue are integers. Methods retain language-specific names.
206
+ The reviewed API-key-only contract is bundled in `openapi/backend.json`.
207
+
208
+ ```python
209
+ client.barcodes.generate({'type': 'code128', 'content': 'IMAZEO-2026', 'format': 'svg', 'includeText': False})
210
+ ```
imazeo-1.0.0/README.md ADDED
@@ -0,0 +1,183 @@
1
+ # imazeo
2
+
3
+ Official **server-side** Python SDK for Imazeo.
4
+
5
+ | | |
6
+ | -------------- | ------------------------------- |
7
+ | Package | `imazeo` |
8
+ | SDK version | `1.0.0` |
9
+ | Default API | `v1` |
10
+ | Supported APIs | `v1` |
11
+ | Runtime | Python **3.10+** (sync `httpx`) |
12
+ | Registry | [PyPI](https://pypi.org/project/imazeo/) |
13
+ | Source | [GitHub](https://github.com/manishbalodia/imazeo-python) |
14
+
15
+ > **Security:** Secret API keys (`X-API-Key`) are for trusted servers only.
16
+ > Do **not** ship this client with a secret key in browsers or client apps.
17
+
18
+ Integration contract and learning path: [GUIDE.md](GUIDE.md).
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ pip install imazeo
24
+ ```
25
+
26
+ Requires Python 3.10+. Create a project API key in the Imazeo customer portal.
27
+ Default API origin is `https://api.imazeo.com` (override with `base_url` when needed).
28
+
29
+ ## Learning path
30
+
31
+ Read the self-contained [integration guide](GUIDE.md) for project/key setup,
32
+ language examples, PDF response types, pagination, output retention, troubleshooting
33
+ and production practices.
34
+
35
+ The default HTTP client refuses redirects so credentials stay on the configured
36
+ API origin.
37
+
38
+ ## Quick start
39
+
40
+ ```python
41
+ from pathlib import Path
42
+ from imazeo import Imazeo
43
+ import os
44
+
45
+ client = Imazeo(
46
+ api_key=os.environ["IMAZEO_API_KEY"],
47
+ base_url=os.environ["IMAZEO_API_ORIGIN"], # supplied API origin
48
+ # project_id="…", # optional; otherwise resolved via /v1/api-key/context
49
+ )
50
+
51
+ qr = client.qr.generate({
52
+ "content": "https://imazeo.com",
53
+ "format": "png",
54
+ "size": 256,
55
+ })
56
+ Path("qr.png").write_bytes(qr.data)
57
+ client.close()
58
+ ```
59
+
60
+ Or use as a context manager:
61
+
62
+ ```python
63
+ with Imazeo(api_key=os.environ["IMAZEO_API_KEY"]) as client:
64
+ ctx = client.context.get()
65
+ print(ctx["projectId"], ctx["keyId"])
66
+ ```
67
+
68
+ ## Authentication
69
+
70
+ ```python
71
+ Imazeo(api_key=os.environ["IMAZEO_API_KEY"])
72
+ ```
73
+
74
+ Sends `X-API-Key` only. Never send `Authorization` together with an API key
75
+ (backend rejects that combination).
76
+
77
+ ## Resources
78
+
79
+ | Resource | Methods |
80
+ | ------------------- | -------------------------------------------------------------------------------- |
81
+ | `client.context` | `get()` → project/key IDs |
82
+ | `client.images` | `upload`, `list` (`page`/`limit`/`q`), `get`, `delete`, `download` |
83
+ | `client.transforms` | `create`, `list`, `get`, `download` (`if_none_match` → `not_modified`), `delete` |
84
+ | `client.qr` | `generate` |
85
+ | `client.barcodes` | `generate` |
86
+ | `client.pdf` | `info`, `render`, `merge`, `extract` |
87
+
88
+ ### Upload + transform
89
+
90
+ ```python
91
+ image = client.images.upload(
92
+ photo_bytes,
93
+ filename="photo.jpg",
94
+ content_type="image/jpeg",
95
+ )
96
+
97
+ out = client.transforms.create({
98
+ "imageId": image["_id"],
99
+ "mode": "EPHEMERAL",
100
+ "transform": {"width": 1200, "format": "webp", "quality": 85},
101
+ })
102
+ # out.data → bytes
103
+ ```
104
+
105
+ ### Remote URL transform
106
+
107
+ ```python
108
+ out = client.transforms.create({
109
+ "url": "https://example.com/image.jpg",
110
+ "transform": {"width": 640, "format": "jpeg"},
111
+ })
112
+ ```
113
+
114
+ ### PDF
115
+
116
+ ```python
117
+ info = client.pdf.info(pdf_bytes)
118
+ page = client.pdf.render(pdf_bytes, {"pages": "1", "format": "png"})
119
+ merged = client.pdf.merge([pdf_a, pdf_b])
120
+ extracted = client.pdf.extract(pdf_bytes, {"pages": "1,2"})
121
+ ```
122
+
123
+ ## Errors
124
+
125
+ ```python
126
+ from imazeo import ImazeoError, RateLimitError
127
+
128
+ try:
129
+ client.images.get(image_id)
130
+ except RateLimitError as error:
131
+ print(error.code, error.request_id)
132
+ except ImazeoError as error:
133
+ print(error.status, error.code, error.message)
134
+ ```
135
+
136
+ ## Configuration
137
+
138
+ | Option | Default | Notes |
139
+ | ------------- | ------------------------ | -------------------------------------- |
140
+ | `api_key` | required | Secret key |
141
+ | `project_id` | from context | Path project |
142
+ | `base_url` | `https://api.imazeo.com` | Origin only; `/v1` stripped if present |
143
+ | `api_version` | `v1` | Allowlisted |
144
+ | `timeout_ms` | `60000` | PDF uses 120s; QR/barcode 30s |
145
+ | `app_name` | — | Appended to User-Agent |
146
+ | `transport` | — | Optional `httpx.BaseTransport` (tests) |
147
+
148
+ ## API version vs package version
149
+
150
+ - **API** path version: `v1` (configured via `api_version`)
151
+ - **SDK** SemVer: `1.0.0`
152
+
153
+ `Imazeo.api_compatibility()` reports supported API versions.
154
+
155
+ ## Not included
156
+
157
+ Portal JWT APIs (projects CRUD, API-key management, usage, plans, tickets, auth),
158
+ admin APIs, tool-artifacts, outputs, and browser secret-key usage.
159
+
160
+ ## Development
161
+
162
+ ```bash
163
+ pip install -e ".[dev]"
164
+ pytest
165
+ ```
166
+
167
+ ## License
168
+
169
+ MIT
170
+
171
+ ## Media contract update — 2026-10-02
172
+
173
+ Barcode generation requires `type` and string `content`; optional `format` is
174
+ `png` or `svg` (default `png`), and `includeText` is a boolean (default `true`).
175
+ The old `data`, `output` and `includetext` fields are removed before release.
176
+ PDF merge sends repeated `file` parts in order. Omit optional fields for defaults;
177
+ JSON numbers/booleans are not coerced and top-level optional nulls are rejected.
178
+ Barcode scale and image hue are integers. Methods retain language-specific names.
179
+ The reviewed API-key-only contract is bundled in `openapi/backend.json`.
180
+
181
+ ```python
182
+ client.barcodes.generate({'type': 'code128', 'content': 'IMAZEO-2026', 'format': 'svg', 'includeText': False})
183
+ ```
@@ -0,0 +1,44 @@
1
+ """Minimal server-side QR example.
2
+
3
+ Requires: IMAZEO_API_KEY, optional IMAZEO_BASE_URL, IMAZEO_PROJECT_ID
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import os
9
+ import sys
10
+ from pathlib import Path
11
+
12
+ from imazeo import Imazeo
13
+
14
+
15
+ def main() -> None:
16
+ api_key = os.environ.get("IMAZEO_API_KEY")
17
+ if not api_key:
18
+ raise SystemExit("Set IMAZEO_API_KEY")
19
+
20
+ with Imazeo(
21
+ api_key=api_key,
22
+ base_url=os.environ.get("IMAZEO_BASE_URL", "http://localhost:3001"),
23
+ project_id=os.environ.get("IMAZEO_PROJECT_ID"),
24
+ ) as client:
25
+ ctx = client.context.get()
26
+ print("project", ctx["projectId"], "env", ctx["environment"])
27
+
28
+ qr = client.qr.generate(
29
+ {
30
+ "content": "https://imazeo.com",
31
+ "size": 256,
32
+ "format": "png",
33
+ }
34
+ )
35
+ Path("qr.png").write_bytes(qr.data)
36
+ print("wrote qr.png", qr.content_type)
37
+
38
+
39
+ if __name__ == "__main__":
40
+ try:
41
+ main()
42
+ except Exception as error: # noqa: BLE001 — example script
43
+ print(error, file=sys.stderr)
44
+ raise SystemExit(1) from error