Skip to main content

Guided interview and Docassemble integration

A guided interview can send its generated PDFs and already-collected answers to LITEfile. LITEfile saves a draft, resolves filing hints against current court choices, and asks the filer for missing details. A successful transfer means draft created, not filed with the court.

Docassemble owns the legal interview and documents. LITEfile owns court codes, filing classifications, party types, fees, payment, submission, and clerk returns. The Vermont docassemble.RFApackage interview includes a working sender.

Configure a source​

Apply the database migrations before enabling a source (uv run python manage.py migrate from efile_app/). Migration 0023_interview_handoff adds receipts, provenance, and correction revisions.

Set LITEFILE_HANDOFF_SOURCES in the LITEfile environment to a JSON object:

{
"vermont-rfa": {
"token": "a-long-random-secret",
"jurisdictions": ["vermont"],
"return_origins": ["https://interviews.example.org"]
}
}

Give each source its own secret and jurisdiction allowlist. Store the secret in server configuration, never interview text, browser JavaScript, or a URL. HTTPS is required for return links. Source authentication is independent of the filer's e-filing account; do not send the filer's password through this API.

Run database migrations when deploying the receiver. Configure the existing S3 upload handler with a private bucket. LITEfile accepts uploaded PDFs; it does not fetch arbitrary document URLs supplied by an interview.

Version 1 request​

Send POST /api/handoffs/v1/ with these headers:

Authorization: Bearer <source secret>
X-LITEFile-Source: vermont-rfa

For documents, use multipart/form-data: one text field named payload containing JSON and one PDF part per document, named with that document's id. Do not put Docassemble expressions or unresolved variable references in the payload. The sender evaluates only answers that are already defined, and omits unknown values. A request without documents may instead use application/json.

{
"schema_version": 1,
"jurisdiction": "vermont",
"source_id": "opaque-stable-interview-handoff-id",
"idempotency_key": "opaque-stable-request-id",
"filing_intent": "relief_from_abuse",
"case_category_name_hints": ["Family"],
"case_type_name_hints": ["Relief from Abuse"],
"filing_type_name_hints": ["Complaint"],
"case": {
"existing_case": false,
"court_name": "Chittenden Family Division",
"county": "Chittenden"
},
"filer": {
"first_name": "Example",
"last_name": "Filer",
"email": "[email protected]"
},
"parties": [
{
"first_name": "Example",
"last_name": "Filer",
"semantic_role": "plaintiff",
"case_side_hint": "plaintiff",
"is_self": true,
"is_filing_party": true
}
],
"documents": [
{
"id": "RFAcomplaint",
"role": "lead",
"form_name": "RFA Complaint",
"sha256": "<64 lowercase hexadecimal characters from the uploaded PDF>"
}
],
"known_filing_facts": {},
"return_url": "https://interviews.example.org/interview?session=<existing-session>"
}

Only schema_version, jurisdiction, source_id, and idempotency_key are required for an empty draft. Case, filer, parties, hints, facts, and documents may be partial or omitted. existing_case is a JSON boolean when known. case also accepts docket_number and case_title. Existing court cases still need a live lookup and confirmation of the case identifier.

People accept first_name, middle_name, last_name, suffix, organization_name, email, phone, address_line_1, address_line_2, city, state, zip_code, and a two-letter country. A party marked is_self: true merges into the filer row, preserving collected contact details. is_filing_party means the filing is made on that person's behalf. It does not mean the person operating the browser is necessarily a party.

Documents use stable source IDs, lead or supporting roles, and SHA-256 hashes. A nonempty handoff bundle must contain exactly one lead; the lead can appear anywhere in the list. The limits are 20 PDFs, 10 MB per PDF, 100 parties, and 512 KB of JSON metadata. Unknown source facts and numeric suggestions remain in the receipt; numeric suggestions never populate resolved court-code fields. Supported questionnaire answers has_children and child_count also populate their normal filing fields.

County-specific and court-specific hints​

Use filing_hint_overrides when a semantic name is correct in one filing location and wrong in another. Matching county values replace general hints field by field. Matching court values apply afterward and replace the county value for the same field. Fields that an override omits continue using the less specific value.

{
"case_category_name_hints": ["Civil"],
"case_type_name_hints": ["General case type"],
"filing_hint_overrides": {
"counties": {
"Cook": {
"case_type_name_hints": ["Cook County case type"],
"documents": {
"complaint": {
"filing_type_name_hints": ["Cook County complaint"]
}
}
}
},
"courts": {
"First Municipal District": {
"case_category_name_hints": ["Court-specific category"],
"documents": {
"complaint": {
"filing_type_name_hints": ["Court-specific complaint"],
"document_type_name_hints": ["Court-specific document type"],
"filing_component_name_hints": ["Court-specific lead document"]
}
}
}
}
}
}

County keys match case.county; they may include or omit the word County. Court keys match either the source's case.court_name or the official court name resolved from live metadata. Matching ignores capitalization and ordinary name punctuation. Scoped documents keys must be document IDs declared in the same request. Names remain semantic suggestions: LITEfile only saves a code when exactly one live option matches.

Response, continuation, and retries​

A new receipt returns HTTP 201. An identical retry returns HTTP 200 with the same draft ID and a fresh continuation link:

{
"draft_id": "18427",
"state": "needs_input",
"issues": [
{
"code": "court_code_required",
"path": "court_code",
"message": "Choose the court.",
"view": "extraction_review"
}
],
"continue_url": "https://litefile.example.org/handoff/claim/<expiring-token>/"
}

The browser follows continue_url, signs in to its jurisdiction's account, and explicitly claims the draft. Merely opening a link does not assign ownership. Claim links expire after 24 hours by default; retry the same request to obtain a fresh link. Once claimed, only the owning account can open or edit the draft. Treat the continuation link as a private capability and avoid logging it.

