DEV Community

Cover image for API Workflow Automation Power Automate: Connect Document Processing to Your Tech Stack
Lucien Chemaly
Lucien Chemaly

Posted on

API Workflow Automation Power Automate: Connect Document Processing to Your Tech Stack

Power Automate handles Microsoft-native document actions well, but the moment your stack reaches outside that ecosystem the built-in options run thin. When a processed file has to land in a Salesforce record, a contract management system, or a storage layer feeding an external ERP, you need to call an outside service directly. AI Builder is a fit while you stay inside Microsoft's toolset; the HTTP action is what bridges to everything else. This tutorial connects Power Automate to the Foxit PDF Services API through that action, with no custom connector to define and no SDK to install.

You will build a flow that picks up a Word document from SharePoint, converts it to PDF with the PDF Services API, and routes the result to a downstream system. Authentication is header-based, with a client_id and a client_secret sent on every request. The processing model is a four-step async pattern (upload, initiate, poll, download) that runs the same way whichever PDF operation you pick. By the end you have a production-oriented flow pattern that adapts to any operation the API exposes.

Prerequisites

Three things need to be in place before you add the first HTTP action.

  • A Foxit Developer account : create one free (no credit card) and retrieve your Client ID and Client Secret from the APIs Dashboard. Sign up at account.foxit.com/site/sign-up.
  • Power Automate with premium connector access : the HTTP action is a premium connector, so confirm your plan includes it before you start.
  • A SharePoint document library (or equivalent trigger source) : any connector that surfaces a file and its binary content works, and SharePoint is the common starting point for enterprise document flows.

Foxit APIs Dashboard showing the Client ID and Client Secret for an API application

The APIs Dashboard is where you copy the Client ID and Client Secret you will pass as request headers.

How the integration works

Foxit offers two ways to work with Power Automate. One is the pre-built Foxit eSign connector, which surfaces envelope and signature operations as native actions you drop into a flow without writing HTTP calls. The other, which this tutorial uses, is the HTTP action pointed at the full PDF Services API for conversions, merges, splits, flattens, compression, page extraction, and password protection.

The PDF Services API is a headless, cloud-hosted REST API on the base host https://na1.fusion.foxit.com/pdf-services. You call endpoints, pass your credentials as headers, and read JSON back, with no UI, no local install, and no SDK dependency. Every operation runs as an asynchronous job, so it follows one shape.

  1. Upload the source file and receive a documentId.
  2. Initiate a task against that documentId and receive a taskId.
  3. Poll the task until its status reaches COMPLETED.
  4. Download the result using the resultDocumentId that the completed task returns.

Knowing that shape up front explains why the flow has four HTTP action blocks. The authentication is identical across all four; only the URI and the body change from step to step.

Authenticate Foxit API calls in the HTTP action

The PDF Services API uses header-based authentication. You pass two named headers, client_id and client_secret, on every request. There is no OAuth exchange, no bearer token, and no connector registration. The header keys are lowercase with an underscore, so sending an Authorization: Bearer header instead returns a 400.

In the Power Automate HTTP action, open the Headers panel and add the two credential headers plus Content-Type.

Power Automate HTTP action Headers panel showing client_id and client_secret set to environment-variable expressions, plus a Content-Type header

The Headers panel for a Foxit call. The credentials are referenced as environment variables rather than pasted in, and Content-Type changes per step.

Do not paste raw credentials into the action. Store them as Power Automate environment variables and reference them with expressions such as @{parameters('FoxitClientId')} and @{parameters('FoxitClientSecret')}. That keeps secrets out of the exported flow definition and makes rotation a one-place change.

The same header pair applies to all four steps. Only two things vary. The URI changes to the endpoint for each step, and the body changes to match. The Content-Type header also shifts, since the upload sends multipart/form-data while the initiate call sends application/json, so update that third header as you build each step.

Build the four-step document processing flow

Lay the structure down first, then configure each block.

Flowchart of the four-step Power Automate pattern: upload, initiate task, poll, download, then route output

Architecture of the four-step Power Automate flow, from SharePoint trigger through upload, initiate, poll, and download to downstream routing

The full flow. A SharePoint trigger feeds four HTTP actions and a Do Until poll, then routes the finished PDF onward.

Step 1: Upload the source file

