doclinc โ€” API Integration Guide
REST API ยท JWT HS256 ยท 2FA Authentication

doclinc API Integration Guide

The doclinc API lets you create secure document transfer transactions, upload files to signed URLs, and trigger an email notification with recipient-side 2FA authentication.

4 steps Create JWT โ†’ create transaction โ†’ upload document โ†’ confirm transaction
SMS / voice / secret recipient authentication methods
Zero attachments recipient accesses via a secure link, not an email attachment

Overview

Functional scope of the API within a confidential document sending workflow.

Context

What the API does

  • Creates and manages document transfer transactions.
  • Generates signed upload URLs per document.
  • Produces an HTML banner to embed in the sender's email (optional).
  • Authenticates the recipient via SMS, voice call, or secret question before granting access to the document.

What the API does not do

  • Does not send emails (when in self-send mode) โ€” the sender uses their own SMTP infrastructure.
  • Does not manage email layout (when in self-send mode) โ€” only the HTML banner is provided.
  • Does not store documents indefinitely โ€” the link expires according to linkExpirationDays.
Key point: When the subscription is created, the API is configured to either let the client
send their own email (known as self-send mode) or emails can be automatically sent by the
API at transaction confirmation (known as auto-send mode). In self-send mode, the sender retains full control over the email experience โ€” sender address, subject, and message body. doclinc provides only the secure layer, the storage, and the recipient authentication flow.

4-Step Flow

Every confidential document sent follows this process, from the authorization token creation through to confirmation.

Overview
1

Create the JWT token

Generate a one-time HS256-signed JWT containing your tenantId and your private API key.

2

Create the transaction

Submit the recipient's information and the document name. The API returns a secure upload URL and an HTML banner (if in self-send mode).

3

Upload the document

Upload the file to the secure channel via the temporary URL provided (valid for urlTimeToLive seconds).

4

Confirm & send

Confirm the transaction, then embed the HTML banner in your email and send it through your own mail server (if in self-send mode).

Prerequisites

Credentials to obtain from doclinc and information required for each recipient.

Setup
Tenant identifier
tenantId
Identifies your organization within the doclinc system. Provided at subscription.
Secret API key
apiKey
Used to sign JWT tokens. Store in a secrets manager โ€” never in source code.

Per recipient

  • Email address
  • Mobile or landline phone number
  • ISO country code (e.g. CA for Canada)
  • Authentication method: sms or voice

Authentication methods

Two options are available depending on your context:

  • SMS / voice call โ€” via /transactions/cells
  • Shared secret โ€” via /transactions/secrets (e.g. employee number)
โš ๏ธ Security: Never store your API key in source code. Use environment variables or a secrets manager (Azure Key Vault, AWS Secrets Manager, etc.).

Happy path โ€” SMS send

Nominal API call sequence for sending a confidential document to a recipient with SMS authentication.

Happy path

1 Create and sign the authorization token

Build an HS256 JWT from your tenantId and a unique identifier (jti), encode it in Base64, and sign it with your doclinc API key. This token is valid for at most 2 hours and must be recreated for each transaction.

// JWT header
{
  "alg": "HS256",
  "typ": "JWT"
}

// JWT body (payload)
{
  "tenantId": "BA686425FBF403B23F3FC4ABE5A98A",
  "jti":      "pay-1773793968",  // prefix + Unix timestamp
  "iat":      1773793968,         // issued at (GMT)
  "exp":      1773801168          // expiry โ‰ค iat + 7200 s
}

// API key (fictional example)
F1F5BCBE71F46FC5E704E53469F5A77A55646F293E6568EA5F978FA6A4629450

// Resulting signed token (Base64)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZW5hbnRJ
ZCCI6IkJBNjg2NDI1RkJGNDAzQjIzRjNGQzRBQkU1QTk4QSIs
Imp0aSI6InBheS0xNzczNzkzOTY4IiwiaWF0IjoxNzczNzkzOT
Y4LCJleHAiOjE3NzM4MDExNjh9.63NKWGi7Zt1Xn9kfkeh9ku
02CxZ0w1fUFq3BgPhz5jM

Important rules

  • The jti field must be unique on every call. Use a fixed prefix followed by the Unix timestamp (e.g. "pay-" + Date.now()).
  • The expiry (exp) cannot exceed 2 hours after iat.
  • Encode in Base64 and sign with your API key.
  • A token used once is automatically revoked.

2 Create the transaction

Submit the recipient's information (email, phone number) and the document name. The API returns a secure upload URL unique per document, an HTML banner to embed in your email, as well as the confirm and cancel commands.

POST /transactions/cells
// Header โ€” use the token generated in step 1
Authorization: Bearer eyJhbGciOiJIUzI1Ni...