A (source, source_id) identifies one original draft; a (source, idempotency_key) identifies one request. Reusing either identity with different content returns HTTP 409. Retry uncertain network outcomes with the same payload, key, document IDs, and hashes. Do not make a new source ID on timeout. Invalid schemas or PDF hashes return HTTP 400, bad authentication HTTP 401, unauthorized jurisdictions HTTP 403, and unavailable document storage HTTP 503.

Resolve and repair filing details​

Claiming the draft looks up semantic hints against live court lists. The saved answers screen also has a button to repeat that lookup after a court selection. Only a unique name match preselects a value. Ambiguous or unmatched hints stay editable. A code the filer has already chosen is not replaced by another guess.

State YAML can define handoff.filing_intents, with case_category_name_aliases, case_type_name_aliases, filing_type_name_aliases, and documents.<source-document-id>.filing_type_name_aliases. These curated names supplement source hints. The Vermont configuration contains aliases for supporting RFA forms. Court confidentiality choices remain part of filing review.

The receipt preserves original suggestions. Append-only metadata events record live resolutions, user edits and confirmations, clerk corrections, and replacement PDF hashes. Targeted edit links return to the missing-details list, so complete answers do not have to be entered again. Final payment, payload validation, and submission remain the ordinary LITEfile workflow; an empty issues list is not an EFSP acceptance guarantee.

Clerk returns and document corrections​

From a locally submitted filing, choose Copy and review filing. LITEfile checks the court's current status for every filing identifier in that submission. Only confirmed rejected or returned statuses permit a correction revision. Pending, uncertain, partly accepted, and transport-failure outcomes cannot be cloned automatically.

The correction opens at normal Review with the original filing link and clerk feedback. No field-selection questionnaire is required. The draft keeps the same matter, parties, answers, and available documents; missing files stay visible as replacement requirements. Section edits return to the same draft's Review. Payment or waiver must be reconfirmed and fees checked again. Repeating the action resumes the same editable revision without requiring another court status lookup. Final submission checks the source status again. A submitted successor opens as a submission, with its own reference.

Older correction drafts retain their recorded field requirements. Adding an unrelated attachment alone does not satisfy a requirement to replace a PDF.

For substantive PDF changes, the saved interview screen still offers Return to my interview to correct a PDF. A filer without an interview can instead upload the corrected PDF in LITEfile. Either way, the PDF contents correction is complete once a PDF differs from the returned filing. LITEfile adds an expiring litefile_correction parameter to the approved return URL. Docassemble resumes the existing interview. After the filer edits the answers, the sender posts the updated PDFs to /api/handoffs/v1/documents/, with its normal source headers and X-LITEFile-Correction: <token>.

The replacement request uses the original source_id, stable document IDs, updated hashes, and a replacement idempotency key. It sends only the documents that changed, so it can replace a supporting PDF without resending the lead; it can include at most one lead. Document IDs keep working after the filer reorganizes documents in LITEfile. It changes PDF storage references, retains the draft's filing metadata, records the replacement, and invalidates its fee quote. It cannot modify submitted or uncertain attempts. Other source answers in a replacement request do not overwrite the filer's LITEfile edits. Documents removed in LITEfile must be added there again.

Configure the Vermont sender​

In the Docassemble server configuration:

litefile:
enabled: true
base_url: https://litefile.example.org
source: court-interviews
token: a-long-random-secret

This top-level configuration is shared by the Docassemble server's interviews. Staging and production use their own credentials and endpoint. An interview can override litefile_config_name in a later YAML block to select another top-level configuration; its default is "litefile". Migrate an older litefile.rfa configuration by moving its contents up to litefile.

The RFA download screen then offers Continue in LITEfile. The adapter sends the enabled court bundle, excluding the separate next-steps instructions. Its only responsibilities are collecting known facts, hashing and transferring PDFs, source authentication, idempotency, and presenting the continuation link.

Each adaptation includes its own litefile.yml, which imports the reusable transport module. Its data and data from code blocks declare source variable paths, party roles, semantic hints, and document mappings. The reusable helper defaults to the normal AssemblyLine and Docassemble person attributes; an interview can pass a custom fields={...} mapping when its objects differ. The main interview only displays the included litefile_continue_button template; configuration and navigation live in the adapter YAML.

Generic litefile_* variables and events let authors override defaults with later data or code blocks. The shared litefile_send event prepares and saves the AssemblyLine cache, then uses Docassemble's BackgroundAction for the network upload. Its first wait response persists the cache before the worker reads it. An initial routing block consumes the result before the host interview's mandatory blocks run. The worker reads credentials from the selected server configuration, while the background task arguments remain empty.

The Python helper has no interview-specific paths or classifications. It uses AssemblyLine's get_cacheable_documents() and retains that cache with the transfer payload, so retries reuse file handles and hashes without making separate frozen PDF copies. A new correction token starts a new cache.

For isolated local testing, both source configurations can explicitly set allow_insecure_local_development: true. The receiver also requires Django DEBUG=True; production return links still require HTTPS. Use synthetic answers and the dev EFSP, and keep local testing credentials outside version control.

Retain and expire unclaimed data​

A draft exists before the filer claims it, so unclaimed data needs a retention schedule. Preview expired handoffs with:

uv run python manage.py expire_unclaimed_handoffs --days 7

Add --apply to delete those unclaimed receipts, drafts, and private PDFs. Claimed drafts and submission revisions are unaffected. Schedule this command according to the deployment's retention policy; also configure access-log redaction for capability URLs and a storage lifecycle for failed-upload orphans.