DKBSignDocs

Core concepts

Workflows

Reusable validation circuits: models, steps, clients, and transactions. Each company is isolated.

Clients

A client is the counterparty the circuit is launched for — not a contacts-book entry. Required fields on create: name (last name), firstname, cni_number, phone, email (unique per company), motif_demande.

POST /api/clients/create always inserts. POST /api/clients/ensure is idempotent on email: existing → 200 { created: false, client: { id } }; new → 201 { created: true, client: { id } }. Company admins can bulk-import up to 1000 rows on POST /api/clients/import (existing emails are skipped).

Models and steps

  1. POST /api/workflows/models/create — name, description optional, signature_level optional (simple or advanced)
  2. POST /api/workflows/models/{model}/steps/create — name, type (unidirectionnel or conditionnel), users[], roles[] optional, actions[] optional, for example [{ "libelle": "Signer", "action": "sign" }]
  3. POST .../steps/configs/create — saves the graph and finalizes the model. Unidirectional steps need next_step_id. Conditional steps need yes_next_step_id and no_next_step_id

Too many finalized models → 403 MODEL_LIMIT_REACHED with limit / used. Changing signature_level on a completed model is company-admin only. After a workflow is launched, client_id / model_id cannot change (409 WORKFLOW_STRUCTURE_LOCKED).

Running a workflow

  1. POST /api/workflows/create — multipart: name, model_id, optional client_id / description, and files[] (PDFs, max 10 MB each)
  2. An actor calls GET /api/workflows/transactions/{transaction}/take (403 STEP_NOT_CANDIDATE if they are not assigned)
  3. Then POST /api/workflows/transactions/step/process
json
{
  "transaction_id": 44,
  "actions": [{ "action": "validate" }],
  "condition": "yes"
}

actions is an array (not a single action string). It may be sent as a JSON string on multipart. Status moves pending → in_progress → completed / cancelled.

Other outcomes: .../process/cancelled (motif_refus), .../return and .../return-to-initiator (motif_retour), then POST /api/workflows/{workflow}/relaunch with new files[].

Step actions

ActionPayload
validateApprove the step. No data required.
signAlso send JSON strings signers_data and signature_params (zones per file_id). Optional signature_appearance PNG data-URL. signature_level is frozen on the instance.
stampPlace via data.documents[].pages[].elements (type: stamp). Image comes from the user’s stored stamp or multipart imgStamp.
qr_codeQR content is the document URL (the element value is ignored).
text / date / initialselements[].type plus value, position, size
json
{
  "documents": [
    {
      "file_id": 123,
      "pages": [
        {
          "page": 1,
          "elements": [
            {
              "type": "text",
              "value": "Approved",
              "position": { "x": 10, "y": 20 },
              "size": { "width": 100, "height": 20 }
            }
          ]
        }
      ]
    }
  ]
}

LDAP

Company admins configure the directory on PUT /api/companies/{company}/ldap/save (ldap_host, ldap_base_dn, bind credentials, ldap_role_mode = default or ad_groups). Bind password is never returned. Map AD groups with PUT .../ldap/role-mappings.

  • Import creates or updates users from AD and never disables missing accounts. 202 — poll .../import/latest
  • Sync updates existing LDAP users and disables those gone from AD (it never deletes rows). Poll .../sync/latest

Job status: pending → processing → completed / failed, plus stats and error. Targeted variants accept emails[] (import, 1–100) or user_ids[] (sync, 1–100).