DocBloc Logo
  • Home
  • Releases
  • Pricing
  • Contact

Loading...

Integrating

  • Overview
  • Quickstart
  • Headless
  • Redirect
  • Iframe embed
  • Native component

Headless

DocBloc emails the signer a link, they sign on our page, and a webhook tells you when it is done. Your product needs no signing UI at all.

Keep your own copy of signed documents

DocBloc deletes a submission and its signed file 30 days after the submission's expiry window elapses — not 30 days after signing. A submission with a 14 day signing window is removed 44 days after it was created, whether it was signed on day one or day fourteen.

If you need the document for longer, retrieve and store it yourself when submission.completed arrives. That event carries everything needed to fetch it.

When to use it

When signing is something that happens to a record rather than a step someone is walking through in your product. A compliance document, a supplier agreement, a policy acknowledgement. It is the least code of any mode and the least that can go wrong.

1. Create the submission

Reference your own record with externalReference. DocBloc indexes it, returns it on every read and carries it in every webhook — it is how the two systems reconcile without you storing a mapping table, though storing the submission id as well means you can go in either direction.

var submission = await docBloc.SubmissionAsync(templateId, new CreateSubmissionDTO
{
    ExpiryInMinutes = 60 * 24 * 14,
    Emails = new Dictionary<int, string> { [1] = employee.Email },
    ExternalReference = $"compliance-{record.Id}",
    Metadata = new Dictionary<string, string> { ["branch"] = branch.Name },

    // Anything you already know. Only the signature genuinely needs collecting.
    FieldValues = new Dictionary<string, string>
    {
        ["employee_name"] = employee.FullName,
        ["issued_date"] = DateTime.UtcNow.ToString("dd/MM/yyyy"),
    },
});

The submission comes back ready to sign, with the first recipient already active. DocBloc has already emailed them — you do not need to send anything.

2. Receive the webhook

[HttpPost("webhook")]
[AllowAnonymous]
public async Task<IActionResult> Receive()
{
    using MemoryStream buffer = new();
    await Request.Body.CopyToAsync(buffer);
    byte[] rawBody = buffer.ToArray();

    if (!_verifier.IsValid(rawBody,
            Request.Headers[DocBlocWebhookVerifier.SignatureHeader],
            Request.Headers[DocBlocWebhookVerifier.TimestampHeader]))
    {
        return Unauthorized();
    }

    var e = JsonSerializer.Deserialize<DocBlocEvent>(rawBody);

    // Ignore what you do not recognise rather than failing on it - DocBloc may add event types,
    // and a 4xx makes it retry something you simply do not want.
    if (e?.Type is "submission.completed" or "submission.declined")
    {
        _queue.Enqueue(() => Handle(e));
    }

    return Ok();
}

Answer promptly and do the work behind it. Fetching the signed PDF and storing it is far too slow to do on the request thread.

3. Take custody of the document

var signed = await docBloc.SignedAsync(externalReference);

await _files.Store(signed.Stream, $"compliance-{record.Id}.pdf");
record.FileReferenceId = fileReference.Id;

This step is not optional. See the warning at the top of this page.

Being idempotent

A retried delivery must not advance the record twice. The simplest correct approach is to record which events you have processed and skip repeats:

if (await _processed.Contains(e.SubmissionId, e.Type))
{
    return;
}

// ... do the work

await _processed.Record(e.SubmissionId, e.Type);

DocBloc

Secure, simple, and compliant e-signatures for modern businesses.

Product

  • Features
  • Pricing

Resources

  • Release Notes
  • API Docs

© 2026 DocBloc. All rights reserved.

PrivacyTerms