Skip to content
Website

Create Document

Upload invoice files with Base64URL encoding and follow their processing status.

POST/api/v1_2/documents

To create a new Document send POST request with body containing a JSON hash of the required fields. The file content must be encoded as URL-safe base64 string (Base64URL in validator https://base64.guru/tools/validator). Online Base64 encoder https://www.base64encode.org/

Only one file per document is allowed, but you can create multiple documents in one request or post files in compressed archive.

In case of multipage file with enabled split max 200 pages are allowed.

For each new created document is returned document id. All created documents are automatically queued for processing.

Big files (big request bodies) can lead to timeouts or unreasonable response times. Rule of thumb is to keep the size of uploaded data under 20MB.

Supported file formats

Format Description
PDF Containing text or scanned documents
* single page PDF document, multipage PDF document, multiple documents in PDF
TIFF, JPEG, PNG image, color/grayscale/b&w
ZIP containing file formats see above
RAR containing file formats see above
7ZIP containing file formats see above

File content types

Set each file’s content_type to the matching MIME type. The enclosing JSON request uses Content-Type: application/json.

File format Content type
PDF application/pdf
JPEG image/jpeg
PNG image/png
TIFF image/tiff
ZIP application/zip
RAR application/x-rar
7ZIP application/x-7z-compressed

Request attributes

Use the request example below to see the nesting of documents and files.

Request attributes include both required and optional fields:

Attribute Required Type, Example Description
filename true String invoice.pdf File name
content_type true String, application/pdf MIME type of document
agenda_id true String, 143 Agenda ID where document belongs to
type true String, PurchaseInvoice Type of document. Allowed values: PurchaseInvoice, SalesInvoice
content true String, JVBERi0xLjQgZGVt..(omitted)) URL-safe base64 encoded string of file content. File content needs to use URL-safe variant of base64 encoding/decoding (common pitfall).
file_split false Boolean,true true,false. In case of false automatic splitting is disabled. One file = one document. Number of pages for split is limited to 200.

Optional duplicate check

If you add additional parameter check_file_duplicates=1 to create document url you will get response message “File duplicate” with additional meta data in case the check is positive.
You can use the provided metadata either to let you user know that the file is duplicate or to obtain extracted data from original. Just be aware that there can be multiple processed docs from single upload (archives, multi page scans).

Query parameters

Name Example Description
check_file_duplicates 1 You will get response message “File duplicate” with additional meta data in case the check is positive.

Headers

Name Example Description
Accept application/json -
Content-Type application/json -

Request body

{
  "documents": [
    {
      "files": [
        {
          "filename": "demo-supplier-invoice.pdf",
          "content_type": "application/pdf",
          "content": "JVBERi0xLjQgZGF0YW1vbGluby1kZW1v"
        }
      ],
      "agenda_id": 12345,
      "file_split": false,
      "type": "PurchaseInvoice"
    }
  ]
}

Code examples

cURL

curl --request POST 'https://app.datamolino.com/api/v1_2/documents?check_file_duplicates=1' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer demo_access_token' \
  --data '{
  "documents": [
    {
      "files": [
        {
          "filename": "demo-supplier-invoice.pdf",
          "content_type": "application/pdf",
          "content": "JVBERi0xLjQgZGF0YW1vbGluby1kZW1v"
        }
      ],
      "agenda_id": 12345,
      "file_split": false,
      "type": "PurchaseInvoice"
    }
  ]
}'

HTTP

POST /api/v1_2/documents?check_file_duplicates=1 HTTP/1.1
Host: app.datamolino.com
Accept: application/json
Content-Type: application/json
Authorization: Bearer demo_access_token

{
  "documents": [
    {
      "files": [
        {
          "filename": "demo-supplier-invoice.pdf",
          "content_type": "application/pdf",
          "content": "JVBERi0xLjQgZGF0YW1vbGluby1kZW1v"
        }
      ],
      "agenda_id": 12345,
      "file_split": false,
      "type": "PurchaseInvoice"
    }
  ]
}

JavaScript Fetch

