curl --request POST \
--url https://eval-api.trential.dev/partner/v1/cases \
--header 'Content-Type: multipart/form-data' \
--header 'x-api-key: <api-key>' \
--form files=@example-file \
--form 'externalId=<string>' \
--form classify=true \
--form 'features=["extraction","forensics","translation"]' \
--form 'metadata={"cycle":"2025-fall"}' \
--form 'caseId=<string>'import requests
url = "https://eval-api.trential.dev/partner/v1/cases"
files = { "files": ("example-file", open("example-file", "rb")) }
payload = {
"externalId": "<string>",
"classify": "true",
"features": "[\"extraction\",\"forensics\",\"translation\"]",
"metadata": "{\"cycle\":\"2025-fall\"}",
"caseId": "<string>"
}
headers = {"x-api-key": "<api-key>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('files', '<string>');
form.append('externalId', '<string>');
form.append('classify', 'true');
form.append('features', '["extraction","forensics","translation"]');
form.append('metadata', '{"cycle":"2025-fall"}');
form.append('caseId', '<string>');
const options = {method: 'POST', headers: {'x-api-key': '<api-key>'}};
options.body = form;
fetch('https://eval-api.trential.dev/partner/v1/cases', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://eval-api.trential.dev/partner/v1/cases",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"externalId\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"classify\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"features\"\r\n\r\n[\"extraction\",\"forensics\",\"translation\"]\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"metadata\"\r\n\r\n{\"cycle\":\"2025-fall\"}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"caseId\"\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Content-Type: multipart/form-data",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://eval-api.trential.dev/partner/v1/cases"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"externalId\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"classify\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"features\"\r\n\r\n[\"extraction\",\"forensics\",\"translation\"]\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"metadata\"\r\n\r\n{\"cycle\":\"2025-fall\"}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"caseId\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://eval-api.trential.dev/partner/v1/cases")
.header("x-api-key", "<api-key>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"externalId\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"classify\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"features\"\r\n\r\n[\"extraction\",\"forensics\",\"translation\"]\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"metadata\"\r\n\r\n{\"cycle\":\"2025-fall\"}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"caseId\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://eval-api.trential.dev/partner/v1/cases")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"externalId\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"classify\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"features\"\r\n\r\n[\"extraction\",\"forensics\",\"translation\"]\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"metadata\"\r\n\r\n{\"cycle\":\"2025-fall\"}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"caseId\"\r\n\r\n<string>\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"success": true,
"message": "Upload accepted",
"meta": {},
"data": {
"caseId": "6850abc123def456abc78901",
"externalId": "applicant-9876",
"upload": {
"uploadId": "6850def456abc789abc12301",
"status": "processing",
"classify": true,
"features": [
{
"name": "extraction",
"status": "processing"
},
{
"name": "forensics",
"status": "processing"
},
{
"name": "translation",
"status": "processing"
}
],
"files": [
{
"fileId": "file_abc",
"fileName": "transcript.pdf"
}
],
"createdAt": "2025-06-22T10:00:00Z",
"updatedAt": "2025-06-22T10:00:00Z"
}
}
}{
"statusCode": 123,
"message": "<string>"
}{
"statusCode": 123,
"message": "<string>"
}{
"statusCode": 123,
"message": "<string>"
}{
"statusCode": 123,
"message": "<string>"
}{
"statusCode": 123,
"message": "<string>"
}{
"statusCode": 123,
"message": "<string>"
}Create a case or add an upload
Upload documents for a candidate. If a case with the given externalId already exists, files are added as a new upload to that case. Otherwise, a new case is created. Pass caseId to link an existing TruEnroll case to the externalId instead.
Accepted formats: PDF, PNG, JPG, JPEG, WebP, ZIP. Limits: 20 files, 100 MiB per file, 100 MiB total.
Optionally send an Idempotency-Key header to make retries safe: replaying the same key with an identical payload returns the original upload instead of creating a duplicate.
curl --request POST \
--url https://eval-api.trential.dev/partner/v1/cases \
--header 'Content-Type: multipart/form-data' \
--header 'x-api-key: <api-key>' \
--form files=@example-file \
--form 'externalId=<string>' \
--form classify=true \
--form 'features=["extraction","forensics","translation"]' \
--form 'metadata={"cycle":"2025-fall"}' \
--form 'caseId=<string>'import requests
url = "https://eval-api.trential.dev/partner/v1/cases"
files = { "files": ("example-file", open("example-file", "rb")) }
payload = {
"externalId": "<string>",
"classify": "true",
"features": "[\"extraction\",\"forensics\",\"translation\"]",
"metadata": "{\"cycle\":\"2025-fall\"}",
"caseId": "<string>"
}
headers = {"x-api-key": "<api-key>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('files', '<string>');
form.append('externalId', '<string>');
form.append('classify', 'true');
form.append('features', '["extraction","forensics","translation"]');
form.append('metadata', '{"cycle":"2025-fall"}');
form.append('caseId', '<string>');
const options = {method: 'POST', headers: {'x-api-key': '<api-key>'}};
options.body = form;
fetch('https://eval-api.trential.dev/partner/v1/cases', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://eval-api.trential.dev/partner/v1/cases",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"externalId\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"classify\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"features\"\r\n\r\n[\"extraction\",\"forensics\",\"translation\"]\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"metadata\"\r\n\r\n{\"cycle\":\"2025-fall\"}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"caseId\"\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Content-Type: multipart/form-data",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://eval-api.trential.dev/partner/v1/cases"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"externalId\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"classify\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"features\"\r\n\r\n[\"extraction\",\"forensics\",\"translation\"]\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"metadata\"\r\n\r\n{\"cycle\":\"2025-fall\"}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"caseId\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://eval-api.trential.dev/partner/v1/cases")
.header("x-api-key", "<api-key>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"externalId\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"classify\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"features\"\r\n\r\n[\"extraction\",\"forensics\",\"translation\"]\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"metadata\"\r\n\r\n{\"cycle\":\"2025-fall\"}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"caseId\"\r\n\r\n<string>\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://eval-api.trential.dev/partner/v1/cases")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"files\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"externalId\"\r\n\r\n<string>\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"classify\"\r\n\r\ntrue\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"features\"\r\n\r\n[\"extraction\",\"forensics\",\"translation\"]\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"metadata\"\r\n\r\n{\"cycle\":\"2025-fall\"}\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"caseId\"\r\n\r\n<string>\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"success": true,
"message": "Upload accepted",
"meta": {},
"data": {
"caseId": "6850abc123def456abc78901",
"externalId": "applicant-9876",
"upload": {
"uploadId": "6850def456abc789abc12301",
"status": "processing",
"classify": true,
"features": [
{
"name": "extraction",
"status": "processing"
},
{
"name": "forensics",
"status": "processing"
},
{
"name": "translation",
"status": "processing"
}
],
"files": [
{
"fileId": "file_abc",
"fileName": "transcript.pdf"
}
],
"createdAt": "2025-06-22T10:00:00Z",
"updatedAt": "2025-06-22T10:00:00Z"
}
}
}{
"statusCode": 123,
"message": "<string>"
}{
"statusCode": 123,
"message": "<string>"
}{
"statusCode": 123,
"message": "<string>"
}{
"statusCode": 123,
"message": "<string>"
}{
"statusCode": 123,
"message": "<string>"
}{
"statusCode": 123,
"message": "<string>"
}Authorizations
Partner API key. Also accepted as Authorization: Bearer <key>.
Headers
Optional. Makes the upload safe to retry: replaying the same key with an identical payload returns the original upload. Reusing a key with a different payload returns 409.
Body
One or more document files. Accepted formats: PDF, PNG, JPG, JPEG, WebP, ZIP. Max 20 files, 100 MiB each, 100 MiB total.
Your reference for this case. Unique per organization; subsequent submissions with the same externalId append to the existing case.
1 - 128Run AI document classification. When false, classification is skipped and the whole upload becomes one academic credential. classify false with an empty features array returns 400.
JSON array of features to run. Defaults to all three. A feature not requested does not run unless an operator starts it later. Example: ["extraction","forensics"]
"[\"extraction\",\"forensics\",\"translation\"]"
JSON object of key-value pairs (string, number, or boolean values).
"{\"cycle\":\"2025-fall\"}"
Case ID or case number of an existing TruEnroll case to link to this externalId. The files become a new upload on that case. A case can be linked once.