← Back to blog

Build a Custom Document Extractor for Make.com

Create a Cryvis custom extractor schema in Console, then call POST /v1/custom-extractors/:slug from Make.com HTTP with multipart file.

A custom extractor is a document type you own: JSON Schema in the Cryvis Console, production URL of the form POST https://api.cryvis.com/v1/custom-extractors/<slug>, multipart field file. Make.com does not need a Cryvis app—HTTP — Make a Request is enough.

This walkthrough goes Console → first successful Make run. Schema deep-dive: Custom extractor schemas. Product: Custom Document Extraction. Hub: Make.com + Cryvis.

Prerequisites

  • Cryvis account with credits (pricing / Console billing)
  • API key from Console → API keys
  • A sample PDF or image of the real document
  • Make scenario editor access

Part A — Console schema

1. Create the extractor

Open Console → New extractor:

  1. Name — human label (Bill of lading).
  2. Document description — short prompt cue (ocean bill of lading, equipment inspection form). Vague descriptions produce vague extractions.
  3. Schema — root must be a JSON Schema object.

2. Schema rules that matter in Make

RuleWhy Make cares
Max ~100 propertiesKeep Sheets columns manageable
Prefer ["string","null"]Missing fields become null, not hard crashes
x-cryvis-validation: soft / hardSoft → 200 + warnings; hard → 422
additionalProperties: falseStable data keys for mapping
No $ref / oneOf / anyOfUnsupported—flatten instead

Example inspection-form schema:

{
  "type": "object",
  "properties": {
    "form_id": {
      "type": ["string", "null"],
      "description": "Form or job number printed at top",
      "pattern": "^[A-Z0-9-]+$",
      "x-cryvis-validation": "hard"
    },
    "inspected_at": {
      "type": ["string", "null"],
      "format": "date",
      "description": "Inspection date YYYY-MM-DD",
      "x-cryvis-validation": "soft"
    },
    "site_name": {
      "type": ["string", "null"],
      "description": "Site or facility name",
      "x-cryvis-validation": "soft"
    },
    "passed": {
      "type": ["boolean", "null"],
      "description": "Overall pass/fail if explicitly stated",
      "x-cryvis-validation": "soft"
    },
    "defects": {
      "type": ["array", "null"],
      "description": "Listed defects",
      "items": {
        "type": "object",
        "properties": {
          "code": {
            "type": ["string", "null"],
            "description": "Defect code"
          },
          "note": {
            "type": ["string", "null"],
            "description": "Defect description"
          }
        },
        "additionalProperties": false
      },
      "x-cryvis-validation": "soft"
    }
  },
  "required": ["form_id"],
  "additionalProperties": false
}

3. Test upload in Console

Upload the sample. Confirm:

  • success: true
  • data.form_id populated
  • meta.document_type looks like custom:<slug>
  • Warnings acceptable for soft fields

Copy the slug (short path id). That string is the only path segment Make needs.

Part B — Make HTTP call

Trigger (Drive / Gmail / Manual)
        |
        v
Download binary
        |
        v
HTTP POST https://api.cryvis.com/v1/custom-extractors/<slug>
  Header: Authorization: Bearer sk_live_...
  Body: multipart
    file = <binary>
        |
        v
Map data.* → destination

HTTP — Make a Request settings

  1. URLhttps://api.cryvis.com/v1/custom-extractors/YOUR_SLUG (no trailing slash gymnastics; replace slug exactly).
  2. Method — POST.
  3. HeadersAuthorization = Bearer {{key}}. Prefer a shared data store or Make connection pattern (Bearer auth).
  4. Body type — Multipart/form-data.
  5. Fields — Name: file, Type: File, Data: map binary, File name: original name.
  6. Parse response — Yes.

Curl equivalent for debugging outside Make:

curl -X POST "https://api.cryvis.com/v1/custom-extractors/YOUR_SLUG" \
  -H "Authorization: Bearer sk_live_..." \
  -F "file=@sample.pdf"

Part C — Map arrays and validation

defects is an array. In Make:

  • Use an Iterator on data.defects to create one Sheets row per defect, or
  • Use map() / join() to collapse codes into a single cell.

meta.validation.warnings is also an array—send to Slack when length > 0 even if HTTP succeeded.

Nested mapping detail: Map API JSON fields. Response envelopes: Parse API JSON responses.

Soft vs hard failures in the scenario

HTTP custom extractor
   |
   +-- 200, warnings empty -----> write destination
   |
   +-- 200, warnings present ---> Slack review + write (or hold)
   |
   +-- 422 VALIDATION_ERROR ----> Error Handler Break
   |
   +-- 401 / 402 ---------------> Error Handler Break + alert

Error handling playbook: Handle API errors.

Iterate on the schema without rewriting Make

You can add optional nullable fields and tighten patterns in Console. Make keeps working as long as you do not rename or remove keys the scenario maps. Treat schema keys like a public API for your own automations.

When you only need a subset of fields in Sheets, still extract them in schema if useful for review—but map only required columns (specific fields).

Built-in vs custom reminder

If the document is an invoice, do not build a custom invoice schema—use Invoice API. Custom extractors exist for the long tail. Decision guide: Extract PDF data. End-to-end JSON → Sheets: Convert PDFs to JSON.

Checklist

  • Console test upload succeeds with real sample
  • Slug pasted into Make URL
  • Multipart field name is file
  • Bearer key scoped / rotatable
  • Iterator planned for array fields
  • Error Handler on HTTP module

Ship the Console schema first, then the Make module—never invent fields in the HTTP response mapping that the schema does not declare.