The two functions that do the conversion

In Workday Orchestrate, base64decode(contentType) turns Base64 text into a file with the content type you name, and base64encode() turns a file into Base64. Both are member functions of the Data type. A String holding Base64 can call base64decode directly, because StringType extends TextType, which is a subtype of DataType.

data.GetDocs.response.asXML()
  .stringAtXPath("/env:Envelope/env:Body/wd:Get_Worker_Documents_Response/wd:Response_Data/wd:Worker_Document/wd:Worker_Document_Data/wd:File")
  .base64decode("application/pdf")

That expression returns a PDF you can store, attach or send. Going the other way, documentFile.base64encode() returns the Base64 form, still as Data. Add .toString() only if a function needs a String argument.

The Data type also has base64MimeDecode(contentType) and base64MimeEncode() for the Base64 MIME form. Use the plain pair for Workday SOAP and REST fields and for JSON APIs. Use the MIME pair only when the other system says its content is MIME-encoded.

Decode a Base64 field from a Workday response into a file

Workday's SOAP API returns attachment content as Base64 text. In the Staffing web service, the File element of Worker_Document_Data is typed xsd:base64Binary and documented as file content in Base64 encoding. Workday's Extend Orchestration Toolkit sample app shows two common sources:

  • SOAP: read wd:File from the Get_Worker_Documents response with stringAtXPath, as in the example above. The same pattern works for Get_Drive_Document_Content.
  • RaaS: a custom report that exposes the attachment's content and content type. The sample reads both fields with stringAtJsonPath and decodes with the content type taken from the report rather than a hard-coded one, in the form data.Values.rawContent.base64decode(data.Values.fileType).

The content type argument matters. base64decode sets the decoded document's content type to whatever you pass. A PDF decoded as text/plain has the right bytes and the wrong label, and anything that reads contentType() or receives the file downstream sees the wrong type. When the source gives you the MIME type, pass it through.

Encode a file into Base64 for a SOAP request

To load a file into Workday through SOAP, put the encoded file inside a Create Text Template step that builds the request body. Workday's Worker Image Upload Inbound sample builds the Photo_Data of a Change_Person_Photo request this way, taking the photo from the integration event's documents:

<wd:Photo_Data>
  <wd:Filename>{{data.Control.fileName}}</wd:Filename>
  <wd:File>{{documents.documentId(data.start.documentId).get().base64encode()}}</wd:File>
</wd:Photo_Data>

documents.documentId(id).get() returns the event document as Data. You can also select by file name with documents.name(fileName).get(), or loop over every document with documents.iterator(). A file stored earlier with Store Document comes back from Retrieve Document as content plus file name, given the collection and entry ID.

The template is the right place for the encoding. Workday's text template runtime is fully streaming, so you can embed large documents in a template without loading them into memory. Then send the template's message as the body of a Send Workday API Request.

Workday's web service limits set a maximum attachment size of 30 MB for both SOAP and REST, and the same 30 MB for images. Check contentLength() before you build the request. For a file over the limit, a clear message in your orchestration log is more useful than a rejected request.

Avoid converting large Base64 values to a String

Orchestrate keeps large Data and Text values on disk in file-backed structures. A String is held in memory. Workday's data types page warns that toString() can move file-backed data into memory and creates a copy, so you may briefly hold two copies. The orchestration's in-memory limit is 200 MB at a time, including temporary values created while evaluating expressions.

That gives two rules for Base64 work:

  • Reading a large Base64 field out of JSON: textDataAtJsonPath(path) returns a Text document, while stringAtJsonPath(path) returns a String. Because Text is a Data subtype, the Text result can call base64decode directly without going through memory as a String.
  • Writing Base64 into a request: embed {{file.base64encode()}} in a Create Text Template instead of building the body with addStringValue(..., file.base64encode().toString()).

addStringValue with toString() is fine for a small image from a page upload. Workday's PMD Widget Dictionary sample does exactly that with a fileUploader part, data.start.entity.part(1).content().base64encode().toString(). Don't carry that pattern over to batch files.

Write a file into an Extend attachment object

An Extend attachment object stores its file in a file field as a Base64-encoded string, alongside the generated fileName, fileLength and contentType fields. You can write fileName, but fileLength and contentType are derived from the file and you can only read them.

If the attachment object has extra fields of your own, Workday requires a multipart/form-data request to write the file and the field data together. In Send Workday API Request, choose Form Multipart Body and add two parts in this order:

  1. Part 0, named data, content type application/json, with a body such as {"file": "cid:filedata", "uploadedBy": {"id": "..."}}.
  2. Part 1, named filedata, content type application/octet-stream, with Select Data pointing at the decoded file, not the Base64 text.

Order matters. Workday's attachment documentation notes that sending the JSON data part after the file data returns a 500 internal server error. To upload several files in one request, post to the attachment object's endpoint with Collection appended and reference each file part from an array named after the object's default collection.

To read a file back, call GET on the instance without an Accept header and you get the file content. With Accept: application/json you get only the field data. The Extend attachment business objects guide covers the model side, and Extend file upload limits covers the page side.

Send a decoded file to an external system

To send a decoded file to an external endpoint, use Send HTTP Request with Reference Existing Data pointing at the Data value from base64decode, or a Form Multipart Body part with content type application/octet-stream and the content disposition parameters the receiving API expects. Use Send HTTP Request only for non-Workday endpoints. Workday's reference sends Workday API calls through Send Workday API Request.

If the receiving API wants Base64 inside JSON, use plain base64encode() in a Create Text Template:

{
  "fileName": "{{data.Control.fileName}}",
  "content": "{{data.GetFile.content.base64encode()}}"
}

Plain Base64 uses only letters, digits, +, / and =, so it needs no JSON escaping. The MIME form inserts line breaks (RFC 2045), which is one more reason to use the plain functions for JSON.

Prove the conversion produced the file you expected

A Base64 conversion can succeed and still produce the wrong file. Check three things:

  • After decoding, log contentType() and contentLength() of the result. The length should match the file size the source reports. For documents found with Find Documents, that is the size field, in bytes. Base64 text is about a third longer than the file, so if the length matches the Base64 field, you have the text, not the file.
  • In an Integration System orchestration, store the decoded file with Store Document and set Attach document to integration event to true. Download it from the integration event in the tenant and open it.
  • After an upload, read the target back: call Get_Worker_Documents for the worker, or GET the attachment object instance, and confirm the file name and length.

For files that arrive as a zip archive, decode with base64decode("application/zip"), list the entries with listFilesInZipArchive() and pull each one out with fetchFileFromZipArchive(path). The Orchestrate Sampler's unzip example does exactly this. Don't reach for unzip(contentType) here: it decompresses gzipped data, not zip archives. See zipping and unzipping files in Orchestrate and generating a PDF attachment for the neighbouring steps.

Sources checked