API Documentation

REST API v1

Overview

REST API for creating and filling signed documents programmatically. All responses are JSON (UTF-8).

Base URL:

https://sign.myzhut.co.il/api/v1

Authentication

Every request requires the header:

Authorization: Bearer <YOUR_API_TOKEN>

Get your token from the profile page. You can regenerate it there if needed.

Never embed the token in client-side code — use it only server-to-server.

Signing flow

The whole process is bound to a single UUID of a signed document:

  1. POST /signed_documents — create the signing instance; receive the UUID and the list of fields.
  2. GET /steps/:uuid — read the fields of the current step.
  3. PATCH /steps/:uuid — fill fields. Once all fields of the step are filled, the server automatically advances current_step.
  4. Repeat 2–3 until status becomes completed.
  5. On completion: the PDF is generated, webhook and email are dispatched.
One UUID = one signed document. Every step shares the same URL — only current_step changes on the server.

Three URLs in the response

A successful POST /signed_documents returns three different URLs. Pick the one matching your use case:

FieldPoints toToken requiredWhen to use
sign_url Web page (edit_wizard/edit_guided/…) No Send to a signer via email / SMS / save to a user profile. They open it in a browser.
step_url PATCH /api/v1/steps/<UUID> Yes (Bearer) Step-aware programmatic fill (step must equal current_step).
fill_url PATCH /api/v1/fill/<UUID> Yes (Bearer) Step-agnostic bulk update — write any fields in one request.

Endpoints

POST /api/v1/signed_documents

Creates a signing instance. Scaffolds empty fields for every step; optionally pre-fills given ones.

Request
{
  "signed_document": {
    "document_id": 7,
    "fields": [
      { "document_field_id": 15, "value": "John Doe" }
    ]
  }
}
Response 201 Created
{
  "id": 123,
  "uuid": "4e7e7aba-eef3-...",
  "document_id": 7,
  "status": "in_progress",
  "created_at": "2026-04-15T09:43:00.000Z",
  "current_step": 1,
  "total_steps": 3,
  "pdf_url": null,
  "sign_url": "https://sign.myzhut.co.il/signed_documents/4e7e7aba-.../edit_wizard",
  "step_url": "https://sign.myzhut.co.il/api/v1/steps/4e7e7aba-...?step=1",
  "fill_url": "https://sign.myzhut.co.il/api/v1/fill/4e7e7aba-...",
  "fields": [
    { "id": 101, "human_name": "Full name", "step": 1, "field_type": "text",   "group_name": null, "value": "John Doe" },
    { "id": 102, "human_name": "Signature", "step": 1, "field_type": "sign",   "group_name": null, "value": null },
    { "id": 103, "human_name": "Text #103", "step": 2, "field_type": "text",   "group_name": null, "value": null }
  ]
}
Response fields
  • sign_url — web URL for the signer (no token needed) — auto-picks the right edit view per fill_type
  • step_url / fill_url — API URLs for programmatic filling (Bearer token required)
  • fields[].idsigned_document_field.id; use this in subsequent PATCH to update the field
  • fields[].human_name — never empty: falls back to "Text #42" style if the template field has no label
  • pdf_urlnull until status=completed
GET /api/v1/steps/:uuid

Returns fields of the current step plus a snapshot of previously completed steps.

Query params (optional)
  • step — request a specific step (must be ≤ current_step, otherwise 403)
Response 200 OK
{
  "uuid": "4e7e7aba-...",
  "current_step": 1,
  "total_steps": 3,
  "all_current_step_filled": false,
  "next_step": null,
  "current_step_fields": [
    { "id": 101, "human_name": "Full name", "field_type": "text", "filled": false,
      "validation": { "required": true, "min_char": 2, "max_char": 60 },
      "position": { "x": 120, "y": 340, "width": 280, "height": 36 } }
  ],
  "previous_steps": []
}
PATCH /api/v1/steps/:uuid

Fills fields of the current step. step must equal current_step — otherwise 403.

When all step fields are filled the server advances current_step automatically. On the last step: status=completed, PDF is generated, webhook and email fire.