// Request body
{
  "transactionType":        "send",
  "transactionLanguageRef": "FR", // sender-side language
  "subjectLanguageRef":     "FR", // recipient-side language
  "linkExpirationDays":     14,   // link validity (days)
  "isLinkReusable":         true,
  "contacts": [
    {
      "recipientEmail":      "recipient@example.com",
      "countryCode":         "CA",
      "recipientCell":       "8191234567",
      "authenticationMethod": "sms"
    }
  ],
  "documents": [ // multiple documents supported
    {
      "name": "pay-stub-2026-01-01.pdf"
    }
  ]
}
// API response
{
  "sendTransaction": {
    "documents": [
      { // unique URL per document
        "url": "https://uploadDomain/...",
        "urlTimeToLive": 3600
      }
    ]
  },
  // HTML banner to add to the email
  "banner": "<HTML>...</HTML>",
  "commands": [
    {
      "href":   "/transactions/cell/6c89a4fd23ae1224d0b754a551bf755a6c35",
      "method": "POST",
      "rel":    "Confirm" // confirm with this endpoint
    },
    {
      "href":   "/transactions/cell/6c89a4fd23ae1224d0b754a551bf755a6c35",
      "method": "Delete",
      "rel":    "Cancel"
    }
  ]
}

About documents

  • One or more documents can be included in a single transaction.
  • Each document receives its own unique upload URL.
  • The HTML banner replaces email attachments โ€” it contains the secure download link.

About commands

  • Both commands allow you to confirm or cancel the entire transaction.
  • Documents from an unconfirmed transaction are not accessible to the recipient.
  • A transaction can be cancelled even after confirmation.

3 Upload the confidential document

Upload the documents using the URLs received in step 2, via your language's native HTTP library. Use one URL per document, in the same order as specified in the transaction request.

PUT {url returned in step 2}
// cURL example
curl -X PUT \
  "https://beta-prod-documenttransfer.s3.ca-central-1.amazonaws.com/..." \
  --upload-file "./confidential-document.pdf"

URL validity period

The upload link is valid for the period defined by urlTimeToLive (3,600 seconds in this example). Using the link after this period will result in an error. Perform the upload immediately after creating the transaction.

Size limits

Your subscription enforces a limit on the total document size per transaction. This limit applies to the sum of all uploaded files and is checked at confirmation time (step 4).

Important: the document is never transmitted by email. It is stored securely and is only accessible after the recipient has completed 2FA authentication from the banner in your email.

4 Confirm the transaction

Once the document has been uploaded, confirm the transaction using the dynamic href from the Confirm command received in step 2. Confirmation returns 200 OK. Then embed the HTML banner in your email body and send it through your own mail infrastructure.

POST /transactions/cell/6c89a4fd23ae1224d0b754a551bf755a6c35
// cURL example โ€” use the dynamic href received in step 2
curl -X POST \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  "https://api.doclinc.io/transactions/cell/6c89a4fd23ae1224d0b754a551bf755a6c35"

Alternate path โ€” Look up an existing contact

The API automatically saves recipient contact details with each transaction. You can look up this information before creating a new transaction.

ALTERNATE PATH

Using GET /transactions/contacts/{email}

This endpoint returns the preferred language, mobile authentication method, and stored secret information for a given recipient. These values can be used directly when creating the next transaction, notably the secretAnswerRef field to reuse an existing secret.

If the contact is not found, the endpoint returns 404.

GET /transactions/contacts/{email}
// Example
GET /transactions/contacts/recipient@example.com

// Sample response
{
  "languageRef": "EN",
  "cellContact": {
    "countryCode":         "CA",
    "cell":                "8191234567",
    "authenticationMethod": "sms"
  },
  "secretContact": { // may be empty
    "secretQuestion":  "Employee number ?",
    "secretAnswerRef": "5a7574b08771edfc1ba8c87493dfd01a45424c57"
    // Encrypted reusable answer if it exists
  }
}

Alternate path โ€” Shared secret authentication

An alternative to phone-based authentication: the recipient answers a secret question to access the document.

ALTERNATE PATH

secretAnswer โ€” new secret

Used to set a new password for the transaction. The value is transmitted in plain text in the request and stored encrypted by the API.

secretAnswerRef โ€” pre-registered secret

Used to reuse an existing secret. The value is obtained via GET /transactions/contacts/{email} โ€” it is the already-stored encrypted value.

POST /transactions/secrets
{
  "transactionType":        "send",
  "transactionLanguageRef": "EN",
  "subjectLanguageRef":     "EN",
  "linkExpirationDays":     14,
  "isLinkReusable":         true,
  "secretQuestion":         "What is your employee number?",
  "contacts": [
    {
      "recipientEmail": "recipient@example.com",
      "secretAnswer":   "EMP-00142",  // new secret โ€” OR null if secretAnswerRef provided
      "secretAnswerRef": null            // encrypted ref obtained via GET /contacts
    }
  ],
  "documents": [
    { "name": "pay-stub-2026-01-01.pdf" }
  ]
}
Note: either secretAnswer or secretAnswerRef is provided โ€” never both simultaneously. The rest of the flow (upload + confirmation) is identical to the happy path. This method is temporarily limited to one recipient per transaction.