const response = await fetch("https://app.datamolino.com/api/v1_2/documents?check_file_duplicates=1", {
  method: "POST",
  headers: {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer demo_access_token"
  },
  body: JSON.stringify({
"documents": [
  {
    "files": [
      {
        "filename": "demo-supplier-invoice.pdf",
        "content_type": "application/pdf",
        "content": "JVBERi0xLjQgZGF0YW1vbGluby1kZW1v"
      }
    ],
    "agenda_id": 12345,
    "file_split": false,
    "type": "PurchaseInvoice"
  }
]
  }),
});

const data = await response.json();

Node.js Axios

import axios from "axios";

const response = await axios({
  method: "post",
  url: "https://app.datamolino.com/api/v1_2/documents?check_file_duplicates=1",
  headers: {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": "Bearer demo_access_token"
  },
  data: {
"documents": [
  {
    "files": [
      {
        "filename": "demo-supplier-invoice.pdf",
        "content_type": "application/pdf",
        "content": "JVBERi0xLjQgZGF0YW1vbGluby1kZW1v"
      }
    ],
    "agenda_id": 12345,
    "file_split": false,
    "type": "PurchaseInvoice"
  }
]
  }
});

console.log(response.data);

Python Requests

import requests

url = "https://app.datamolino.com/api/v1_2/documents?check_file_duplicates=1"
headers = {
  "Accept": "application/json",
  "Content-Type": "application/json",
  "Authorization": "Bearer demo_access_token"
}
payload = {
  "documents": [
{
  "files": [
    {
      "filename": "demo-supplier-invoice.pdf",
      "content_type": "application/pdf",
      "content": "JVBERi0xLjQgZGF0YW1vbGluby1kZW1v"
    }
  ],
  "agenda_id": 12345,
  "file_split": False,
  "type": "PurchaseInvoice"
}
  ]
}

response = requests.request("POST", url, headers=headers, json=payload)
response.raise_for_status()
print(response.json())

Ruby Net::HTTP

require 'json'
require 'net/http'

uri = URI("https://app.datamolino.com/api/v1_2/documents?check_file_duplicates=1")
request = Net::HTTP::Post.new(uri)
request["Accept"] = "application/json"
request["Content-Type"] = "application/json"
request["Authorization"] = "Bearer demo_access_token"
request.body = <<~JSON
{
  "documents": [
{
  "files": [
    {
      "filename": "demo-supplier-invoice.pdf",
      "content_type": "application/pdf",
      "content": "JVBERi0xLjQgZGF0YW1vbGluby1kZW1v"
    }
  ],
  "agenda_id": 12345,
  "file_split": false,
  "type": "PurchaseInvoice"
}
  ]
}
JSON

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
  http.request(request)
end

puts JSON.parse(response.body)

Ruby on Rails

# app/services/datamolino_client.rb
require 'json'
require 'net/http'

class DatamolinoClient
  BASE_URL = "https://app.datamolino.com"

  def initialize(access_token: Rails.application.credentials.dig(:datamolino, :access_token))
@access_token = access_token
  end

  def request_create_document
uri = URI("#{BASE_URL}/api/v1_2/documents?check_file_duplicates=1")
request = Net::HTTP::Post.new(uri)
request["Accept"] = "application/json"
request["Content-Type"] = "application/json"
request["Authorization"] = "Bearer #{@access_token}"
request.body = <<~JSON
  {
    "documents": [
      {
        "files": [
          {
            "filename": "demo-supplier-invoice.pdf",
            "content_type": "application/pdf",
            "content": "JVBERi0xLjQgZGF0YW1vbGluby1kZW1v"
          }
        ],
        "agenda_id": 12345,
        "file_split": false,
        "type": "PurchaseInvoice"
      }
    ]
  }
JSON

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end

JSON.parse(response.body)
  end
end

PHP Guzzle

<?php

use GuzzleHttp\Client;

$client = new Client();
$response = $client->request('POST', 'https://app.datamolino.com/api/v1_2/documents?check_file_duplicates=1', [
'headers' => json_decode('{"Accept":"application/json","Content-Type":"application/json","Authorization":"Bearer demo_access_token"}', true),
'json' => json_decode('{"documents":[{"files":[{"filename":"demo-supplier-invoice.pdf","content_type":"application/pdf","content":"JVBERi0xLjQgZGF0YW1vbGluby1kZW1v"}],"agenda_id":12345,"file_split":false,"type":"PurchaseInvoice"}]}', true)
]);

