Reamline

Getting started

From a spool file to your first JSON, in about ten minutes.

What you need

A file your business system produced: an invoice, a statement run, a report. The original, exactly as it came out. Not a PDF, not something re-saved from a text editor.

If your system prints to a file, or spools to a queue you can copy from, that file is what you want.

No file to hand?

Open the app and press Load demo. It opens a sample statement run with its template already built, so you can press Extract and see the JSON straight away. Nothing to sign up for, and nothing to download.

Both pieces are also downloadable, if you would rather read them than click:

  • statement-demo.txt is three printed pages: one customer whose statement runs onto a second page, and a second customer after it. One file, two documents.
  • statement-template.json is the template that reads it, with a field, a table, a recognition rule and a splitting rule.

The template came out of the picker rather than being written by hand, and a test runs it against the sample on every build, so what comes back is what is documented here rather than what was true when this page was written.

It is also a working example to copy from. Open the app, press Import JSON, paste it in, and press Try it on this file to see it run before it replaces anything.

Set up the document type

Open the app, drag your file in, and follow the five steps in how it works: mark the values, mark the repeating rows, say how to recognise the document, check the output, publish.

Publishing matters. The API only ever runs published versions, so your draft edits cannot disturb something already in production.

Get an API key

In the app, open Use it and create a key. It is shown once, so store it then. Only a hash is kept, and it cannot be recovered afterwards.

Keys are extract scope by default. That is deliberate: a key that can extract should not be able to delete your templates, so a leaked build-server key costs you some quota rather than your work.

Send your first file

The document goes as base64 so it arrives byte-for-byte, which matters more than it sounds. See encoding below.

KEY=rm_your_key_here
TPL=tpl_your_template_id

printf '{"templateId":"%s","textB64":"%s"}' "$TPL" "$(base64 -w0 INVOICE.TXT)" > payload.json

curl -s -X POST https://reamline.com/v1/extract \
  -H "Content-Type: application/json" \
  -H "x-api-key: $KEY" \
  -d @payload.json

You get back JSON with one entry per document found in the file:

{
  "template": "Austen Invoice@1",
  "summary": { "documents": 1, "ok": 1, "warned": 0, "failed": 0 },
  "documents": [
    { "status": "ok",
      "data": { "docRef": "00153467", "total": "600.00" } }
  ],
  "usage": { "transforms": 15, "limit": 100, "remaining": 85 }
}

Working through a directory

Because the response is ordinary JSON, jq turns it into whatever the next system wants. This prints one JSON object per document found:

for f in /usr/spool/lp/*.TXT; do
  printf '{"templateId":"%s","textB64":"' "$TPL" > /tmp/p.json
  base64 -w0 "$f" >> /tmp/p.json
  printf '"}' >> /tmp/p.json

  curl -sf -X POST https://reamline.com/v1/extract \
    -H "Content-Type: application/json" -H "x-api-key: $KEY" \
    -d @/tmp/p.json > /tmp/out.json || { echo "FAILED: $f"; continue; }

  jq -c '.documents[] | .data' /tmp/out.json
done
Check the call worked before parsing it. On an error the response has no documents at all, and jq prints null, which looks like an empty invoice rather than a failure. curl -sf makes the command itself fail instead.

Older systems

Everything above works on machines far older than this service. On SCO OpenServer, with GNU coreutils and curl installed:

/usr/local/bin/curl -s -X POST https://reamline.com/v1/extract \
  -H "Content-Type: application/json" \
  -H "x-api-key: $KEY" \
  -d "{\"templateId\":\"$TPL\",\"textB64\":\"`/usr/local/coreutils-8.32/bin/gbase64 -w0 /root/INVOICE.TXT`\"}"

Backticks rather than $( ) for the older Bourne shell. Use -d @file rather than an inline string once your spool files get large, or you will eventually hit the command-line length limit.

Encoding

Send the file exactly as your system produced it. Legacy spool is rarely UTF-8, and re-encoding is not harmless: a £ that becomes a three-byte character shifts every column after it, and fixed-width extraction then reads the wrong characters without any error.

base64 on the original bytes is byte-exact and avoids the problem entirely. Tools that read the file as text first, including the default file handling in some scripting languages, may not be.

To check a file before trusting it:

LC_ALL=C grep -q '[^ -~\t\f]' INVOICE.TXT && echo "has high-bit bytes" || echo "plain ASCII"

What you are charged for

Documents, not requests. A statement run that produces 63 statements counts as 63, whether you send it as one file or sixty-three. The free allowance is 100 documents a month.

Every response carries a usage object so you can watch it as you go.