Skip to main content
Formalingo

.NET SDK

Install and use the official Formalingo .NET SDK.

.NET SDK

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

Installation

dotnet add package Formalingo.Sdk

Setup

using Formalingo.Sdk;
using Formalingo.Sdk.Generated.Models;

var client = FormalingoClientFactory.CreateClient("af_live_YOUR_KEY");

To use a custom base URL (e.g. for local development):

var client = FormalingoClientFactory.CreateClient(
    "af_live_YOUR_KEY",
    "http://localhost:3000"
);

Forms

List forms

var forms = await client.Api.V1.Forms.GetAsync();

Create a form

var form = await client.Api.V1.Forms.PostAsync(new() {
    Title = "Customer Satisfaction Survey",
    Description = "Help us improve our service.",
});

Get a form

var form = await client.Api.V1.Forms["FORM_ID"].GetAsync();

Update a form

var form = await client.Api.V1.Forms["FORM_ID"].PutAsync(new() {
    Status = "published",
});

Delete a form

await client.Api.V1.Forms["FORM_ID"].DeleteAsync();

Sections

// List sections
var sections = await client.Api.V1.Forms["FORM_ID"].Sections.GetAsync();

// Create a section
var section = await client.Api.V1.Forms["FORM_ID"].Sections.PostAsync(new() {
    Title = "Personal Information",
});

Questions

// Create a question
var question = await client.Api.V1.Forms["FORM_ID"].Questions.PostAsync(new() {
    QuestionText = "What is your full name?",
    Type = "short_text",
    IsRequired = true,
});

// Create a multiple choice question
var mcq = await client.Api.V1.Forms["FORM_ID"].Questions.PostAsync(new() {
    QuestionText = "How did you hear about us?",
    Type = "mcq",
    Options = new() {
        Choices = new List<string> { "Social media", "Friend", "Search engine", "Other" },
    },
});

Recipients

// Create a recipient with pre-fill
var recipient = await client.Api.V1.Forms["FORM_ID"].Recipients.PostAsync(new() {
    Label = "John Doe",
    Email = "john@acme.com",
    Prefill = new Dictionary<string, string> {
        ["question-uuid-1"] = "John Doe",
        ["question-uuid-2"] = "Acme Corp",
    },
});

Console.WriteLine(recipient.Link);
// → https://www.formalingo.com/f/TOKEN

// Bulk create with one caller-owned retry key for the exact request
var bulkBody = new BulkPostRequestBody {
    ConfirmBulk = true,
    Recipients = [
        new BulkPostRequestBody_recipients {
            Label = "Alice",
            Email = "alice@example.com",
        },
    ],
};
var recipients = await FormalingoClientFactory.CreateBulkRecipientsAsync(
    client,
    Guid.Parse("00000000-0000-0000-0000-000000000001"),
    bulkBody,
    "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

await client.Api.V1.Forms["FORM_ID"].Branding.PutAsync(new() {
    PrimaryColor = "#6366F1",
    WelcomeHeading = "Welcome!",
    ThankYouHeading = "Thank you!",
    ThankYouMessage = "We appreciate your feedback.",
});

Documents

// List documents
var docs = await client.Api.V1.Documents.GetAsync();

// Create a submission with signers
var body = new CreateSubmissionBody {
    Signers = [
        new SignerInput {
            Role = "signer_1",
            Name = "John Doe",
            Email = "john@acme.com",
            Prefill = new SignerInput_prefill {
                AdditionalData = new Dictionary<string, object> {
                    ["field-uuid-1"] = "John Doe",
                },
            },
            PrefillReadonly = true,
        },
    ],
};
var submission = await FormalingoClientFactory.CreateDocumentSubmissionAsync(
    client,
    Guid.Parse("00000000-0000-0000-0000-000000000001"),
    body,
    "document-create-7f3f");

Console.WriteLine(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 {
    var form = await client.Api.V1.Forms["non-existent"].GetAsync();
} catch (ApiException ex) {
    Console.Error.WriteLine($"API error ({ex.ResponseStatusCode}): {ex.Message}");
}