Moving your integration from RikAI to Applied Intelligence Engine (AIE)
RikAI 2 and RikAI 2-Extract endpoints will be replaced on 13 November 2026. AIE is a different API surface, not a drop-in host swap: the request body is restructured, results arrive on a separate webhook from status updates, and several response fields are renamed. This guide maps every field you send and every field you receive. AIE documentation can be found here.
| Date | Milestone | What it means |
|---|---|---|
| 11 September 2026 | Test endpoints live | Your credentials have access to the new AIE endpoints. |
| September – October 2026 | 60-day test window | Run both stacks in parallel against your own documents. |
| 13 November 2026 | RikAI 2 and RikAI 2-Extract switched off | Existing endpoints stop accepting requests. |
1. What actually changes
Below table overviews the areas that have changed, and what remains the same.
| Area | RikAI | AIE | Impact |
|---|---|---|---|
| Path | api.lazarusforms.com/api/rikai/… | api-prod.lazarusforms.com/api/engine/bulk | Changed |
| Auth headers | orgId, authKey, apiVersion | Identical | Same |
| Request body | Flat keys, except settings | Nested input / output objects, as well as settings | Rewrite |
| Result delivery | Webhook or outputURL receives status and results | Results go to output.url, specify POST or PUT method; status goes to statusWebhook.url | Rewrite |
| Result shape | data is an array | data is a single object | Rewrite |
| Status polling | api.lazarusforms.com/api/rikai/zip/async/{statusId} | api-prod.lazarusforms.com/api/engine/jobs/{jobId}/status | Changed |
| File types & size cap | PDF, PNG, JPG/JPEG, TIF/TIFF, HEIC, TXT | Unchanged | Same |
| HTTP response codes | 200, 207, 400, 403, 404, 413, 429, 521 | Unchanged | Same |
2. Endpoints and authentication
Authentication is unchanged. Send the same orgId and authKey headers you use today; apiVersion stays optional and defaults to the latest production version. Pin apiVersion to the latest version, 2026-08-01, explicitly during migration so a platform release can't move underneath your test run.
| Purpose | Today (off 31 Oct) | AIE (live 1 Sep) |
|---|---|---|
| Submit files | POST api.lazarusforms.com/api/rikai/bulk/rikai2 | POST api-prod.lazarusforms.com/api/engine/bulk |
| Check job status | GET api.lazarusforms.com/api/rikai/zip/async/{statusId} | GET api-prod.lazarusforms.com/api/engine/jobs/{jobId}/status |
Paths follow the AIE API reference.
3. Request mapping
Every RikAI parameter and where it goes. The shape is the real change: flat top-level keys become two nested objects — input (what to process) and output (where to send the answer).
| RikAI | AIE | Status | Notes |
|---|---|---|---|
inputURL | input.file[].url | Moved | file is an array of objects. |
base64 | input.file[].base64 | Moved | file is an array of objects. |
sftp | input.file[].sftp and output.sftp | Moved | One top-level block becomes per-file and per-output credentials (user, password, privateKey, privateKeyPassphrase). |
question | input.prompt | Renamed and moved | |
outputURL | output.url | Moved | Required in AIE. This is where the answer is delivered. In output, ability to also choose contentType (application/json or application/zip), headers, method (POST or PUT) and sftp credentials. |
outputURLHeaders | output.headers | Moved | |
returnJSON | output.contentType | Moved | Boolean becomes an explicit content type; defaults to application/json. Choose application/zip to match RikAI 2's ability to send a ZIP file in outputURL. |
| — | output.method | New | Option between POST or PUT. Defaults to POST. Set PUT to match RikAI 2's outputURL behavior. |
webhook | statusWebhook.url | Moved | Now lifecycle events only — submitted, running, failed, succeeded. No answer data. |
webhookHeaders | statusWebhook.headers | Moved | Set output.headers too if your result endpoint also needs auth. |
webhookSendFull | — | Gone | Obsolete. The status/result split does what this flag used to. Omit statusWebhook entirely for result-only delivery. |
fileId | inputId | Renamed | Still your own correlation key, still echoed back on every response. |
forceOCR | rasterize | Renamed | Same purpose: set true for fillable PDFs. |
returnOCR | — | Deprecated | Deprecated — there is no AIE equivalent. Remove it from your request body. |
settings | settings | Changed | Now structured: modelSettings.capability, modelSettings.tier, explainabilitySettings.enabled, advancedExplainability. See "Settings" below. |
language | language | Same | |
metadata | metadata | Same | Still echoed on every webhook. |
staticIP | staticIP | Same |
RikAI 2 request
{
"inputURL": "https://you.example/doc.pdf",
"question": "What is the policy number?",
"webhook": "https://you.example/hook",
"fileId": "claim-8842",
"forceOCR": true,
"language": "EN",
"metadata": { "batch": "q3" }
}
AIE request
{
"input": {
"file": [{ "url": "https://you.example/doc.pdf" }],
"prompt": "What is the policy number?"
},
"output": {
"url": "https://you.example/results",
"method": "POST",
"contentType": "application/json"
},
"statusWebhook": { "url": "https://you.example/hook" },
"inputId": "claim-8842",
"rasterize": true,
"language": "EN",
"metadata": { "batch": "q3" }
}
Settings
Unless Lazarus has told you otherwise, for RikAI 2 migration use these modelSettings: capability: "standard" and tier: "light". See RikAI 2-Extract migration in section 5.
"settings": {
"modelSettings": {
"capability": "standard",
"tier": "light"
}
}
If your workload needs a different configuration, Lazarus provides a per-client recommendation.
Full parameter reference: AIE bulk upload · RikAI 2 bulk upload
4. Bulk submission and multiple questions
Multiple files in one request carries over. What is documented on both sides:
| Capability | RikAI 2 | AIE |
|---|---|---|
| Multiple files | inputURL accepts a string or an array | input.file is always an array of file objects |
| Your correlation IDs | fileId accepts a string or an array | inputId accepts a string or an array |
| Questions | question | input.prompt |
| Answers come back as | data — an array of answer objects | data — a single answer object per output webhook |
5. Migrating RikAI 2-Extract
RikAI 2-Extract migrates to the same AIE endpoint as RikAI 2. Everything in sections 1–4 and 6–10 applies to Extract as well: same hosts, same authentication, same nested request body, same split between the status webhook and the result webhook, same envelope renames. Three things are specific to Extract — the endpoint you leave behind, the model settings you must send, and where your extraction schema now lives.
Relevant Documentation Pages
5.1 Endpoint
| Purpose | Today (off 13 Nov) | AIE |
|---|---|---|
| Submit files | POST api.lazarusforms.com/api/rikai/bulk/rikai2-extract | POST api-prod.lazarusforms.com/api/engine/bulk |
| Check job status | GET api.lazarusforms.com/api/rikai/zip/async/{statusId} | GET api-prod.lazarusforms.com/api/engine/jobs/{jobId}/status |
RikAI 2 and RikAI 2-Extract converge on one AIE endpoint.
5.2 Model settings — required
Extract workloads need a different capability from the RikAI 2 values in section 3. Send:
"settings": {
"modelSettings": {
"capability": "consistent-output-structure",
"tier": "standard"
}
}
capabilitymust be"consistent-output-structure"— this is what constrains the model to your schema.tieris"standard"for Extract workloads, not the"light"tier used for RikAI 2 in section 3.- If your workload needs a different configuration, Lazarus provides a per-client recommendation.
5.3 Your extraction schema moves to settings.responseSchema
| RikAI 2-Extract | AIE | Status | Notes |
|---|---|---|---|
question — a JSON string or dictionary holding your extraction schema | settings.responseSchema | Moved and reformatted | Same intent, different format, improved results. This is the one part of an Extract migration that is a rewrite rather than a rename. |
question | input.prompt | New | Not a replacement for the schema. Use it alongside the schema for additional guidance and context. |
| — | responseSchema at the top level | Avoid | A top-level responseSchema exists but is deprecated in favour of settings.responseSchema. Use the nested one. |
AIE constrains output with a JSON Schema. Per the structured outputs guide, this lets you extract multiple structured fields in one call, guarantee that fields are always present, enforce types such as numbers, dates and booleans, and have the platform validate and retry against the schema. Write the schema using the structured outputs guide as the authority on supported keywords.
5.4 Worked example
An Extract request pulling four fields off a policy document, before and after.
RikAI 2-Extract request
{
"inputURL": "https://you.example/policy.pdf",
"question": {
"policyNumber": "The policy number on the declarations page",
"insuredName": "Full name of the named insured",
"effectiveDate": "Policy effective date in YYYY-MM-DD",
"premium": "Total annual premium"
},
"webhook": "https://you.example/hook",
"fileId": "policy-8842"
}
AIE request
{
"input": {
"file": [{ "url": "https://you.example/policy.pdf" }],
"prompt": "Read the declarations page. If a field is absent, return null."
},
"output": {
"url": "https://you.example/results",
"method": "POST",
"contentType": "application/json"
},
"statusWebhook": { "url": "https://you.example/hook" },
"inputId": "policy-8842",
"settings": {
"modelSettings": {
"capability": "consistent-output-structure",
"tier": "standard"
},
"responseSchema": {
"type": "object",
"properties": {
"policyNumber": { "type": "string",
"description": "The policy number on the declarations page" },
"insuredName": { "type": "string",
"description": "Full name of the named insured" },
"effectiveDate": { "type": "string",
"description": "Policy effective date in YYYY-MM-DD" },
"premium": { "type": "number",
"description": "Total annual premium" }
},
"required": ["policyNumber", "insuredName",
"effectiveDate", "premium"]
}
}
}
How to translate your own question object
- Each key in your Extract
questionbecomes a key underproperties. Keep the key names identical and your downstream code keeps working. - The instruction text you wrote as that key's value becomes its
description. - Add a
type. Extract inferred types from your wording;responseSchemaenforces them, so a premium that used to come back as"1,240.00"can be typed as a number. - List the keys you always want present in
required. This is the guarantee Extract could not give you. - Anything in your old question that was general guidance rather than a field — "use the declarations page", "dates are UK format" — moves to
input.prompt, not into the schema.
5.5 Response differences
The envelope is identical to section 6. Inside the answer, Extract-specific differences:
| RikAI 2-Extract | AIE | Status | Notes |
|---|---|---|---|
data (array) | data (object) | Changed | Same unwrap as RikAI 2: data[0].answer becomes data.answer. |
data[].answer (object) | data.answer | Same | Your extracted structure. Its shape is governed by settings.responseSchema. |
data[].question (your schema, echoed) | settings echo | Moved | The schema is no longer echoed inside data. If your code reads it back from the answer, read it from the echoed settings instead. |
| — | data.fieldConfidences | New | Per-field confidence for each key in your schema. Extract returned no confidence at all. |
| — | data.confidence, data.context | New | Present on the AIE answer object. Extract returned neither. |
5.6 Extract-specific checks
Run these in addition to the checklist in section 9.
- Capability is set —
capabilityis"consistent-output-structure"andtieris"standard", not the section 3 values. - Schema is nested — the schema is under
settings.responseSchema, not at the top level. - Key names match — every key your downstream code reads exists in
propertiesunder the same name it had in the Extractquestion. - Types hold — numeric and date fields come back as the declared type across a representative document set, not as strings.
- Required fields appear — every key in
requiredis present on every answer, including for documents where the value is missing. - Field parity — the same documents produce the same extracted values on Extract and on AIE.
6. Response mapping
RikAI 2 posted six payload types to one URL. AIE posts four status payloads to statusWebhook.url and one result payload to output.url.
Envelope fields — on every payload
| RikAI | AIE | Status | Notes |
|---|---|---|---|
statusId | jobId | Renamed | Also the path parameter on the status endpoint. |
fileId (as sent) | inputId | Renamed | |
id | id | Same | |
status | status | Same | |
apiVersion | apiVersion | Same | Format YYYY-MM-DD. |
metadata | metadata | Same | |
startTime / endTime | startTime / endTime | Same | Unix epoch. |
documentId | — | Gone | Use jobId plus your own inputId to correlate. |
model, baseModel | — | Gone | AIE is model-independent; the runtime is no longer named in the payload. Drop any logic that branches on these. |
organization, provider | — | Gone |
Result fields — the success payload
| RikAI | AIE | Status | Notes |
|---|---|---|---|
data (array) | data (object) | Changed | data[0].answer becomes data.answer. |
data[].answer | data.answer | Same | |
data[].question | data.prompt | Renamed | |
data[].confidence | data.confidence | Same | |
data[].context | data.context | Same | |
data[].translated (string) | data.translated.answer | Changed | String becomes an object. |
data[].translatedContext | data.translated.context | Moved | |
data[].warning | data.warning | Same | |
| — | data.fieldConfidences | New | Per-field confidence for structured answers. Replacement for RikAI2-Extract. |
questions | prompts | Renamed | |
pages | pages | Same | |
ocrResults | ocrResults | Deprecated | returnOCR request flag that controlled this on RikAI 2 is deprecated. |
settings | settings | Changed | Echoed back in the new nested shape. |
language | language | Same | |
code | code | Same |
RikAI 2 success webhook
{
"status": "...", "code": 200,
"data": [
{
"answer": "PN-4471",
"question": "What is the policy number?",
"confidence": 0.97,
"context": "...",
"translated": "PN-4471"
}
],
"statusId": "...", "documentId": "...",
"model": "rikai2", "baseModel": "...",
"questions": 1, "pages": 3,
"organization": "...", "provider": "lazarus"
}
AIE output webhook
{
"status": "SUCCESS",
"data": {
"answer": "PN-4471",
"prompt": "What is the policy number?",
"confidence": 0.97,
"context": "...",
"fieldConfidences": { },
"translated": {
"answer": "PN-4471", "context": "..."
}
},
"jobId": "...", "inputId": "claim-8842",
"prompts": 1, "pages": 3,
"apiVersion": "2026-06-30", "metadata": { }
}
Schemas: AIE output webhook · AIE status webhooks · RikAI 2 webhook responses
7. Errors and failure handling
HTTP codes on the submit call are unchanged — 200, 207 partial success, 400, 403, 404, 413 over 32 MB, 429 rate limit, 521. Failure webhooks still carry code, message, and an error object.
One difference worth handling explicitly: if AIE cannot deliver to output.url, you get a warning payload on the status webhook, not a silent drop. Log the jobId so the result can be re-requested.
8. How to run the migration
- Inventory what you send and what you read. List every RikAI 2 parameter your code sets and every response field it reads. Check both against sections 3 and 6 — and section 5 if you use RikAI 2-Extract.
- Build against test, in parallel. Using your preferred environment credentials (e.g. staging or QA), keep RikAI 2 running. Send the same documents to both and diff the answers. Confidence scores will not be byte-identical; the extracted values are what you are comparing. The Lazarus team is here to help you as needed.
- Run the validation checklist. Section 9. Your QA team can run it as written.
- Tell Lazarus your cutover date. By 1 November, the on-call window is staffed for you.
- Switch production and monitor. By 13 November. Lazarus monitors alongside you for the first week.
9. Validation checklist
Run every line against the test before you name a cutover date.
- Right credentials, right environment — your test
orgId/authKeyare configured per environment. - Submit succeeds — a single-file request to
/api/engine/bulkreturns200with ajobId. - Settings are explicit —
capabilityis"standard"andtieris"light", unless Lazarus recommended otherwise for you. - Bulk job parses — a multi-file submission is reassembled correctly on your side from the individual
dataobjects, correlated oninputId. - Status endpoint responds —
GET /api/engine/jobs/{jobId}/statusreturns the job. - All four status events arrive —
SUBMITTED,RUNNING, thenSUCCESSorFAILUREon your status webhook. - Result arrives separately — your
output.urlhandler receives the answer payload, and your status handler does not try to readdatafrom it. - Correlation holds —
inputIdandmetadatacome back on every payload and match what you sent. - Object, not array — your parser reads
data.answer. - Renamed fields are read —
jobId,inputId,prompt,rasterize. - Removed fields are not read — nothing branches on
documentId,model,baseModel,ocrResults,organization, orprovider. - Status enum matches exactly — string comparison against
SUCCESS/FAILURE/AUTH_FAILURE/RUNNING/SUBMITTED. - Fillable PDFs —
rasterize: truereturns the same valuesforceOCR: truedid. - Answer parity — a representative document set produces matching extracted values on both stacks.
Migrating RikAI 2-Extract? Run section 5.6 as well.
10. Reference
| Document | Link |
|---|---|
| AIE engine — API reference | docs.lazarusai.com/2026-06-30/models/AIE/engine |
| AIE output webhook — result payload | Output-Webhook-Response |
| AIE status webhooks — lifecycle payloads | Status-Webhook-Responses |
| AIE structured outputs — writing responseSchema | Structured outputs guide |
| RikAI 2 — API reference | docs.lazarusai.com/2026-06-30/models/Rikai/rikai2/ |
| RikAI 2 — webhook response schemas | Webhook-Responses |
| RikAI 2-Extract — API reference | docs.lazarusai.com/models/Rikai/rikai2-extract/ |
| Getting started | Quickstart |