Skip to content

Commit 2e625b6

Browse files
committed
Update to version 4.0.0 on 2026-10-26
- **BREAKING CHANGE**: This version calls DocSpring API v2 (`/api/v2`). The 3.x versions call API v1, which keeps working. Every change is in the migration guide: https://docspring.com/docs/api-guide/migrating-to-api-v2/ - **BREAKING CHANGE**: If you set the API's full base URL yourself, change `/api/v1` in it to `/api/v2`. The client only picks the version in the URLs it builds from a region or host. - **BREAKING CHANGE**: Operations are named after the resource they act on. generate_pdf is create_submission, batch_generate_pdfs is create_submission_batch, combine_pdfs is create_combined_pdf, create_html_template and create_pdf_template_from_upload are create_template (with a `template_type`), create_pdf_template (which uploads a PDF file) is upload_template, get_full_template is get_template (which returns the template, without its fields for now), update_template_document (which uploads a PDF file) is upload_template_document, update_template_document_from_upload is update_template_document, generate_preview is generate_submission_preview, get_combined_submission is get_combined_pdf, list_combined_submissions is list_combined_pdfs, expire_combined_submission is expire_combined_pdf, move_template_to_folder is move_template and move_folder_to_folder is move_folder. New: get_folder, list_custom_files, get_custom_file and delete_custom_file. A template's fields, and adding fields to a template, aren't in API v2 yet. - **BREAKING CHANGE**: Data requests are called signature requests. `get_data_request`, `update_data_request`, `create_data_request_token` and `create_data_request_event` are `get_signature_request`, `update_signature_request`, `create_signature_request_token` and `create_signature_request_event` (at `/signature_requests`), and their models are `SignatureRequest`, `SignatureRequestToken` and `SignatureRequestEvent`. A submission's `data_requests` is `signature_requests` (also when you create one), `data_request_id` is `signature_request_id`, a token's `data_request_url` is `signature_request_url`, the `waiting_for_data_requests` state is `waiting_for_signature_requests`, and a template's `add_data_request_submission_id_footers` is `add_signature_request_submission_id_footers`. New ones get IDs that start with `srq_` instead of `drq_`. - **BREAKING CHANGE**: A response is the resource itself, with no `status` or wrapper key. Lists return `data` and `next_cursor`: pass `next_cursor` as `cursor` to get the next page, and `limit` (1 to 100, default 50) for its size. `page` and `per_page` are gone. Every create returns 201. - **BREAKING CHANGE**: Every error has one shape, `{"error": {"code", "message", "details", "request_id"}}`, with a `code` to check (`validation_failed`, `not_found`, `insufficient_credits`, `rate_limited`, ...), and each detail has a `pointer` to the body value it's about, or a `parameter` with the query parameter's name. - **BREAKING CHANGE**: Requests are validated strictly: an unknown property or query parameter, or a value of the wrong type, is a 422 instead of being ignored. Request bodies must be JSON (`Content-Type: application/json`, or it's a 415), except the PDF uploads. Request bodies are flat, with no `template`, `folder` or `webhook` key around them. - **BREAKING CHANGE**: Submission data is checked more strictly. An empty `data` is validated like any other, date fields take `YYYY-MM-DD` (or the template's date format when `parse_dates_using_template_date_format` is on), and a signature request's `fields` must be fields on the template (set `ignore_unknown_fields` to leave out the others). A submission that fails because of the template is still saved as `invalid_data`, and the 422 includes its `submission_id`. - **BREAKING CHANGE**: A submission's or combined PDF's files are in `files`, by format. `files.pdf` has `state`, `error_message`, `download_url`, `permanent_url`, `filename`, `content_type`, `size` and `sha256`, and replaces `download_url`, `permanent_download_url` and `pdf_hash`. A submission's `files.audit_trail` and `files.preview`, with the same properties, replace `audit_trail_download_url` and `preview_download_url`. A file made after its submission was processed is listed while it's being made, so check its `state` before using its links. Combined submissions are combined PDFs (`CombinedPdf`), a template's `document_url` is `document.download_url`, and a custom file's `url` is `download_url`. - **BREAKING CHANGE**: A template's `embed_domains` is a list of domains, not a comma-separated string, and each entry is checked. Copying a template with `parent_folder_id` null puts the copy at the root (leave it out to keep the template's folder). A template's schema and model code describe the version that submissions use by default (the latest published version), not the draft: pass `version` for another one. - **BREAKING CHANGE**: Every property name is snake_case, including template `defaults` (`font_size`, was `fontSize`), `html_engine_options` (`margin_top`), a field dependency condition's `range_max`, and the field settings in a submission's `field_overrides`. - `field_overrides` takes a `docspring.FieldOverride` per field name, with every setting an override can change (`required`, `font_size`, `color`, ...), so a misspelt setting or a value of the wrong type is caught before the request is sent. - A combined PDF's `source_pdfs` and a rule's `conditions` take a model per kind, with only the properties that kind uses (another kind's property is a 422 `not_allowed`). `CombinedPdfSourceInput` is a `SubmissionSourcePdf`, `CombinedPdfSourcePdf`, `TemplateSourcePdf`, `CustomFileSourcePdf` or `UrlSourcePdf`, picked by its `type`. `TemplateFieldDependencyConditionInput` is a `FieldPresenceCondition` (`present`, `blank`), `FieldEqualsCondition` (`equals`, `not_equals`), `FieldInCondition` (`in`, with a list), `FieldComparisonCondition` (`gt`, `gte`, `lt`, `lte`, on a number field) or `FieldRangeCondition` (`range`), picked by its `operator`. Pass dicts, or the models, which set their own `type` (and `FieldInCondition` and `FieldRangeCondition` their `operator`): `docspring.UrlSourcePdf(url=url)`. A template returns its conditions with only the properties their operators use, in the shape an update takes. - **BREAKING CHANGE**: Templates: `ready` and a `document` object (with its `state`, `page_count` and `page_dimensions`) replace `document_processed`, `document_state`, `document_parse_error` and the `page_*` fields. `list_templates` returns template summaries. Templates have no `webhook_url` or `webhook_options`: create a webhook with `template_ids` instead. - **BREAKING CHANGE**: Secrets are write-only. A submission's or combined PDF's `password` and a template's `encrypt_pdfs_password` and `slack_webhook_url` aren't returned; `has_password`, `has_encrypt_pdfs_password` and `has_slack_webhook_url` say whether one is set. - **BREAKING CHANGE**: Webhooks created with this version send payload version 4, `{"id", "event_type", "created_at", "data"}`, where `data` is the resource as API v2 returns it. Their events have API v2's names (`combined_pdf.processed`, `signature_request.completed`). Webhooks created with 3.x or in the dashboard keep their payload version. - **BREAKING CHANGE**: Models are named after the API's resources (`Submission`, `CombinedPdf`, `Template`, `TemplateSummary`, `SignatureRequest`), request bodies after their operation (`CreateSubmissionRequest`), and enums are their own types (`SubmissionState`, `WebhookEventType`). - Response enums are enum types too (`SubmissionState`, a `str` enum), so `submission.state == SubmissionState.PROCESSED` and `submission.state == "processed"` both work. A value added to the API after this release becomes a member of its own with that value, instead of failing validation. Iterating an enum gives the values this version knows. - The client checks each request against the API's request schemas before sending it, so an invalid request fails without a round trip, with the details the API's 422 response would have. A request the API would reject raises `docspring.RequestValidationError` (a `ValueError`), whose `details` are dicts with `code`, `message` and a `pointer` into the body (or a `parameter`). It runs before pydantic checks the arguments, and the request models no longer check patterns, lengths or ranges themselves, so a dict with a key the API doesn't document, or a value out of range, raises it rather than a pydantic `ValidationError`. Turn the check off with `client.api_client.configuration.client_side_validation = False`. - A waited request to `sync.api.docspring.com` that times out returns a 504 `polling_timeout` error with the resource's ID, so you can get it later. Without an ID, the request got no answer in time: check whether the resource was created before you send it again. - Date-time query parameters are sent in RFC 3339 (`2026-10-19T00:00:00+00:00`), which API v2 requires. - **BREAKING CHANGE**: Request models reject properties they don't have, so a misspelled property is an error instead of being dropped without a word. Response models still keep unknown fields in `additional_properties`. - **BREAKING CHANGE**: Requires Python 3.10 or later, urllib3 2.7 or later and pydantic 2.11 or later. It no longer depends on `lazy-imports`. - An empty API token ID or secret counts as not set, so the client reads `DOCSPRING_TOKEN_ID` or `DOCSPRING_TOKEN_SECRET` instead. It was sent as an empty string. - Templates: new `default_form_mode` setting (`web`, `visual` or `dual`), when you create or update a template. It's the hosted form that `/templates/<id>/form` opens when the link has no `mode` parameter: the web form, the visual form (filled in on the PDF), or both in tabs. HTML templates have no visual form, so they only accept `web`. - Templates: `defaults` can set `required_field_background_color`, the background colour that visual forms and signature requests give required fields. PDFs don't draw it. - Templates: new `allow_skipping_optional_fields` setting (boolean), when you create or update a template. Visual forms and signature requests then show the Continue button as soon as the required fields are filled in, without visiting each optional field. The `allowSkippingOptionalFields` embed option overrides it. - Templates: when you replace a template's PDF, `reimport_fields` (boolean) replaces the template's fields with the fillable fields in the new PDF (or in its current PDF when you don't upload one). A PDF with no fillable fields keeps the template's fields. - Fields: `shape_type` can be `triangle` or `polygon`, with `shape_sides` (3 to 12) for a polygon. Text fields can set `keep_leading_spaces` to keep the spaces at the start of each line in the PDF. - Templates: create_template and upload_template take `detect_fields` (boolean, default false). DocSpring then sets up the PDF's fields as the "Automatically detect fields" upload option does: it imports or detects them, names them with AI and sets up conditional logic. `field_source` (`auto`, `pdf_detection` or `pdf_form_fields`), `field_naming` (`ai` or `preserve`) and `field_logic` (`ai` or `none`) choose how, like the Set Up Fields choices in the template editor. With `pdf_form_fields`, `preserve` and `none`, the PDF's form fields are imported with their own names and no AI. Each account gets free AI pages every month, and further pages are paid from credits. See https://docspring.com/docs/template-editor/automatic-field-detection/. - Templates: new `ai_field_naming_language` setting (`auto`, `english` or `form_language`) for PDF templates, when you create or update one: the language AI uses for field names. It's null for HTML templates. - Templates: a template's `document` includes `has_fillable_fields`, `page_processing_statuses` (how processing is going on each page: its image, its fields and AI naming) and `field_logic_status` (the AI logic step that runs once every page's fields are done, and can still rename fields and add rules). Field setup is finished when `document.state` is `processed` and `field_logic_status` isn't `pending` or `processing`.
1 parent 6bdb778 commit 2e625b6

513 files changed

Lines changed: 24710 additions & 13022 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/python.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
runs-on: ubuntu-latest
1717
strategy:
1818
matrix:
19-
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
19+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
2020

2121
steps:
2222
- uses: actions/checkout@v4

‎.gitlab-ci.yml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ stages:
1414
- pip install -r test-requirements.txt
1515
- pytest --cov=docspring
1616

17-
pytest-3.9:
18-
extends: .pytest
19-
image: python:3.9-alpine
2017
pytest-3.10:
2118
extends: .pytest
2219
image: python:3.10-alpine
@@ -29,3 +26,6 @@ pytest-3.12:
2926
pytest-3.13:
3027
extends: .pytest
3128
image: python:3.13-alpine
29+
pytest-3.14:
30+
extends: .pytest
31+
image: python:3.14-alpine

0 commit comments

Comments
 (0)