Our Upload endpoints require a payload of type multipart/form-data
as defined by RFC 7578. Most HTTP clients provide features that simplify this process.
Best practices for filenames
in Upload APIs
filenames
in Upload APIsAllowed characters
Filenames should use only safe and compatible characters as follow:
- Alphanumeric characters: A-Z, a-z, 0-9
- Hyphens (
-
) - Underscores (
_
) - Periods (
.
) for file extensions - Spaces may be allowed but should be URL-encoded (e.g.,
%20
or+
)
Avoid special characters
Some characters can cause issues in file systems and URLs and should be avoided. These include:
- Slashes (
/
,\
): reserved for path separators - Backslashes (
\
): commonly reserved, especially on Windows systems - Wildcards (
*
,?
) - Angle brackets (
<
,>
) - Colon (
:
), pipe (|
) - Quotes (
"
), apostrophes ('
) - Ampersand (
&
), percent (%
)
Note:
Using these characters may require URL encoding or preferably, excluding them from filenames entirely.
Length limitations
For compatibility and ease of use, keep filenames under 255 characters.
You can use any library or platform that can send HTTP requests. This page offers code samples for some popular technologies, including:
cURL
You can upload a file to Ocrolus using cURL with its--form
option. Use the @
syntax to refer to a particular file on your file system.
curl \
--url "https://api.ocrolus.com/v1/book/upload"
--oauth2-bearer "eyJhb...ciOSiU" \
--form book_uuid="$THE_BOOK_UUID" \
--form upload="@./path/to/document.pdf"
Which operating system?
Most shells will handle the preceding syntax identically. The most notable exceptions are PowerShell and Windows CMD.
They respectively use backticks (
`
) and carets (^
) instead of backslashes (\
) for line continuations.
Python
You can use the requests
library and pass the files to requests.post
's files
keyword parameter, as demonstrated in the following code sample.
You can also use the oauthlib
library to create a session. The library will automatically apply the correct Content-Type
and Authorization
headers when used as shown. Remember to close the opened file (possibly using a with
statement) once you're done with it!
import requests
response = requests.post(
'https://api.ocrolus.com/v1/book/upload',
headers={
'Accept': 'application/json',
'Authorization': 'Bearer <BEARER_TOKEN>',
},
data={
'pk': '123456',
}
files={
'upload': open('/path/to/bank-statement.pdf', 'rb'),
},
)
print(response.json())
# You'll need to install the requests and requests-oauthlib libraries
from oauthlib.oauth2 import BackendApplicationClient
from requests_oauthlib import OAuth2Session
client_id = "your_client_id"
client_secret = "your_client_secret"
# Get these from the Ocrolus Dashboard (and don't share them with anyone)
client = BackendApplicationClient(client_id=client_id)
session = OAuth2Session(client=client)
token = session.fetch_token("https://auth.ocrolus.com/oauth/token", client_secret=client_secret)
filepath = "/path/to/the/file.pdf"
url = "https://api.ocrolus.com/v1/book/upload"
data = {"pk": "the_book_pk"} # The book's primary key, as a string or an int
with open(filepath, "rb") as file:
files = {"upload": file}
response = session.post(url, data=data, files=files)
print(response.json())
Node.js
Axios is a popular option that pairs well with the form-data package, as demonstrated below:
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/'
});
ocrolusApi.post(
'https://api.ocrolus.com/v1//book/upload',
form_data,
{ headers: form_data.getHeaders(),
authorization: 'Bearer <BEARER_TOKEN>'
}
).then(res => {
console.log('response', res.data);
}).catch(err => {
console.log('error', err);
});
Prefer something else?
The preceding code sample is written in JavaScript, but you can use the demonstrated APIs with any language that
compiles to it (e.g. CoffeeScript or TypeScript).
Java
You can encode multipart/form-data
payloads with APIs offered by Spring or Java EE. You could use Spring's MultipartBodyBuilder
or Java EE's MimeMultipart
classes.
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;
}
}
Prefer something else?
The preceding code samples are written in Java, but the demonstrated APIs are usable with any language that runs on
the JVM (e.g. Kotlin or Scala).
.NET
You can use .NET's HttpClient
and MultipartFormDataContent
classes 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);
}
}
Prefer something else?
The preceding code sample is written in C#, but the demonstrated APIs are usable with any language that uses the .NET runtime (e.g. F# or Visual Basic).
Go
You can use Go's standard http
and multipart
packages 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
You can use PHP's cURL extension 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);
?>