curl --request POST \
--url https://go.aiinsurance.io/api/v1/companies/{companyId}/files/migrations/finalize \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"source": {
"environment": "https://legacy.example.com",
"companyId": "legacy-company-42",
"fileId": "legacy-file-17"
},
"revision": {
"bucket": "legacy-company-files",
"object": "documents/loss-run.pdf",
"generation": "1720000000000000",
"byteSize": 102400,
"contentType": "application/pdf",
"md5Hash": "1B2M2Y8AsgTpgAmY7PhCfg=="
},
"versionId": "550e8400-e29b-41d4-a716-446655440021"
}
'import requests
url = "https://go.aiinsurance.io/api/v1/companies/{companyId}/files/migrations/finalize"
payload = {
"source": {
"environment": "https://legacy.example.com",
"companyId": "legacy-company-42",
"fileId": "legacy-file-17"
},
"revision": {
"bucket": "legacy-company-files",
"object": "documents/loss-run.pdf",
"generation": "1720000000000000",
"byteSize": 102400,
"contentType": "application/pdf",
"md5Hash": "1B2M2Y8AsgTpgAmY7PhCfg=="
},
"versionId": "550e8400-e29b-41d4-a716-446655440021"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
source: {
environment: 'https://legacy.example.com',
companyId: 'legacy-company-42',
fileId: 'legacy-file-17'
},
revision: {
bucket: 'legacy-company-files',
object: 'documents/loss-run.pdf',
generation: '1720000000000000',
byteSize: 102400,
contentType: 'application/pdf',
md5Hash: '1B2M2Y8AsgTpgAmY7PhCfg=='
},
versionId: '550e8400-e29b-41d4-a716-446655440021'
})
};
fetch('https://go.aiinsurance.io/api/v1/companies/{companyId}/files/migrations/finalize', 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://go.aiinsurance.io/api/v1/companies/{companyId}/files/migrations/finalize",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'source' => [
'environment' => 'https://legacy.example.com',
'companyId' => 'legacy-company-42',
'fileId' => 'legacy-file-17'
],
'revision' => [
'bucket' => 'legacy-company-files',
'object' => 'documents/loss-run.pdf',
'generation' => '1720000000000000',
'byteSize' => 102400,
'contentType' => 'application/pdf',
'md5Hash' => '1B2M2Y8AsgTpgAmY7PhCfg=='
],
'versionId' => '550e8400-e29b-41d4-a716-446655440021'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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://go.aiinsurance.io/api/v1/companies/{companyId}/files/migrations/finalize"
payload := strings.NewReader("{\n \"source\": {\n \"environment\": \"https://legacy.example.com\",\n \"companyId\": \"legacy-company-42\",\n \"fileId\": \"legacy-file-17\"\n },\n \"revision\": {\n \"bucket\": \"legacy-company-files\",\n \"object\": \"documents/loss-run.pdf\",\n \"generation\": \"1720000000000000\",\n \"byteSize\": 102400,\n \"contentType\": \"application/pdf\",\n \"md5Hash\": \"1B2M2Y8AsgTpgAmY7PhCfg==\"\n },\n \"versionId\": \"550e8400-e29b-41d4-a716-446655440021\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://go.aiinsurance.io/api/v1/companies/{companyId}/files/migrations/finalize")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"source\": {\n \"environment\": \"https://legacy.example.com\",\n \"companyId\": \"legacy-company-42\",\n \"fileId\": \"legacy-file-17\"\n },\n \"revision\": {\n \"bucket\": \"legacy-company-files\",\n \"object\": \"documents/loss-run.pdf\",\n \"generation\": \"1720000000000000\",\n \"byteSize\": 102400,\n \"contentType\": \"application/pdf\",\n \"md5Hash\": \"1B2M2Y8AsgTpgAmY7PhCfg==\"\n },\n \"versionId\": \"550e8400-e29b-41d4-a716-446655440021\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://go.aiinsurance.io/api/v1/companies/{companyId}/files/migrations/finalize")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"source\": {\n \"environment\": \"https://legacy.example.com\",\n \"companyId\": \"legacy-company-42\",\n \"fileId\": \"legacy-file-17\"\n },\n \"revision\": {\n \"bucket\": \"legacy-company-files\",\n \"object\": \"documents/loss-run.pdf\",\n \"generation\": \"1720000000000000\",\n \"byteSize\": 102400,\n \"contentType\": \"application/pdf\",\n \"md5Hash\": \"1B2M2Y8AsgTpgAmY7PhCfg==\"\n },\n \"versionId\": \"550e8400-e29b-41d4-a716-446655440021\"\n}"
response = http.request(request)
puts response.read_body{
"sourceId": "550e8400-e29b-41d4-a716-446655440019",
"fileId": "550e8400-e29b-41d4-a716-446655440020",
"currentVersionId": "550e8400-e29b-41d4-a716-446655440021",
"revision": {
"versionId": "550e8400-e29b-41d4-a716-446655440021",
"storageKey": "companies/example/files/550e8400-e29b-41d4-a716-446655440020/550e8400-e29b-41d4-a716-446655440021",
"state": "ready",
"uploadUrl": null,
"byteSize": 102400,
"contentType": "application/pdf"
},
"metadata": {
"displayName": "Loss run.pdf",
"displayDate": "2020-01-02T03:04:05.000Z",
"displayAuthor": "Legacy adjuster"
},
"conflicts": []
}Finalize File Migration
Step 2 of a migration document load. After the bytes reach the resumable upload URL from Prepare File Migration (prepareCompanyFileMigration), call this to verify them and make the version current. Next, call Reconcile File Migration Metadata (reconcileCompanyFileMigration) to attach the file to its records, folders, and categories. Everyday uploads use Finalize Upload (finalizeCompanyFileUpload) instead.
Verifies the destination object size, normalized MIME type and matching source checksums, then atomically makes this known version current and retains integrity evidence. Retrying an already verified active revision returns its state. A missing object, checksum mismatch, superseded revision or operator version change cannot be finalized. Migration versions must use this endpoint; ordinary file finalization rejects them. Upload completion is separate from asynchronous malware scanning; an infected result requires attention and must not trigger another upload.
Available only while the destination company is in Sandbox mode. Forms are outside this contract.
Required permission: file.upload
Also requires file.view and file.edit.
curl --request POST \
--url https://go.aiinsurance.io/api/v1/companies/{companyId}/files/migrations/finalize \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"source": {
"environment": "https://legacy.example.com",
"companyId": "legacy-company-42",
"fileId": "legacy-file-17"
},
"revision": {
"bucket": "legacy-company-files",
"object": "documents/loss-run.pdf",
"generation": "1720000000000000",
"byteSize": 102400,
"contentType": "application/pdf",
"md5Hash": "1B2M2Y8AsgTpgAmY7PhCfg=="
},
"versionId": "550e8400-e29b-41d4-a716-446655440021"
}
'import requests
url = "https://go.aiinsurance.io/api/v1/companies/{companyId}/files/migrations/finalize"
payload = {
"source": {
"environment": "https://legacy.example.com",
"companyId": "legacy-company-42",
"fileId": "legacy-file-17"
},
"revision": {
"bucket": "legacy-company-files",
"object": "documents/loss-run.pdf",
"generation": "1720000000000000",
"byteSize": 102400,
"contentType": "application/pdf",
"md5Hash": "1B2M2Y8AsgTpgAmY7PhCfg=="
},
"versionId": "550e8400-e29b-41d4-a716-446655440021"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
source: {
environment: 'https://legacy.example.com',
companyId: 'legacy-company-42',
fileId: 'legacy-file-17'
},
revision: {
bucket: 'legacy-company-files',
object: 'documents/loss-run.pdf',
generation: '1720000000000000',
byteSize: 102400,
contentType: 'application/pdf',
md5Hash: '1B2M2Y8AsgTpgAmY7PhCfg=='
},
versionId: '550e8400-e29b-41d4-a716-446655440021'
})
};
fetch('https://go.aiinsurance.io/api/v1/companies/{companyId}/files/migrations/finalize', 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://go.aiinsurance.io/api/v1/companies/{companyId}/files/migrations/finalize",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'source' => [
'environment' => 'https://legacy.example.com',
'companyId' => 'legacy-company-42',
'fileId' => 'legacy-file-17'
],
'revision' => [
'bucket' => 'legacy-company-files',
'object' => 'documents/loss-run.pdf',
'generation' => '1720000000000000',
'byteSize' => 102400,
'contentType' => 'application/pdf',
'md5Hash' => '1B2M2Y8AsgTpgAmY7PhCfg=='
],
'versionId' => '550e8400-e29b-41d4-a716-446655440021'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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://go.aiinsurance.io/api/v1/companies/{companyId}/files/migrations/finalize"
payload := strings.NewReader("{\n \"source\": {\n \"environment\": \"https://legacy.example.com\",\n \"companyId\": \"legacy-company-42\",\n \"fileId\": \"legacy-file-17\"\n },\n \"revision\": {\n \"bucket\": \"legacy-company-files\",\n \"object\": \"documents/loss-run.pdf\",\n \"generation\": \"1720000000000000\",\n \"byteSize\": 102400,\n \"contentType\": \"application/pdf\",\n \"md5Hash\": \"1B2M2Y8AsgTpgAmY7PhCfg==\"\n },\n \"versionId\": \"550e8400-e29b-41d4-a716-446655440021\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://go.aiinsurance.io/api/v1/companies/{companyId}/files/migrations/finalize")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"source\": {\n \"environment\": \"https://legacy.example.com\",\n \"companyId\": \"legacy-company-42\",\n \"fileId\": \"legacy-file-17\"\n },\n \"revision\": {\n \"bucket\": \"legacy-company-files\",\n \"object\": \"documents/loss-run.pdf\",\n \"generation\": \"1720000000000000\",\n \"byteSize\": 102400,\n \"contentType\": \"application/pdf\",\n \"md5Hash\": \"1B2M2Y8AsgTpgAmY7PhCfg==\"\n },\n \"versionId\": \"550e8400-e29b-41d4-a716-446655440021\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://go.aiinsurance.io/api/v1/companies/{companyId}/files/migrations/finalize")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"source\": {\n \"environment\": \"https://legacy.example.com\",\n \"companyId\": \"legacy-company-42\",\n \"fileId\": \"legacy-file-17\"\n },\n \"revision\": {\n \"bucket\": \"legacy-company-files\",\n \"object\": \"documents/loss-run.pdf\",\n \"generation\": \"1720000000000000\",\n \"byteSize\": 102400,\n \"contentType\": \"application/pdf\",\n \"md5Hash\": \"1B2M2Y8AsgTpgAmY7PhCfg==\"\n },\n \"versionId\": \"550e8400-e29b-41d4-a716-446655440021\"\n}"
response = http.request(request)
puts response.read_body{
"sourceId": "550e8400-e29b-41d4-a716-446655440019",
"fileId": "550e8400-e29b-41d4-a716-446655440020",
"currentVersionId": "550e8400-e29b-41d4-a716-446655440021",
"revision": {
"versionId": "550e8400-e29b-41d4-a716-446655440021",
"storageKey": "companies/example/files/550e8400-e29b-41d4-a716-446655440020/550e8400-e29b-41d4-a716-446655440021",
"state": "ready",
"uploadUrl": null,
"byteSize": 102400,
"contentType": "application/pdf"
},
"metadata": {
"displayName": "Loss run.pdf",
"displayDate": "2020-01-02T03:04:05.000Z",
"displayAuthor": "Legacy adjuster"
},
"conflicts": []
}Authorizations
User-principal OAuth 2.0 Bearer authentication. Send a user-scoped Auth0 access token (audience = the app API audience) as Authorization: Bearer <jwt>. The request resolves to the user's identity and is authorized by their Role on the {companyId} in the path — the same role-based permissions the web app enforces. This is the path the MCP connector uses to act on a user's behalf; endpoints that accept it list both BearerAuth and ApiKeyAuth.
Body
Response
Durable migration state
