Upload Endpoints require a payload of type multipart/form-data as defined by RFC 7578. This is usually handled by most platforms using specific libraries or modules.

Listed below are relevant code samples for:

cURL

When invoking our endpoints using cURL the appropriate way to upload a file is to use the --form option and reference the file using the @ format.

curl \
  --user 'api_key:api_secret' \
  --form 'pk=123456' \
  --form '[email protected]/path/to/bank-statement.pdf' \
  https://api.ocrolus.com/v1/book/upload

Python

If you're using Python:

  • use the urllib3 library and send the files using the filepost module; or
  • use requests and pass the files to requests.post's files keyword parameter, as demonstrated in the following code sample.
import requests

filepath = '/path/to/bank-statement.pdf'
url = "https://api.ocrolus.com/v1/book/upload"

auth = ('api_key', 'api_secret')
data = {'pk': '123456'} # The book's primary key
files = { 'upload': open(filepath,'rb') }

response = requests.post(url, auth=auth, data=data, files=files)
print(response.json())

When used as shown, the library will automatically apply the correct Content-Type and Authorization headers. Remember to close the opened file once the upload is finished!

Node.js

If you're using Node.js you can leverage one of these packages:

const unirest = require('unirest');

const req = unirest.
  post('https://api.ocrolus.com/v1/book/upload').
  auth({ user: 'api-key', pass: 'api-secret' }).
  field('pk', '123456').
  attach('file', 'path/to/bank-statement.pdf').
  then(res => {
    console.log('response', res.body);
  }).catch(err => {
    console.log('error', err);
  });
const fs = require('fs'),
        axios = require('axios'),
        FormData = require('form-data');

const form_data = new FormData();
form_data.append('pk', '123456');
form_data.append('upload', fs.createReadStream('./index.js'));

const ocrolusApi = axios.create({
  baseURL: 'https://api.ocrolus.com/v1/',
  auth: { username: 'api-key', password: 'api-secret' }
});

ocrolusApi.post(
  '/book/upload', form_data, { headers: form_data.getHeaders() }
).then(res => {
  console.log('response', res.data);
}).catch(err => {
  console.log('error', err);
});

Java

If you're using Java, you can use one of the following classes to encode the request.

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.core.io.FileSystemResource;
import org.springframework.http.MediaType;
import org.springframework.http.client.MultipartBodyBuilder;
import org.springframework.web.reactive.function.client.WebClient;

public class Main {
  public static void main(String[] args) {
    WebClient client = WebClient.builder().
        baseUrl("https://api.ocrolus.com/v1/").
        defaultHeaders(h -> {
          h.setBasicAuth("api-key", "api-secret");
          h.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
        }).
        build();

    MultipartBodyBuilder bookUploadBuilder = new MultipartBodyBuilder();
    bookUploadBuilder.part("pk", 123456);
    bookUploadBuilder.part("upload", new FileSystemResource("path/to/bank-statement.pdf"));

    System.out.println(client.post().uri("book/upload").bodyValue(bookUploadBuilder.build()).
        retrieve().bodyToMono(String.class).block());
  }
}
import java.net.URI;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.core.io.FileSystemResource;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
import org.springframework.http.client.MultipartBodyBuilder;
import org.springframework.web.client.RestTemplate;

public class Main {
  public static void main(String[] args) {
    RestTemplate client = new RestTemplate();

    MultipartBodyBuilder bookUploadBuilder = new MultipartBodyBuilder();
    bookUploadBuilder.part("pk", 123456);
    bookUploadBuilder.part("upload", new FileSystemResource("./Main.java"));

    RequestEntity bookUploadRequest = RequestEntity.
        post(URI.create("https://api.ocrolus.com/v1/book/upload")).
        accept(MediaType.APPLICATION_JSON).
        headers(h -> h.setBasicAuth("api-key", "api-secret")).
        body(bookUploadBuilder.build());

    System.out.println(client.exchange(bookUploadRequest, String.class).getBody());
  }
}
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

import java.net.URL;
import java.net.HttpURLConnection;

import java.util.Base64;

import java.util.stream.Collectors;

import javax.mail.MessagingException;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMultipart;

class Main {
  public static void main(String[] args) throws IOException, MessagingException {
    MimeMultipart multipart = makePayload("123456", "path/to/bank-statement.pdf");
    
    URL url = new URL("https://api.ocrolus.com/v1/book/upload");
    HttpURLConnection connection = (HttpURLConnection)url.openConnection();
    connection.setDoOutput(true);

    connection.setRequestProperty("Authorization", makeAuthorizationHeader("api-key", "api-secret"));
    connection.setRequestProperty("Content-Type", multipart.getContentType().replaceAll("(?ms)\\s*\r\n\\s*", " "));
    connection.setRequestMethod("POST");
    multipart.writeTo(connection.getOutputStream());

    connection.connect();

    System.out.println(String.format("[%d] %s", connection.getResponseCode(), connection.getResponseMessage()));

    BufferedReader reader = new BufferedReader(new InputStreamReader((InputStream)connection.getContent()));
    System.out.println(reader.lines().collect(Collectors.joining("\n")));
  }