Add an HTTP action after your SharePoint trigger. Set the method to POST and the URI to https://na1.fusion.foxit.com/pdf-services/api/documents/upload, with Content-Type set to multipart/form-data. The upload endpoint accepts the file as a form field named file and caps input at 100 MB, and it deletes uploaded files after 24 hours, so the returned documentId is short-lived. If you want a ready sample to test with, use input.docx.

To send multipart/form-data from the HTTP action, set the body to Power Automate's multipart structure, which carries the file part under $multipart.

{  
  "$content-type": "multipart/form-data",  
  "$multipart": [  
    {  
      "headers": {  
        "Content-Disposition": "form-data; name=\"file\"; filename=\"input.docx\""  
      },  
      "body": {  
        "$content-type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",  
        "$content": "@{base64(body('Get_file_content'))}"  
      }  
    }  
  ]  
}  
Enter fullscreen mode Exit fullscreen mode

In this code, you declare the request as multipart, then describe a single part whose Content-Disposition name is file, which is the form field the upload endpoint expects. The part's body is an object rather than a string, since binary content travels as a $content base64 payload with its own $content-type, and base64(body('Get_file_content')) converts the file that the Get file content action returned. A successful upload responds with JSON containing a documentId, so follow the action with a Parse JSON step that surfaces documentId as a string, then reference it in step 2.

One quirk to know about here. Since a 2023 change, escaped quote characters in the Content-Disposition value can make the HTTP action send JSON instead of multipart. If the upload comes back rejected, put a single " character in a Compose action and reference that Compose output where the quotes belong, which sidesteps the escaping.

The upload HTTP action in Power Automate, showing the upload URI, the POST method, client_id and client_secret headers as environment-variable expressions, a multipart Content-Type, and the multipart request body

The finished upload action. The credentials are environment-variable references, Content-Type is set to multipart for this step only, and the body carries the $multipart structure with the file part.

Step 2: Initiate the task

Add a second HTTP action with method POST. This example converts a Word file to PDF, so point the URI at https://na1.fusion.foxit.com/pdf-services/api/documents/create/pdf-from-word. The body carries only the documentId from step 1.

{  
  "documentId": "@{body('Parse_Upload_Response')?['documentId']}"  
}  
Enter fullscreen mode Exit fullscreen mode

The code above hands the uploaded document to the convert task. The call returns HTTP 202 with a taskId, which identifies the running job. Parse the response to pull taskId out, since you pass it as a path segment in the step 3 poll URI.

Step 3: Poll the status endpoint

Add a Do Until loop. Inside it, place a third HTTP action that GETs https://na1.fusion.foxit.com/pdf-services/api/tasks/{taskId} with the task id in the path, then a Parse JSON action to read the response. The status response carries a status field, a progress percentage, and, once finished, a resultDocumentId.

Set the Do Until to exit when the status reaches COMPLETED. Status values are uppercase, so branching on a lowercase completed never matches.

@equals(body('Parse_Status_Response')?['status'], 'COMPLETED')  
Enter fullscreen mode Exit fullscreen mode

Set a maximum iteration count of 30 and add a Delay action before the poll request. A 10-second gap between checks suits most operations, since polling with no delay hammers the API each cycle and can burn your run budget on longer jobs.

Step 4: Download the processed file

Once the loop exits, read resultDocumentId from the completed status response. Add a fourth HTTP action with method GET and URI https://na1.fusion.foxit.com/pdf-services/api/documents/{resultDocumentId}/download. The response body is your processed PDF, ready to route. Pass the resultDocumentId from the poll here, not the upload documentId, since swapping the two is the most common 4xx at this step.

The download returns the file with a content type of application/pdf, so a successful run gives you a PDF whose text and embedded images carry over from the source document.

First page of the PDF returned by the download step, showing body text and an embedded photograph preserved from the source Word file

The converted output from a real run against the sample DOCX. Paragraph flow and the embedded image both survive the conversion, which is the quickest way to confirm the pipeline worked end to end.

Route the output and handle flow errors

The processed PDF is now in the flow. Route it.

Route 1, back to SharePoint : add a Create file action from the SharePoint connector. Set the folder path to your target library, the file name to your convention, and the file content to the body of the step 4 response. The PDF lands in SharePoint for downstream flows or users.