echo $response->getBody();

Java OkHttp

OkHttpClient client = new OkHttpClient();

RequestBody body = RequestBody.create("{\n  \"documents\": [\n    {\n      \"files\": [\n        {\n          \"filename\": \"demo-supplier-invoice.pdf\",\n          \"content_type\": \"application/pdf\",\n          \"content\": \"JVBERi0xLjQgZGF0YW1vbGluby1kZW1v\"\n        }\n      ],\n      \"agenda_id\": 12345,\n      \"file_split\": false,\n      \"type\": \"PurchaseInvoice\"\n    }\n  ]\n}", MediaType.parse("application/json"));
Request request = new Request.Builder()
.url("https://app.datamolino.com/api/v1_2/documents?check_file_duplicates=1")
.addHeader("Accept", "application/json")
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "Bearer demo_access_token")
.method("POST", body)
.build();

Response response = client.newCall(request).execute();

C# HttpClient

using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, "https://app.datamolino.com/api/v1_2/documents?check_file_duplicates=1");
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Authorization", "Bearer demo_access_token");
request.Content = new StringContent("{\n  \"documents\": [\n    {\n      \"files\": [\n        {\n          \"filename\": \"demo-supplier-invoice.pdf\",\n          \"content_type\": \"application/pdf\",\n          \"content\": \"JVBERi0xLjQgZGF0YW1vbGluby1kZW1v\"\n        }\n      ],\n      \"agenda_id\": 12345,\n      \"file_split\": false,\n      \"type\": \"PurchaseInvoice\"\n    }\n  ]\n}", Encoding.UTF8, "application/json");

using var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
Console.WriteLine(await response.Content.ReadAsStringAsync());

Go Native

client := &http.Client{}
req, err := http.NewRequest("POST", "https://app.datamolino.com/api/v1_2/documents?check_file_duplicates=1", strings.NewReader("{\n  \"documents\": [\n    {\n      \"files\": [\n        {\n          \"filename\": \"demo-supplier-invoice.pdf\",\n          \"content_type\": \"application/pdf\",\n          \"content\": \"JVBERi0xLjQgZGF0YW1vbGluby1kZW1v\"\n        }\n      ],\n      \"agenda_id\": 12345,\n      \"file_split\": false,\n      \"type\": \"PurchaseInvoice\"\n    }\n  ]\n}"))
if err != nil { panic(err) }
req.Header.Add("Accept", "application/json")
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", "Bearer demo_access_token")

res, err := client.Do(req)
if err != nil { panic(err) }
defer res.Body.Close()

body, err := io.ReadAll(res.Body)
if err != nil { panic(err) }
fmt.Println(string(body))

Swift URLSession

import Foundation

var request = URLRequest(url: URL(string: "https://app.datamolino.com/api/v1_2/documents?check_file_duplicates=1")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Accept")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("Bearer demo_access_token", forHTTPHeaderField: "Authorization")
request.httpBody = "{\n  \"documents\": [\n    {\n      \"files\": [\n        {\n          \"filename\": \"demo-supplier-invoice.pdf\",\n          \"content_type\": \"application/pdf\",\n          \"content\": \"JVBERi0xLjQgZGF0YW1vbGluby1kZW1v\"\n        }\n      ],\n      \"agenda_id\": 12345,\n      \"file_split\": false,\n      \"type\": \"PurchaseInvoice\"\n    }\n  ]\n}".data(using: .utf8)

let (data, _) = try await URLSession.shared.data(for: request)
print(String(data: data, encoding: .utf8)!)

Responses

201 Created

Synthetic example of a successful upload:

{
  "documents": [
    {
      "upload_file_name": "demo-supplier-invoice.pdf",
      "id": 24680
    }
  ]
}

201 Created (duplicate detected)

When check_file_duplicates=1, inspect each result for a message. A duplicate result uses the same HTTP status as a successful upload and includes the original upload and document references.

{
  "documents": [
    {
      "upload_file_name": "demo-supplier-invoice.pdf",
      "message": "File duplicate",
      "original_upload_uuid": "00000000-0000-4000-8000-000000000001",
      "original_upload_doc_ids": [24680]
    }
  ]
}

Type to search…

↑↓ navigate↵ selectEsc close