  private static String makeAuthorizationHeader(String username, String password) throws UnsupportedEncodingException {
    byte[] byteData = String.format("%s:%s", username, password).getBytes();
    return String.format("Basic %s", Base64.getMimeEncoder().encodeToString(byteData));
  }

  private static MimeMultipart makePayload(String bookPK, String filePath) throws IOException, MessagingException {
    MimeBodyPart bookPKPart = new MimeBodyPart();
    bookPKPart.setText(bookPK);
    bookPKPart.setDisposition("form-data; name=pk");
    bookPKPart.addHeader("Content-Type", "text/plain; charset=utf-8");

    MimeBodyPart filePart = new MimeBodyPart();
    filePart.attachFile(new File(filePath));
    filePart.setDisposition("form-data; name=upload");

    MimeMultipart multipart = new MimeMultipart();
    multipart.setSubType("form-data");
    multipart.addBodyPart(bookPKPart);
    multipart.addBodyPart(filePart);

    return multipart;
  }
}

.NET

If you're using .NET, use the HttpClient class in combination with the MultipartFormDataContent class to encode your request.

using System;
using System.IO;
using System.Text;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

class MainClass {
  public static String BOOK_PK = "123456";

  public static void Main (string[] args) {
    HttpClient client = new HttpClient() { BaseAddress = new Uri("https://api.ocrolus.com/v1/") };
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
      "Basic", MakeAuthorizationHeaderValue("api_key", "api_secret"));

    WriteResponse(client.PostAsync("book/upload", MakePayload(BOOK_PK, "./path/to/bank-statement.pdf")));
  }

  private static String MakeAuthorizationHeaderValue(String username, String password) {
    return Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes($"{username}:{password}"));
  }
  
  private static HttpContent MakePayload(String bookPk, String filePath) {
    MultipartFormDataContent content = new MultipartFormDataContent();

    // Add Book PK to payload
    content.Add(new StringContent(bookPk), "pk");

    // Add File content to payload
    FileInfo file = new FileInfo(filePath);
    content.Add(new StreamContent(file.OpenRead()), "upload", file.Name);
    
    // Debug payload
    // content.CopyToAsync(Console.OpenStandardOutput()).Wait();

    return content;
  }

  private static void WriteResponse(Task<HttpResponseMessage> responseTask) {
    Console.WriteLine(responseTask.Result.Content.ReadAsStringAsync().Result);
  }
}

Go

If you're using Go, use the http package in combination with the multipart package to encode your request.

package main

import (
    "io"
    "log"
    "mime/multipart"
    "net/http"
    "os"
    "strconv"
)

func main() {
    req, err := newUploadRequest(123456, "path/to/bank-statement.pdf")
    if err != nil {
        log.Fatal(err)
    }
    req.SetBasicAuth("api-key", "api-secret")

    client := &http.Client{}

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

    _, err = io.Copy(os.Stdout, res.Body)
    if err != nil {
        log.Fatal(err)
    }
}

func newUploadRequest(bookPK int64, filePath string) (*http.Request, error) {
    body, contentType, err := newUploadBody(bookPK, filePath)
    if err != nil {
        return nil, err
    }

    req, err := http.NewRequest(http.MethodPost, "https://api.ocrolus.com/v1/book/upload", body)
    if err != nil {
        return nil, err
    }
    req.Header.Set("Content-Type", contentType)

    return req, nil
}

func newUploadBody(bookPK int64, filePath string) (io.Reader, string, error) {
    bodyReader, bodyWriter := io.Pipe()
    uploadWriter := multipart.NewWriter(bodyWriter)

    file, err := os.Open(filePath)
    if err != nil {
        return nil, "", err
    }

    go func() {
        defer bodyWriter.Close()
        defer file.Close()

        err = uploadWriter.WriteField("pk", strconv.FormatInt(bookPK, 10))
        if err != nil {
            bodyWriter.CloseWithError(err)
            return
        }

        part, err := uploadWriter.CreateFormFile("upload", file.Name())
        if err != nil {
            bodyWriter.CloseWithError(err)
            return
        }

        _, err = io.Copy(part, file)
        if err != nil {
            bodyWriter.CloseWithError(err)
            return
        }

        err = uploadWriter.Close()
        if err != nil {
            bodyWriter.CloseWithError(err)
            return
        }
    }()

    return bodyReader, uploadWriter.FormDataContentType(), nil
}

PHP

If you're using PHP, use the cURL extension in combination with the CURLFile class to encode your request.

<?php

$username = "username";
$password = "password";
$pk = '123456';
$filepath = "path/to/pdf";
$filename = "bank-statement.pdf";

$request = curl_init('https://api.ocrolus.com/v1/book/upload');
$postdata = array(
  'pk' => $pk,
  'upload' => curl_file_create(
    $filepath . '/' . $filename,
    'application/pdf',
    $filename
  )
);

curl_setopt($request, CURLOPT_USERPWD, $username . ":" . $password);
curl_setopt($request, CURLOPT_POST, true);
curl_setopt($request, CURLOPT_POSTFIELDS, $postdata);

curl_setopt($request, CURLOPT_RETURNTRANSFER, true);
echo curl_exec($request);

curl_close($request);

?>