Route 2, external webhook (CRM or ERP) : add a fifth HTTP action after the download. Method POST, URI set to your system's inbound webhook, Content-Type set to application/json, and the file content in the body (base64-encode it if the receiver expects that) alongside any metadata the integration needs.

Wrap the Do Until loop in a Scope action to catch stuck jobs. Open the Scope's Configure run after settings and check both has failed and has timed out. In that error branch, add an alert (a Teams message or an email) that surfaces the task id and the raw status.

@{body('Parse_Status_Response')?['status']}  
Enter fullscreen mode Exit fullscreen mode

The expression above reads the last status the poll saw. A task can also land on FAILED, and the Scope catches both a FAILED job and a poll that never reaches COMPLETED within 30 iterations, so a stuck job surfaces as an alert rather than a silent gap you notice weeks later in an audit.

Common mistakes

Most failures in this flow trace back to a short list of details. Check these first.

  • camelCase header keys or a bearer token : the keys are lowercase client_id and client_secret. Sending clientId and clientSecret, or wrapping the credentials in an Authorization: Bearer header, returns a 400.
  • Branching on a lowercase status : task statuses come back uppercase, so a Do Until condition testing for completed never matches and the loop runs to its iteration cap before giving up.
  • Passing the wrong id to the download call : the download takes the resultDocumentId from the completed task, not the documentId you got from the upload. Swapping the two is the most common 4xx at the final step.
  • Escaped quotes in Content-Disposition : since a 2023 change, escaped quote characters can make the HTTP action send JSON instead of multipart, so the upload is rejected. Hold a single " in a Compose action and reference it instead.
  • Leaving Content-Type on one value : the upload needs multipart/form-data and the initiate call needs application/json. Reusing one value across both steps breaks whichever step is wrong.
  • Waiting for a download URL in the status response : there isn't one. The completed task gives you resultDocumentId, and you build the download URI from it.
  • Polling with no delay : a Do Until without a Delay action hits the API every cycle and burns your run budget on longer jobs. Ten seconds between checks is a reasonable default.
  • Reusing a stale documentId : uploaded files are deleted after 24 hours, so an id from yesterday's run no longer resolves. Uploads are also capped at 100 MB.
  • Expecting one task to convert and flatten : each operation is its own task. Chain them by feeding the first task's resultDocumentId into the next call as its documentId.

FAQ

Do I need a paid Power Automate plan?

Yes for the HTTP action, which is a premium connector. The Foxit side is free to test, since the Developer plan requires no credit card.

Does the trigger have to be SharePoint?

No. Anything that hands the flow a file and its content works, including OneDrive, a Dataverse row, an inbound HTTP request, or a scheduled trigger that fetches the file itself.

How do I convert something other than Word?

Change the step 2 endpoint. The create category covers Excel, PowerPoint, HTML, and URL sources, so create/pdf-from-excel or create/pdf-from-url slots in without touching the upload, poll, or download steps.

What happens when a task fails?

The poll returns a status of FAILED along with an error, and the Do Until exits on that terminal state. The Scope block described above catches it and routes to your alert path.

Can I run several operations on one document?

Yes. Chain tasks by passing the resultDocumentId from one completed task as the documentId of the next, which is how a convert-then-compress or convert-then-flatten sequence works.

Is there a native Foxit connector instead of the HTTP action?

There is a Foxit eSign connector for signature workflows, but PDF Services operations are not exposed as native actions, so the HTTP action is the route for conversions and other document processing.

What comes next

The pattern you built, header auth plus a four-step async job plus downstream routing, carries to any PDF Services operation. Keep steps 1, 3, and 4 exactly as they are and only change the step 2 endpoint. Flatten is POST /pdf-services/api/documents/modify/pdf-flatten, compress is modify/pdf-compress, split is modify/pdf-split, and combine is enhance/pdf-combine, each taking the same documentId body (combine takes a documentInfos array instead). To convert and then flatten, chain two tasks, feeding the first task's resultDocumentId into the flatten call as its documentId.

Test your endpoints before they touch production data. Foxit's developer portal at developer-api.foxit.com includes a sandbox for running real requests against the API. Create a free account (no credit card) at account.foxit.com/site/sign-up and run your upload, initiate, and poll calls there first.

What document workflows are you automating with Power Automate? Drop your setup in the comments.

Top comments (0)