Geautomatiseerde bestandsupload

API Integration: Creating a Ticket with File Uploads [ADVANCED USE]

The ticket creation API accepts a multipart/form-data POST request. Files are sent as the field a-file[] (multiple files supported). On success, the API returns a redirect — follow it to confirm completion.

Endpoint

Endpoint does not change for this feature, please see the documentation page.


1. Windows (PowerShell)

# Define endpoint
$baseUrl  = "https://order.4ortho.nl"
$endpoint = "/api/ticket/YOUR_API_TOKEN/01/YOUR_LOGIN_DEBITNUMBER/P.%20Atient/123456/2008-09-01/"
$url      = "$baseUrl$endpoint"
# Collect files to upload
$filePaths = @(
    "C:\scans\scan1.stl",
    "C:\scans\scan2.stl"
)

# Build multipart form
$form = [System.Net.Http.MultipartFormDataContent]::new()

foreach ($filePath in $filePaths) {
    $fileStream  = [System.IO.File]::OpenRead($filePath)
    $fileName    = [System.IO.Path]::GetFileName($filePath)
    $fileContent = [System.Net.Http.StreamContent]::new($fileStream)
    $form.Add($fileContent, "a-file[]", $fileName)
}

# Do NOT follow redirects — we need the Location header
$handler                    = [System.Net.Http.HttpClientHandler]::new()
$handler.AllowAutoRedirect  = $false
$client                     = [System.Net.Http.HttpClient]::new($handler)

$response = $client.PostAsync($url, $form).Result

Write-Host "Status: $($response.StatusCode)"

if ($response.Headers.Location) {
    $redirectUrl = $response.Headers.Location.ToString()
    # Resolve relative URLs
    if ($redirectUrl -notmatch "^https?://") {
        $redirectUrl = "$baseUrl$redirectUrl"
    }
    Write-Host "Redirect URL: $redirectUrl"
    # Open in default browser
    Start-Process $redirectUrl
} else {
    Write-Host "Body: $($response.Content.ReadAsStringAsync().Result)"
}

# Clean up
$form.Dispose()
$client.Dispose()

2. macOS (bash + curl)

#!/bin/bash

BASE_URL="https://order.4ortho.nl"
ENDPOINT="/api/ticket/YOUR_API_TOKEN/01/YOUR_LOGIN_DEBITNUMBER/P.%20Atient/123456/2008-09-01/"

URL="${BASE_URL}${ENDPOINT}"
# List the files to upload
FILES=(
    "/path/to/scan1.stl"
    "/path/to/scan2.stl"
)

# Post files, do NOT follow redirects — capture the Location header
REDIRECT_URL=$(curl -s -o /dev/null -w '%{redirect_url}' \
    $(printf -- '-F "a-file[]=@%s" ' "${FILES[@]}") \
    "$URL")

echo "Redirect URL: $REDIRECT_URL"

# Open in default browser
if [ -n "$REDIRECT_URL" ]; then
    open "$REDIRECT_URL"          # macOS
    # xdg-open "$REDIRECT_URL"   # Linux
fi

3. Java (HttpClient, Java 11+)

import java.io.*;
import java.net.*;
import java.net.http.*;
import java.nio.file.*;
import java.util.*;

public class TicketUploader {

    public static void main(String[] args) throws Exception {
        String baseUrl  = "https://order.4ortho.nl";
        String endpoint = "/api/ticket/YOUR_API_TOKEN/01/YOUR_LOGIN_DEBITNUMBER/P.%20Atient/123456/2008-09-01/";
        URI uri = URI.create(baseUrl + endpoint);
        List<Path> files = List.of(
            Path.of("/path/to/scan1.stl"),
            Path.of("/path/to/scan2.stl")
        );

        // Generate a unique boundary
        String boundary = "----Boundary" + UUID.randomUUID();

        // Build multipart body
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        for (Path file : files) {
            String fileName = file.getFileName().toString();
            baos.write(("--" + boundary + "\r\n").getBytes());
            baos.write(("Content-Disposition: form-data; name=\"a-file[]\"; filename=\"" + fileName + "\"\r\n").getBytes());
            baos.write(("Content-Type: application/octet-stream\r\n\r\n").getBytes());
            baos.write(Files.readAllBytes(file));
            baos.write("\r\n".getBytes());
        }
        baos.write(("--" + boundary + "--\r\n").getBytes());

        // Do NOT follow redirects — we need the Location header
        HttpClient client = HttpClient.newBuilder()
            .followRedirects(HttpClient.Redirect.NEVER)
            .build();

        HttpRequest request = HttpRequest.newBuilder()
            .uri(uri)
            .header("Content-Type", "multipart/form-data; boundary=" + boundary)
            .POST(HttpRequest.BodyPublishers.ofByteArray(baos.toByteArray()))
            .build();

        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

        int status = response.statusCode();
        System.out.println("Status: " + status);

        if (status >= 300 && status < 400) {
            String location = response.headers().firstValue("Location").orElse(null);
            if (location != null) {
                // Resolve relative redirects against the original URL
                URI redirectUri = uri.resolve(location);
                System.out.println("Redirect URL: " + redirectUri);

                // Open in default browser
                if (Desktop.isDesktopSupported()) {
                    Desktop.getDesktop().browse(redirectUri);
                }
            }
        } else {
            System.out.println("Body: " + response.body());
        }
    }
}

Notes

  • The field name must be exactly a-file[] (name not important, but must include the brackets to create a list of files).
  • All examples open a webbrowser with the given redirect-target – this is the proper way; upload files, capture the location URL, open it, withint short succession
  • There is no incremental file upload
  • There is no resume upload
  • All files must be given at the same time, in their complete form
  • Above examples are Claude Code generated, please treat them as such. The end goal is; a HTTP FORM compatible file upload + open the redirect location when done

Special cases

  • you can add ?no_redirect=bytegear to the URL to receive a JSON object instead of a redirect, sample output is;
{
  "location": "https://order.4ortho.nl/api/session/4c76e115435447a1321f3c8f78e6bd7e9831fb4a/",
  "owner": 18,
  "current_time": 1776420891,
  "ttl": 1776420951
}
  • Here you can see a serial time the redirect was requested on and one that tells the latest you can use it; you have 1 minute from receiving the object to opening the link.