Request
{
  "step": 1,
  "fields": [
    { "id": 101, "value": "John Doe" },
    { "id": 102, "value": "data:image/png;base64,iVBORw0KGgo..." }
  ]
}
Response — step not fully filled yet
{ "current_step": 1, "status": "in_progress",
  "next_step_url": "https://sign.myzhut.co.il/api/v1/steps/4e7e7aba-.../show?step=1" }
Response — step closed, more to go
{ "current_step": 2, "status": "in_progress",
  "next_step_url": "https://sign.myzhut.co.il/api/v1/steps/4e7e7aba-.../show?step=2" }
Response — document completed
{ "current_step": 3, "status": "completed",
  "next_step_url": "https://sign.myzhut.co.il/rails/active_storage/blobs/.../signed_document.pdf" }
GET /api/v1/fill/:uuid

Returns all fields split into filled and unfilled, ignoring step ordering.

Response
{
  "uuid": "4e7e7aba-...", "current_step": 2, "status": "in_progress",
  "filled_fields":   [ ... ],
  "unfilled_fields": [ ... ],
  "all_fields_filled": false
}
PATCH /api/v1/fill/:uuid

Step-agnostic update. Writes values for any field by id (including fields from any step). After the update the server checks: if the current step is now fully filled, it advances current_step or completes the document (PDF + webhook + email).

Request
{
  "fields": [
    { "id": 101, "value": "..." },
    { "id": 150, "value": "..." }
  ]
}

Field value formats

field_typeValue
text, mobile, email, personal_numberplain string
date"2026-04-15" (ISO 8601)
sign"data:image/png;base64,iVBORw..." (base64 PNG)
checkbox, radio"true" / "false" (string, not boolean)

Completion

When all fields of the last step are filled (through any endpoint), the server automatically:

  1. Sets status = completed.
  2. Queues PDF generation asynchronously (PdfGenerationJob.perform_later).
  3. POSTs to document.webhook if configured.
  4. Emails document.email with the PDF attached if configured.
  5. Returns next_step_url — a direct link to the generated PDF.

Webhook payload

When a signed document becomes completed, we POST to the URL configured in document.webhook.

Request headers
Content-Type: application/json
User-Agent: MyHatima-Webhook/1.0
Request body
{
  "signed_document": {
    "id": 123,
    "uuid": "4e7e7aba-...",
    "document_id": 15,
    "title": "Contract",
    "status": "completed",
    "fill_type": "wizard",
    "current_step": 3,
    "total_steps": 3,
    "created_at": "2026-04-15T09:30:00.000Z",
    "completed_at": "2026-04-16T11:20:00.000Z",
    "pdf_file": "https://sign.myzhut.co.il/rails/active_storage/blobs/.../signed_document.pdf",
    "signed_document_fields": [
      { "id": 101, "title": "ФИО", "human_name": "ФИО", "field_type": "text",
        "value": "Иван Иванов", "filled": true, "step": 1, "group_name": null },
      { "id": 102, "title": "Подпись", "human_name": "Подпись", "field_type": "sign",
        "value": "data:image/png;base64,iVBORw...", "filled": true, "step": 1, "group_name": null },
      { "id": 103, "title": "Passport", "human_name": "Passport", "field_type": "personal_number",
        "value": "AB1234567", "filled": true, "step": 2, "group_name": "passport" }
    ]
  }
}
Respond with any 2xx to acknowledge. 5xx/timeouts are logged but not retried (v1).
Signature verification (HMAC-SHA256 with X-Webhook-Signature / X-Webhook-Timestamp) is planned but not yet enabled. For now, validate only by expected URL path and payload shape.

Errors

HTTPReason
401Missing or invalid token
403step != current_step in PATCH /steps
404UUID not found
400Document is already completed
422Field validation failed

Web + API mix

The same UUID works in both the API and the web UI:

  • API PATCH /fill/:uuid fills some fields → a signer opens /signed_documents/<UUID>/edit_wizard and completes the rest.
  • And vice versa: start in the UI, finish via the API.
If the signed document was created through the web form and it only has one step, it is marked completed right after the first submit. For a mixed flow create via POST /api/v1/signed_documents.