Skip to main content
Formalingo

Python SDK

Install and use the official Formalingo Python SDK.

Python SDK

The formalingo-sdk package provides a type-safe client for the Formalingo API, generated with Microsoft Kiota.

Installation

pip install git+https://github.com/Formalingo/sdk-python.git

Or with uv:

uv pip install git+https://github.com/Formalingo/sdk-python.git

Setup

from formalingo import create_client

client = create_client("af_live_YOUR_KEY")

The create_client helper wires up authentication and the HTTP adapter automatically. You can optionally pass a custom base URL:

client = create_client("af_live_YOUR_KEY", base_url="https://staging.formalingo.com")

Note: The Kiota-generated client includes the full API path: client.api.v1.forms, client.api.v1.documents, etc.

Forms

List forms

forms = await client.api.v1.forms.get()

Create a form

from formalingo.models.create_form_body import CreateFormBody

body = CreateFormBody()
body.title = "Customer Satisfaction Survey"
body.description = "Help us improve our service."

form = await client.api.v1.forms.post(body)

Get a form

form = await client.api.v1.forms.by_form_id("FORM_ID").get()

Update a form

from formalingo.models.update_form_body import UpdateFormBody

body = UpdateFormBody()
body.status = "published"

form = await client.api.v1.forms.by_form_id("FORM_ID").put(body)

Delete a form

await client.api.v1.forms.by_form_id("FORM_ID").delete()

Sections

# List sections
sections = await client.api.v1.forms.by_form_id("FORM_ID").sections.get()

# Create a section
from formalingo.models.create_section_body import CreateSectionBody

body = CreateSectionBody()
body.title = "Personal Information"

section = await client.api.v1.forms.by_form_id("FORM_ID").sections.post(body)

Questions

from formalingo.models.create_question_body import CreateQuestionBody

# Create a text question
body = CreateQuestionBody()
body.question_text = "What is your full name?"
body.type = "short_text"
body.is_required = True

question = await client.api.v1.forms.by_form_id("FORM_ID").questions.post(body)

Recipients

from formalingo.models.create_recipient_body import CreateRecipientBody

body = CreateRecipientBody()
body.label = "John Doe"
body.email = "john@acme.com"
body.prefill = {
    "question-uuid-1": "John Doe",
    "question-uuid-2": "Acme Corp",
}

recipient = await client.api.v1.forms.by_form_id("FORM_ID").recipients.post(body)
print(recipient.link)
# → https://www.formalingo.com/f/TOKEN

# Bulk create with one caller-owned retry key for the exact request
from uuid import UUID
from formalingo import create_bulk_recipients
from formalingo.api.v1.forms.item.recipients.bulk.bulk_post_request_body import BulkPostRequestBody
from formalingo.api.v1.forms.item.recipients.bulk.bulk_post_request_body_recipients import BulkPostRequestBody_recipients

bulk_body = BulkPostRequestBody(
    confirm_bulk=True,
    recipients=[
        BulkPostRequestBody_recipients(
            label="Alice",
            email="alice@example.com",
        ),
    ],
)
recipients = await create_bulk_recipients(
    client,
    UUID("00000000-0000-0000-0000-000000000001"),
    bulk_body,
    "recipient-bulk-create-7f3f",
)

The idempotency key is required. Reuse it only when retrying the exact same serialized request body. On idempotency_request_in_progress, retry the exact body with the same key. A different body returns idempotency_key_conflict; recipient erasure returns idempotency_replay_unavailable.

Branding

from formalingo.models.branding_update_request import BrandingUpdateRequest

body = BrandingUpdateRequest()
body.primary_color = "#6366F1"
body.welcome_heading = "Welcome!"
body.thank_you_heading = "Thank you!"

await client.api.v1.forms.by_form_id("FORM_ID").branding.put(body)

Documents

# List documents
docs = await client.api.v1.documents.get()

# Create a submission
from uuid import UUID

from formalingo import create_document_submission
from formalingo.models.create_submission_body import CreateSubmissionBody
from formalingo.models.signer_input import SignerInput
from formalingo.models.signer_input_prefill import SignerInput_prefill

prefill = SignerInput_prefill(
    additional_data={"field-uuid-1": "John Doe"},
)
signer = SignerInput(
    role="signer_1",
    name="John Doe",
    email="john@acme.com",
    prefill=prefill,
    prefill_readonly=True,
)

body = CreateSubmissionBody(signers=[signer])

submission = await create_document_submission(
    client,
    UUID("00000000-0000-0000-0000-000000000001"),
    body,
    "document-create-7f3f",
)
print(submission.signers[0].link)
# → https://www.formalingo.com/d/TOKEN

The required idempotency key makes retries safe. The helper unwraps the API envelope so submission.signers comes from response.data.signers.

Error Handling

try:
    form = await client.api.v1.forms.by_form_id("non-existent").get()
except Exception as error:
    print(f"API error: {error}")