How an Extend app sends a file to Document Intelligence
An Extend app sends a document to Document Intelligence by saving the user's upload in an attachment business object, reading the file back in an orchestration, and posting the raw bytes to https://api.workday.com/ml/docint/v1/<endpoint> with Content-Type: application/octet-stream. The response is JSON you can map onto the app's own records or show on a page.
Workday's App Catalog reference app, Document Intelligence with the AI Gateway, is built this way, and its Scan Document orchestration is the working example the steps below follow.
Which Document Intelligence endpoint fits which document
All six APIs share the base URL https://api.workday.com/ml/docint/{version} (currently v1) and take a single file in the request body. They differ in what they return.
| Endpoint | Accepts | Returns |
|---|---|---|
EndpointPOST /doc | AcceptsPDF, JPG/JPEG, PNG | Returnstext: the document as newline-separated strings |
EndpointPOST /receipt | AcceptsPDF, JPG/JPEG, PNG | ReturnsscanProperties such as amount, date, merchant, currency, each with a confidence |
EndpointPOST /resume | AcceptsDOCX, PDF with real text (not a scanned image) | Returnsstructured sections: contact, education, experience, references, summary |
EndpointPOST /contracts?document_type= | AcceptsPDF, JPG/JPEG, PNG | Returnstext plus fields |
EndpointPOST /financials?document_type= | AcceptsPDF, JPG, PNG | Returnstext plus fields |
EndpointPOST /ids?document_type= | AcceptsPDF, JPG, PNG | Returnstext plus fields |
The last three require the document_type query parameter. Contracts takes supplier_contract or customer_contract; Financial Documents takes us_bank_statement, us_bank_check, payslips or w2_form; Identification Documents takes passport (non-US), us_passport or us_drivers_license.
Each entry in fields carries type, page_number, mention_text, start_index, end_index, normalized_value and normalized_vertices. Map from normalized_value where it is present: Workday trims it and returns dates as YYYY-MM-DD, which saves you parsing mention_text yourself.
The maximum file size for every Document Intelligence API is 20 MB.
Turn the service on before you write the app
AI Gateway is available in Development tenants for all customers and in other tenants only for Extend AI customers; the Workday Extend Packages page lists it as an Extend AI feature. In a non-Development tenant you also have to opt in:
- Enable the Innovation Services feature and Machine Learning data contributions.
- On the Innovation Services Opt-In task, under Available Services, select WCP > Workday AI Gateway.
- On the Innovation Services Data Selection Opt-In task, select WCP: Workday AI Gateway and opt in to the data categories it lists, including Receipt Scanning for Expenses, Generic Documents and Resume Documents.
- On Edit Tenant Setup - Machine Learning, choose the hosting region for Machine Learning data contributions. Workday lets you set this region once; changing it later goes through Customer Support.
If you skip this, the call fails with HTTP 403. Workday documents 403 for both a missing opt-in and a tenant that is not entitled, so check the package and the opt-in before you look at security.
Step 1: save the upload in an attachment object
Define an attachment business object for the scanned files. Workday adds file, fileName, fileLength and contentType to every attachment object, and you can add your own fields beside them. The reference app's Document object adds uploadedBy, uploadedDate, scanned and scanType, so the orchestration knows which endpoint to call and the page can show which files have been processed.
On the page, a fileUploader widget feeds an outbound endpoint that POSTs to the object's collection with baseUrlType workday-app. Set multiPartFileLast to true on that endpoint: when an attachment object has extra fields, the request is multipart/form-data, and Workday's attachment documentation warns that sending the JSON data after the file data returns a 500.
For upload widget limits and file-type checks on the page, see file upload and attachment limits in Extend.
Step 2: read the file back in the orchestration
Launch an orchestration from the same outbound sequence and pass it the new document's ID. Inside it, the attachment API gives you two different reads of the same instance:
GET /apps/<appReferenceId>/v1/documents/<id>with noAcceptheader returns the file data.- The same GET with
Accept: application/jsonreturns the field data only, such asscanType.
The reference orchestration does both with two Send Workday API Request steps, then reads the type with data("GetDocumentMetadata", "response").asJSON().stringAtJsonPath("$.scanType"). The reference flow builds the attachment path with context.appReferenceId() rather than hard-coding the app reference ID, which differs from one Developer Site account to another.
Step 3: post the bytes to Document Intelligence
The scan is a third Send Workday API Request step:
- Method
POST. - Path: built by interpolation, as the reference flow does with
s"${"/ml/docint/v1/"}${data("SetDocumentValues","scanType")}", plus?document_type=…for contracts, financials and IDs. - Header
content-type: application/octet-stream. - Body: the file read in step 2, passed through as
data("GetDocument", "response").asTEXT()with content typeapplication/octet-stream. - Credential: the default Workday credential. The reference app sets the flow's default credential to the token of the user who launched it, so the scan runs as that user.
In the reference flow the Send Workday API Request step takes only the path, not the host. If you call the API from outside an app, use your region's gateway from the API gateways reference; calling another region's gateway can return 401: Unauthorized.
A 422 means a missing or invalid request parameter, most often a missing or misspelled document_type. Workday lists a 500 as a missing file attachment. Check that the step 2 read returned the file itself and not the field data, which is what you get if that GET carries Accept: application/json.
Step 4: write the result back and show it
Record the outcome on the attachment instance so it is not scanned twice. The reference app PATCHes {"scanned": true} back to /apps/<appReferenceId>/v1/documents/<id>. Then end the orchestration with a Create Text Template set to application/json that wraps the scan response, and have the page bind its fields from the launch response.
Two documented details should shape what the app does with the values:
- Receipt values arrive with a
confidencescore. In the reference response it ranges from 0.46 for a date to 0.89 for a currency, so treat a low score as a value for the user to confirm, not one to submit unseen. - The Resume API is tuned for text-based files. Workday's own guidance is to avoid images, text boxes, tables and columns, and to keep personal details out of headers and footers. Since
/resumedoes not accept image-based PDFs, a scanned resume can only go to/doc, which returns plain text.
Watch the page's 25-second budget
A synchronous orchestration launched from a presentation page has 25 seconds in total, and that limit overrides any timeout you set on the steps. Workday does not publish scan times, so time your largest realistic file in a test run. If the scan, the reads and the write-back come near the limit, switch to an asynchronous orchestration that writes the scanned values onto the record, and have the page read the record when the user returns to it. The launch message itself can be up to 20 MB, matching the Document Intelligence file limit, but passing an ID and reading the file inside the flow keeps the launch small.
Prove it worked
A successful run is not the same as a correct scan. Check three things against the same test file:
- The orchestration's step messages show the ScanDocument step returned 200 and the log of its response contains the expected
textorfields. - Reading the attachment instance with
Accept: application/jsonshowsscannedset totrue. - The value on the page, or the value your app saved to its business object, matches the document: the receipt amount, the contract's effective date, the check's routing number.
If any step fails, the Orchestrate error guide covers credential and request-body faults that affect every Send Workday API Request step, not only this one.
kiweely can run that last check for you: it uploads the test file through the deployed page as a given user in the browser, then reads the attachment instance and the run's step messages back from the tenant, so you see the stored result rather than only a green run.
Sources checked
- Concept: Workday AI Gateway
- Document Intelligence REST APIs
- Document Scan REST API
- Receipt REST API
- Resume REST API
- Contracts REST API
- Financial Documents REST API
- Identification Documents REST API
- Concept: Attachment Objects
- Workday Extend Packages
- Reference: Workday Extend API Gateways and Authorization Base URLs
- Reference: Orchestration Runtime Limits