How does authentication work?
Send a JSON POST body containing action: "auth" and apiKey. Send the returned token on protected calls with Authorization: Bearer ….
Authenticate an integration, submit one or more label records, let the user review the rendered labels, and produce a print-ready PDF.
Start here
The API is session-oriented. An API key creates a temporary token, submitted records are stored in that token's session, and the preview page renders those records with the selected project's label template.
Send a JSON POST body containing action: "auth" and apiKey. Send the returned token on protected calls with Authorization: Bearer ….
Every API action uses POST with an application/json body. The interactive preview is a browser page opened with GET. No PUT request is needed.
With a known project ID: authenticate, submit labelData, then open /preview. The preview's Save File button renders and downloads the PDF.
labelData accepts a JSON object containing a data array. Each array item is one label record. Raw CSV is not accepted directly.
Yes. Send multiple objects in the JSON data array. Each object normally produces one label in the resulting batch.
No. File Label Express creates a print-ready preview/PDF. A user, desktop application, print service, or printer-management system initiates the physical print.
Core integration
If the integration already knows its assigned project ID, only two API calls are required before sending the user to preview.
output.user.token.
labelData.
Send the token in the bearer header. The JSON body contains the optional application name and an array with one object per label.
downloadPDF immediately after labelData.
labelData does not create a PDF. Calling downloadPDF immediately afterward returns “No PDF data found.” A PDF exists only after rendered HTML has been passed through saveGeneratedSource, which the normal preview page handles when the user clicks Save File.
If the project ID is not stored by the integrating application, call getProjects after authentication. The application may then call getProjectMeta to discover the exact field names required by the chosen label project.
Protocol
All API actions are sent as JSON POST requests:
Content-Type: application/json
Accept: application/json
Authorization: Bearer TEMPORARY_TOKEN
The request body must be a JSON object. Put the operation name in action, then add its operation-specific properties. Omit the Authorization header from the initial auth call.
| Credential | Where it is sent | Used for |
|---|---|---|
apiKey | JSON request property | The initial auth request only. |
token | Authorization: Bearer … | Subsequent protected API calls. |
token | Initial preview handoff URL | Exchanged for a secure session cookie and removed by redirect. |
| Operation | Method | Response | Token |
|---|---|---|---|
auth | POST | JSON | No |
getSession | POST | JSON | Bearer header |
getProjects | POST | JSON | Bearer header |
getProjectMeta | POST | JSON | Bearer header |
labelData / submitLabels | POST | JSON | Bearer header |
/preview | GET | HTML page | Preview URL |
saveGeneratedSource | POST | JSON | Bearer header |
downloadPDF | POST | application/pdf | Bearer header |
sampleData | POST | JSON | Bearer header |
getFilingSystem | POST | JSON | Not required for public catalog data |
convertXLS / convertXLSX | POST | JSON containing base64 CSV | Bearer header |
https://filelabel.co/api/ with POST and select the operation with the JSON action property. The preview is a separate interactive browser route.
Authorization header. The calling origin plus the Content-Type and Authorization headers must be permitted by the API's CORS configuration. Server-to-server requests are not subject to browser CORS enforcement.
Most API responses use an error/output envelope:
{
"error": [],
"output": { }
}
An empty error array/object indicates success. Some application errors are returned with HTTP 200, so integrations must inspect the response body instead of relying only on the HTTP status.
Payloads
The label batch is an ordered array of objects. Each object's keys must match the field names configured for the selected project.
data arraylabelDatalabelDatadata instead of a JSON arraySend a JSON object at the request root. The data member contains one object per label:
{
"action": "labelData",
"app": "Records System",
"data": [
{
"last_name": "Morgan",
"first_name": "Alex",
"dob": "1985-04-12"
},
{
"last_name": "Rivera",
"first_name": "Jamie",
"dob": "1977-11-03"
}
]
}
A new labelData call replaces the prior active remote batch for the same token/session. Submit the complete intended batch each time.
Quick start
This example uses a known project ID and submits two labels. Replace the placeholder credentials, project, and fields with values assigned to the user.
curl --request POST 'https://filelabel.co/api/' \
--header 'Content-Type: application/json' \
--data '{
"action": "auth",
"apiKey": "YOUR_API_KEY"
}'
{
"error": [],
"output": {
"user": {
"userId": "USER_ID",
"logged_in": true,
"token": "TEMPORARY_TOKEN"
}
}
}
curl --request POST 'https://filelabel.co/api/' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer TEMPORARY_TOKEN' \
--data '{
"action": "labelData",
"app": "Records System",
"data": [
{
"last_name": "Morgan",
"first_name": "Alex",
"dob": "1985-04-12"
},
{
"last_name": "Rivera",
"first_name": "Jamie",
"dob": "1977-11-03"
}
]
}'
https://filelabel.co/preview?project=PROJECT_ID&token=TEMPORARY_TOKEN
File Label Express validates the token, stores the session in a secure HTTP-only cookie, and redirects to /preview?project=PROJECT_ID. The user then reviews the batch and selects Save File. Printing the resulting PDF is handled by the user's PDF viewer, desktop software, or print-management process.
<?php
function flxPost(array $parameters, ?string $token = null): array
{
$handle = curl_init('https://filelabel.co/api/');
$json = json_encode($parameters, JSON_THROW_ON_ERROR);
$headers = [
'Content-Type: application/json',
'Accept: application/json',
];
if ($token !== null) {
$headers[] = 'Authorization: Bearer '.$token;
}
curl_setopt_array($handle, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $json,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_HTTPHEADER => $headers,
]);
$body = curl_exec($handle);
if ($body === false) {
throw new RuntimeException(curl_error($handle));
}
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);
if ($status < 200 || $status >= 300) {
throw new RuntimeException('File Label Express returned HTTP '.$status.'.');
}
return json_decode($body, true, 512, JSON_THROW_ON_ERROR);
}
$auth = flxPost([
'action' => 'auth',
'apiKey' => getenv('FILELABEL_API_KEY'),
]);
if (!empty($auth['error'])) {
throw new RuntimeException('File Label Express authentication failed.');
}
$token = $auth['output']['user']['token'];
$result = flxPost([
'action' => 'labelData',
'app' => 'Records System',
'data' => [
[
'last_name' => 'Morgan',
'first_name' => 'Alex',
'dob' => '1985-04-12',
],
[
'last_name' => 'Rivera',
'first_name' => 'Jamie',
'dob' => '1977-11-03',
],
],
], $token);
$previewUrl = 'https://filelabel.co/preview?'.http_build_query([
'project' => 'PROJECT_ID',
'token' => $token,
]);
// Redirect the user's browser or return this URL to the client application.
header('Location: '.$previewUrl);
Server-side integration
This updated client sends JSON request bodies, authenticates protected calls with the bearer header, validates TLS certificates, reports transport and API errors, and keeps the temporary token separate from the permanent API key.
<?php
declare(strict_types=1);
final class Filelabel_API
{
private const API_URL = 'https://filelabel.co/api/';
private const PREVIEW_URL = 'https://filelabel.co/preview';
private string $apiKey;
private ?string $token;
private int $timeout;
public bool $loggedIn = false;
public function __construct(
string $apiKey,
?string $token = null,
int $timeout = 30
) {
$apiKey = trim($apiKey);
if ($apiKey === '') {
throw new InvalidArgumentException('An API key is required.');
}
$this->apiKey = $apiKey;
$this->token = $token ?: null;
$this->timeout = max(1, $timeout);
}
/** Authenticate the API key and retain the returned temporary token. */
public function auth(): array
{
$output = $this->requestJson([
'action' => 'auth',
'apiKey' => $this->apiKey,
], false);
$token = $output['user']['token'] ?? null;
if (!is_string($token) || $token === '') {
throw new RuntimeException(
'Authentication did not return a token.'
);
}
$this->token = $token;
$this->loggedIn = true;
return $output['user'];
}
/** Check a previously saved token without exposing the API key. */
public function checkSession(): bool
{
if ($this->token === null) {
return false;
}
try {
$session = $this->getSession();
$this->loggedIn = !empty($session['logged_in']);
} catch (RuntimeException $exception) {
$this->loggedIn = false;
}
return $this->loggedIn;
}
public function getSession(): array
{
$output = $this->requestJson([
'action' => 'getSession',
]);
if (!isset($output['session']) || !is_array($output['session'])) {
throw new RuntimeException('No session was returned.');
}
return $output['session'];
}
public function getProjects(): array
{
$output = $this->requestJson([
'action' => 'getProjects',
]);
return isset($output['projects']) && is_array($output['projects'])
? $output['projects']
: [];
}
public function getProjectMeta(string $projectId): array
{
return $this->requestJson([
'action' => 'getProjectMeta',
'project' => $projectId,
]);
}
/** Submit one JSON object per label. */
public function labelData(array $records, ?string $app = null): array
{
if ($records === []) {
throw new InvalidArgumentException(
'At least one label record is required.'
);
}
foreach ($records as $record) {
if (!is_array($record)) {
throw new InvalidArgumentException(
'Every label record must be an array.'
);
}
}
$payload = [
'action' => 'labelData',
'data' => array_values($records),
];
if ($app !== null && $app !== '') {
$payload['app'] = $app;
}
return $this->requestJson($payload);
}
public function previewUrl(string $projectId, int $offset = 0): string
{
return self::PREVIEW_URL.'?'.http_build_query(
[
'project' => $projectId,
'offset' => max(0, $offset),
'token' => $this->requireToken(),
],
'',
'&',
PHP_QUERY_RFC3986
);
}
/** Download a PDF already generated by the preview flow. */
public function downloadPDF(): string
{
[$status, $contentType, $body] = $this->sendJson([
'action' => 'downloadPDF',
], 'application/pdf', true);
if ($status < 200 || $status >= 300) {
throw new RuntimeException(
'File Label Express returned HTTP '.$status.'.'
);
}
if (stripos($contentType, 'application/json') !== false) {
$this->decodeResponse($body);
}
if (strncmp($body, '%PDF', 4) !== 0) {
throw new RuntimeException(
'File Label Express did not return a PDF.'
);
}
return $body;
}
public function getToken(): ?string
{
return $this->token;
}
private function requestJson(
array $payload,
bool $authorized = true
): array
{
[$status, $contentType, $body] = $this->sendJson(
$payload,
'application/json',
$authorized
);
if ($status < 200 || $status >= 300) {
throw new RuntimeException(
'File Label Express returned HTTP '.$status.'.'
);
}
return $this->decodeResponse($body);
}
private function sendJson(
array $payload,
string $accept = 'application/json',
bool $authorized = true
): array {
try {
$json = json_encode(
$payload,
JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR
);
} catch (JsonException $exception) {
throw new InvalidArgumentException(
'The request could not be encoded as JSON.',
0,
$exception
);
}
$curl = curl_init(self::API_URL);
if ($curl === false) {
throw new RuntimeException('Unable to initialize cURL.');
}
$headers = [
'Content-Type: application/json',
'Accept: '.$accept,
];
if ($authorized) {
$headers[] = 'Authorization: Bearer '.$this->requireToken();
}
curl_setopt_array($curl, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $json,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_ENCODING => '',
CURLOPT_USERAGENT => 'Filelabel_API/1.0',
CURLOPT_HTTPHEADER => $headers,
]);
$body = curl_exec($curl);
$status = (int) curl_getinfo($curl, CURLINFO_HTTP_CODE);
$contentType = (string) curl_getinfo($curl, CURLINFO_CONTENT_TYPE);
if ($body === false) {
$message = curl_error($curl);
curl_close($curl);
throw new RuntimeException('File Label Express: '.$message);
}
curl_close($curl);
return [$status, $contentType, $body];
}
private function decodeResponse(string $body): array
{
try {
$response = json_decode(
$body,
true,
512,
JSON_THROW_ON_ERROR
);
} catch (JsonException $exception) {
throw new RuntimeException(
'File Label Express returned invalid JSON.',
0,
$exception
);
}
if (!is_array($response)) {
throw new RuntimeException(
'File Label Express returned an invalid response.'
);
}
if ($this->hasError($response['error'] ?? null)) {
throw new RuntimeException(
'File Label Express: '.
$this->formatError($response['error'])
);
}
$output = $response['output'] ?? [];
return is_array($output) ? $output : ['value' => $output];
}
private function requireToken(): string
{
if ($this->token === null || $this->token === '') {
throw new LogicException(
'Authenticate before calling this operation.'
);
}
return $this->token;
}
private function hasError($error): bool
{
if ($error === null || $error === false || $error === '') {
return false;
}
return !is_array($error) || $error !== [];
}
private function formatError($error): string
{
if (is_string($error)) {
return $error;
}
$encoded = json_encode($error, JSON_UNESCAPED_SLASHES);
return $encoded !== false ? $encoded : 'Unknown API error.';
}
}
session_start();
require_once 'Filelabel_API.php';
$filelabel = new Filelabel_API(
getenv('FILELABEL_API_KEY'),
$_SESSION['filelabel_token'] ?? null
);
if (!$filelabel->checkSession()) {
$filelabel->auth();
$_SESSION['filelabel_token'] = $filelabel->getToken();
}
$projects = $filelabel->getProjects();
$projectIds = array_keys((array) $projects);
if (!$projectIds) {
throw new RuntimeException('No label projects are assigned.');
}
$projectId = $projectIds[0];
$filelabel->labelData([
[
'last_name' => 'Morgan',
'first_name' => 'Alex',
'dob' => '1985-04-12',
],
[
'last_name' => 'Rivera',
'first_name' => 'Jamie',
'dob' => '1977-11-03',
],
], 'Records System');
header('Location: '.$filelabel->previewUrl($projectId));
exit;
The example stores the temporary token in the integrating application's PHP session. The constructor performs no network request. The application validates a saved token with checkSession() and calls auth() only when a new token is required.
Reference
All API actions use the same base endpoint. The action parameter selects the operation.
Authenticates a user's API key and starts a temporary File Label Express session.
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | Must be auth. |
apiKey | string | Yes | The API key assigned to the File Label Express user. |
POST https://filelabel.co/api/
Content-Type: application/json
{
"action": "auth",
"apiKey": "YOUR_API_KEY"
}
On success, store output.user.token temporarily and use it for the remainder of the label workflow. Do not expect the token in an HTTP response header.
Returns the session associated with a token. It can be used to confirm that the token is still logged in and to recover session details such as assigned projects.
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | Must be getSession. |
POST https://filelabel.co/api/
Content-Type: application/json
Authorization: Bearer TEMPORARY_TOKEN
{
"action": "getSession"
}
{
"error": [],
"output": {
"session": {
"logged_in": true,
"userId": "USER_ID",
"projects": { }
}
}
}
Validate output.session.logged_in. Do not treat the mere presence of a session object as proof that authentication is active.
Returns the label projects assigned to the authenticated user.
POST https://filelabel.co/api/
Content-Type: application/json
Authorization: Bearer TEMPORARY_TOKEN
{
"action": "getProjects"
}
The projects are returned under output.projects, keyed by project ID. Store the selected project ID; it is needed for metadata, preview, and PDF creation.
Returns configuration for one project, including its accepted field names and print-template information.
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | Must be getProjectMeta. |
project | string | Yes | An assigned File Label Express project ID. |
POST https://filelabel.co/api/
Content-Type: application/json
Authorization: Bearer TEMPORARY_TOKEN
{
"action": "getProjectMeta",
"project": "PROJECT_ID"
}
{
"error": [],
"output": {
"name": "Example Project",
"fields": ["last_name", "first_name", "dob"],
"printTemplate": "FLX-6-L.css",
"printTemplateInfo": {
"labelsPer": "6",
"pageWidth": "11.0in",
"pageHeight": "8.75in"
}
}
}
Replaces the active session batch with the submitted label records. submitLabels is a compatibility alias for the same operation.
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | labelData or submitLabels. |
data | array<object> | Yes | One or more label records. Keys must match the project fields. |
app | string | No | Human-readable name of the integrating application. |
POST https://filelabel.co/api/
Content-Type: application/json
Authorization: Bearer TEMPORARY_TOKEN
{
"action": "labelData",
"app": "Records System",
"data": [
{
"last_name": "Morgan",
"first_name": "Alex"
},
{
"last_name": "Rivera",
"first_name": "Jamie"
}
]
}
The response's output contains the session's stored batch. Server-generated keys may replace the numeric request indexes; integrations should not treat those generated keys as durable record IDs.
Displays the submitted records using the selected project's live label design and print template.
| Parameter | Type | Required | Description |
|---|---|---|---|
project | string | Yes | The assigned project whose template will render the batch. |
token | string | Yes | The same temporary token used to submit the batch. |
offset | integer | No | Leaves blank label positions before the first rendered label. |
https://filelabel.co/preview?project=PROJECT_ID&token=TEMPORARY_TOKEN
This is a one-time handoff URL. File Label Express validates the token, sets a secure HTTP-only session cookie, and redirects to the same preview without the token. The user then reviews the labels and selects Save File.
Advanced endpoint that converts a complete, already-rendered HTML document into a PDF stored in the current session.
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | Must be saveGeneratedSource. |
project | string | Yes | An assigned project ID. |
html | string | Yes | A complete rendered HTML document stored as a JSON string. |
count | integer | No | Number of valid labels, used for the project counter and audit. |
POST https://filelabel.co/api/
Content-Type: application/json
Authorization: Bearer TEMPORARY_TOKEN
{
"action": "saveGeneratedSource",
"project": "PROJECT_ID",
"html": "<!doctype html>...</html>",
"count": 12
}
A successful response contains output.pdf = "PDF created successfully.". The PDF bytes are then available once through downloadPDF. Identical repeated generation requests may be rate-limited briefly.
Downloads the PDF currently stored in the authenticated session.
curl --request POST 'https://filelabel.co/api/' \
--header 'Content-Type: application/json' \
--header 'Accept: application/pdf' \
--header 'Authorization: Bearer TEMPORARY_TOKEN' \
--data '{
"action": "downloadPDF"
}' \
--output labels.pdf
The browser preview normally initiates this download automatically after PDF creation. The downloaded PDF is named labels.pdf. Once delivered, the session copy is removed, so a second download requires regenerating it.
Generates ten example records using the fields and form configuration of a project.
POST https://filelabel.co/api/
Content-Type: application/json
Authorization: Bearer TEMPORARY_TOKEN
{
"action": "sampleData",
"project": "PROJECT_ID"
}
This action returns the sample array directly rather than consistently wrapping it in output. Use it for testing and field discovery, not as production label data.
Returns projects grouped by supported filing-system family, or projects for one named family.
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | Must be getFilingSystem. |
name | string | No | Optional family such as gbs, barkley, tab, smead, tabbies, or datafile. |
POST https://filelabel.co/api/
Content-Type: application/json
{
"action": "getFilingSystem",
"name": "gbs"
}
Converts the first worksheet of an Excel file into CSV data. These utilities do not submit the resulting rows as labels.
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | Yes | convertXLS for older Excel files or convertXLSX for modern workbooks. |
data | string | Yes | Base64-encoded workbook bytes stored as a JSON string. |
POST https://filelabel.co/api/
Content-Type: application/json
Authorization: Bearer TEMPORARY_TOKEN
{
"action": "convertXLSX",
"data": "BASE64_ENCODED_WORKBOOK"
}
{
"error": [],
"output": {
"data": "BASE64_ENCODED_CSV"
}
}
After conversion, the integrating application must decode and parse the CSV, map its columns to the chosen project's fields, and submit the resulting array through labelData.
Reliability
Always check both the HTTP result and the response body's error field. API v1 may report an application error in a successful HTTP response.
{
"error": {
"apiKey": "The API key is incorrect."
},
"output": []
}
| Error condition | Meaning | Recommended action |
|---|---|---|
| Missing/incorrect API key | Authentication did not succeed. | Verify the assigned key. Do not retry rapidly. |
| No session or authentication token | The token is missing, expired, or invalid. | Authenticate again and restart the active batch. |
| Permission denied | The user does not have access to the requested project. | Use a project from getProjects or request assignment. |
| No PDF data found | No PDF was created in this session, or it was already downloaded. | Use preview/Save File or call saveGeneratedSource before downloading. |
| Rate limit reached | The same PDF-generation request was repeated too quickly. | Wait before retrying; do not immediately loop. |
| Invalid action | The named action is not available. | Check spelling and use an action documented on this page. |
Security
getProjects instead of accepting arbitrary project IDs from end users.auth call.
Clarifications
Authorization: Bearer TEMPORARY_TOKEN. Only the initial interactive preview handoff carries the token in its URL; File Label Express exchanges it for a secure HTTP-only cookie and immediately redirects to a clean URL.Content-Type: application/json. Put the action, application name, and data array in that object, and send the token in the bearer header.labelData. Parse the CSV in your application, map the columns to the project's fields, and submit an array of objects. The spreadsheet conversion endpoints can convert XLS/XLSX into base64-encoded CSV, but they do not submit labels automatically.labelData request. The preview combines the complete batch and the project's print template controls labels per page and page breaks.labelData stores records; it does not render them. Use the preview page and its Save File button. Advanced clients must first create the complete rendered document with saveGeneratedSource.getProjectMeta and inspect output.fields and any returned form definition. Field names are project-specific and should be preserved exactly.