Worked implementation guide · reviewed August 23, 2026

Custom schema extraction: from field definition to API response

Dokyumi’s extraction request does not send a JSON schema inline. Create the schema first, then send the document and that schema’s slug to the shared extraction endpoint.

Direct answer

Define named, typed fields in the dashboard; POST a supported file plus the schema slug to/api/v1/extract; then branch on status and inspect both validation arrays before using the returned data.

Step 1

Define the extraction schema

This example mirrors Dokyumi’s canonical field shape. Create it through the dashboard; the public extraction endpoint accepts the resulting slug, not this object as its request body. Supported field types include string, number, currency, date, boolean, enum, array, and object.

Resulting schema definition · invoice-intake
{
  "name": "Invoice Intake",
  "slug": "invoice-intake",
  "description": "Fields used by the AP intake workflow",
  "ocr_mode": "standard",
  "confidence_threshold": 0.8,
  "fields": [
    {
      "key": "vendor_name",
      "label": "Vendor Name",
      "type": "string",
      "required": true,
      "description": "Company or person issuing the invoice"
    },
    {
      "key": "invoice_number",
      "label": "Invoice Number",
      "type": "string",
      "required": true
    },
    {
      "key": "invoice_date",
      "label": "Invoice Date",
      "type": "date",
      "required": true,
      "description": "ISO 8601 date: YYYY-MM-DD"
    },
    {
      "key": "purchase_order_number",
      "label": "Purchase Order Number",
      "type": "string",
      "required": false
    },
    {
      "key": "total_amount",
      "label": "Total Amount",
      "type": "currency",
      "required": true,
      "description": "Final amount due as a number"
    }
  ]
}
The dashboard creation route derives the slug from the schema name. Field keys allow letters, numbers, and underscores; duplicate keys are rejected. The current dashboard creation flow uses the default confidence threshold of 0.8; the public extraction call does not accept a per-request threshold.

Step 2

Send the file and schema slug

The endpoint is synchronous and uses Bearer authentication plus multipart form data. Althoughschema is optional at the protocol level, passing it explicitly avoids the fallback to your first active schema. Direct API calls do not accept a webhook URL; configurable webhook delivery belongs to separate white-label upload sites.

cURL requestPOST /api/v1/extract
curl -X POST https://dokyumi.com/api/v1/extract \
  -H "Authorization: Bearer dk_live_your_api_key" \
  -F "file=@invoice.pdf" \
  -F "schema=invoice-intake"
FieldTypeWhereMeaning
filemultipart fileRequiredA supported PDF or image file, up to 20MB.
schemastringOptional in the protocolThe active schema slug. Pass it explicitly so the request cannot fall back to the organization’s first active schema.
statuscompleted | reviewSuccess responseBranch first. Failures use a non-2xx error envelope, not a failed success status.
dataobjectSuccess responseModel-produced fields. Treat them as accepted only after your validation and review policy.
confidencepartial field mapSuccess responseModel-reported 0–1 values when present; fields can be omitted.
validationobjectSuccess responseIncludes valid, errors, and low_confidence_fields. Inspect both arrays for review results.
metaobjectSuccess responseIncludes processing time, page count, credits used, OCR-cache state, and runtime model identifier.

Step 3

Read the success envelope

The template below assumes a one-page example that passed type validation. Angle-bracket values are placeholders, not literal API values; no timing or model performance is implied. The empty confidence map is valid because reported field scores are partial and may be omitted.

Annotated response template · placeholders are non-literal
{
  "id": "<extraction UUID>",
  "status": "completed",
  "request_id": "<request UUID>",
  "schema": "invoice-intake",
  "data": {
    "vendor_name": "Acme Corp",
    "invoice_number": "INV-2026-001",
    "invoice_date": "2026-08-20",
    "purchase_order_number": null,
    "total_amount": 1250
  },
  "confidence": {},
  "validation": {
    "valid": true,
    "errors": [],
    "low_confidence_fields": []
  },
  "meta": {
    "processing_time_ms": "<measured integer>",
    "page_count": 1,
    "credits_used": 1,
    "ocr_cached": false,
    "model": "<runtime model identifier>"
  }
}

completed

No Zod type-validation errors and no reported confidence values below the schema threshold. It is not a guarantee that every value is correct.

review

At least one validation error or reported below-threshold score. Inspect validation.errors and validation.low_confidence_fields.

non-2xx

The request failed. Read error and code; page-limit errors can also include pages and page_limit.

Step 4

Make review handling part of the integration

Handle the HTTP boundary first, then route successful review results using both sources of review detail. Your business rules can add stricter checks for nulls, required identifiers, totals, or cross-field consistency before writing anywhere downstream.

Server-side JavaScript pattern
const response = await fetch('https://dokyumi.com/api/v1/extract', {
  method: 'POST',
  headers: { Authorization: `Bearer ${process.env.DOKYUMI_API_KEY}` },
  body: formData,
})

if (!response.ok) {
  const failure = await response.json()
  throw new Error(`${failure.code}: ${failure.error}`)
}

const result = await response.json()

if (result.status === 'review') {
  await sendToReviewQueue({
    extractionId: result.id,
    data: result.data,
    validationErrors: result.validation.errors,
    lowConfidenceFields: result.validation.low_confidence_fields,
  })
} else {
  await mapAcceptedFields(result.data)
}

HTTP 400

Missing/invalid file or no active matching schema.

HTTP 402

The post-OCR page count requires more credits than remain.

HTTP 403

The API key scope does not authorize that schema.

HTTP 413

The document exceeds the configured page limit; self-serve plans use 50.

HTTP 429

The configured request limiter or monthly credit quota was reached.

Production checklist

What to verify on your documents

  • Use representative digital PDFs, scans, photos, and layout variants from the workflow you intend to automate.
  • Confirm that field types match downstream expectations; currency and number fields validate as numbers, while date fields use YYYY-MM-DD.
  • Treat null required values and omitted confidence scores according to explicit business rules.
  • Estimate credits with ceil(page_count / 5); one extraction can use more than one credit.
  • Keep API keys server-side and scope keys when a caller should access only selected schemas.
  • Review the security page before using documents with sensitive data, and document your deletion-request process.

Evidence notes

Sources and limitations

Sources used

Limitations

  • The invoice values are a synthetic teaching example, not a customer document or evidence of extraction performance.
  • The response block uses explicit placeholders for request-specific timing and model values and therefore is an annotated template, not literal JSON to paste into a parser.
  • Model-reported confidence is not calibrated accuracy, and an omitted confidence value is not approval.
  • Type validation does not establish source-document truth. Add business checks and human review appropriate to the consequences of a wrong field.

Published and last reviewed August 23, 2026. Product behavior can change; the linked API, pricing, and security pages are the controlling public references.