Full API Reference

All available endpoints with their response codes.

Reference

Retrieve recipient contact details

Returns pre-registered authentication information for a contact. The API automatically saves recipient contact details with each transaction created โ€” this endpoint allows you to look them up before creating a new transaction.

GET /transactions/contacts/{email}
// Example
GET /transactions/contacts/recipient@example.com

// Sample response
{
  "languageRef": "FR",
  "cellContact": {
    "countryCode":         "CA",
    "cell":                "8191234567",
    "authenticationMethod": "sms"
  },
  "secretContact": { // may be empty
    "secretQuestion":  "Employee number ?",
    "secretAnswerRef": "5a7574b08771edfc1ba8c87493dfd01a45424c57"
    // Encrypted reusable answer if it exists
  }
}
CodeStatusDescription
200SUCCESSOK
401UNAUTHORIZEDInvalid authorization
404NOT FOUNDContact not found
461INVALID SUBInvalid subscription
500SERVER ERRORUnexpected error

Create a transaction โ€” Phone authentication

Initializes a secure transaction with SMS or voice call authentication. Returns upload URLs for each document and the transaction identifier.

POST /transactions/cells
// Request body
{
  "transactionType":        "send",
  "transactionLanguageRef": "EN",  // sender interface language
  "subjectLanguageRef":     "EN",  // recipient interface language
  "linkExpirationDays":     14,   // link validity (days)
  "isLinkReusable":         true,
  "contacts": [
    {
      "recipientEmail":       "recipient@example.com",
      "countryCode":          "CA",   // ISO country code
      "recipientCell":        "8191234567",   // phone for 2FA
      "authenticationMethod": "sms"  // "sms" or "voice"
    }
  ],
  "documents": [
    { "name": "Confidential-document.pdf" }
  ]
}

// Response
{
  "sendTransaction": {
    "documents": [
      {
        "url":           "https://uploadDomain/...",
        "urlTimeToLive": 3600  // seconds
      }
    ]
  },
  "banner":   "Html code to insert in email",
  "commands": [
    { "href": "/transactions/cell/{id}", "method": "POST",   "rel": "Confirm" },
    { "href": "/transactions/cell/{id}", "method": "Delete",  "rel": "Cancel"  }
  ]
}
CodeStatusDescription
201CREATEDOK
400BAD REQUESTInvalid JSON or incorrect country code / phone number
401UNAUTHORIZEDInvalid authorization
461INVALID SUBInvalid subscription
463DUPLICATEDuplicate phone number in the list
470FEATURE NOT AVAILABLEFeature not included in your plan
500SERVER ERRORUnexpected error

Create a transaction โ€” Shared secret authentication

Initializes a secure transaction with secret question authentication. Provide either secretAnswer (new secret) or secretAnswerRef (pre-registered secret) โ€” never both. Limited to one recipient per transaction.

POST /transactions/secrets
// Request body
{
  "transactionType":        "send",
  "transactionLanguageRef": "EN",  // sender interface language
  "subjectLanguageRef":     "EN",  // recipient interface language
  "linkExpirationDays":     14,
  "isLinkReusable":         true,
  "secretQuestion":         "What is your employee number?",
  "contacts": [
    {
      "recipientEmail":  "recipient@example.com",
      "secretAnswer":   "EMP-00142",  // new secret
      "secretAnswerRef": null            // OR encrypted ref via GET /contacts
    }
  ],
  "documents": [
    { "name": "confidential-document.pdf" }
  ]
}

// Response โ€” same structure as /transactions/cells
{
  "sendTransaction": {
    "documents": [
      {
        "url":           "https://uploadDomain/...",
        "urlTimeToLive": 3600
      }
    ]
  },
  "banner":   "Html code to insert in email",
  "commands": [
    { "href": "/transactions/cell/{id}", "method": "POST",   "rel": "Confirm" },
    { "href": "/transactions/cell/{id}", "method": "Delete",  "rel": "Cancel"  }
  ]
}
CodeStatusDescription
201CREATEDOK
400BAD REQUESTInvalid request body
401UNAUTHORIZEDInvalid authorization
461INVALID SUBInvalid subscription
470FEATURE NOT AVAILABLEFeature not included in your plan
500SERVER ERRORUnexpected error

โœ“ Confirm a transaction

POST /transactions/{id}
CodeStatusDescription
200SUCCESSTransaction confirmed
401UNAUTHORIZEDInvalid authorization
404NOT FOUNDTransaction or document not found
465DOCUMENT SIZE EXCEEDEDTotal document size exceeded
500SERVER ERRORUnexpected error

โœ• Cancel a transaction

Cancels the transaction. Note that it is permitted to cancel a transaction even after confirmation.

DELETE /transactions/{id}
CodeStatusDescription
204DELETEDTransaction successfully cancelled
401UNAUTHORIZEDInvalid authorization
404NOT FOUNDTransaction not found
500SERVER ERRORUnexpected error