Skip to main content
Integrations & API

Import email attachments with Microsoft Power Automate

Build a shared-mailbox workflow that uploads PDF attachments to fynk using Power Automate and the REST API.

Written By Sebastian

Last updated About 7 hours ago

Use Microsoft Power Automate and the fynk REST API to turn a shared Microsoft 365 mailbox into an inbox for PDF documents. Each eligible attachment creates a separate document in fynk, with the teams and tags you choose.

This is a custom automation you configure and maintain in your Microsoft environment. The example imports PDF attachments; it does not import the email body, automatically map email information to metadata, or start a signing process.

Can I use Zapier, Make or n8n instead?

Yes. The same API-based approach can also be implemented in Zapier, Make or n8n: trigger on an incoming email, retrieve each PDF attachment, request an upload slot, upload the file with the returned form fields, and create the document in fynk.

Use the platform's HTTP or webhook actions for these requests. You do not need a dedicated fynk action for every step. The Power Automate expressions and multipart JSON shown below are specific to Power Automate; rebuild the field mappings and file upload in your chosen platform.

  • Zapier: use Webhooks by Zapier. For the storage upload, use its file-capable POST action with the attachment and returned form fields. The Custom Request action cannot send file objects; it can be used for the JSON API requests. Check webhook payload limits and plan availability.
  • Make: use the HTTP app with JSON for the fynk API requests and multipart/form-data for the storage upload. Map every returned form field and the attachment's filename and file data.
  • n8n: use the HTTP Request node. For the upload, choose Form-Data, add the returned fields as form parameters, and add the attachment as an n8n Binary File parameter named file.

Your email connector must provide access to the attachment contents. Apply the same API permissions, team assignment, duplicate prevention and failure handling described in this guide. These alternatives are supported by the platforms' documented HTTP/file-upload capabilities; this article is a Power Automate walkthrough, not an end-to-end tested recipe for all three platforms.

Before you start

  • A fynk Business or Pro account with API access, and an Owner to create the API token.
  • A Microsoft Power Automate licence that permits the premium HTTP action, and permission to use the required connectors in your tenant.
  • An Exchange Online shared mailbox and a Microsoft 365 connection account with Full Access to it. Ask your Microsoft 365 administrator to configure access and confirm that the account can open the mailbox.
  • At least one party configured in fynk under Account settings → My Parties, and the team that should receive imported documents.

The flow makes three requests for each PDF: request an upload slot, upload the file to the returned storage URL, then create the fynk document.

1. Create the API token

Go to Account settings → API integrations → fynk API → Configure. Under API Tokens, choose Create Token. Give the token a descriptive name and the Document Manager role. If you will create a tag through the API, add Tag Manager for that setup step. Copy the token and store it securely; it is shown only once.

See REST API: get started for token expiry, permissions and API versions. Check the API reference against your configured API version before deploying the flow.

For requests to the fynk API, use these headers. Replace the token placeholder with your securely stored token value:

Authorization: Bearer <your-API-token>
Accept: application/json
Content-Type: application/json

Use a secret store, such as Azure Key Vault, where available. Enable Secure Inputs and Secure Outputs on actions handling the token, temporary upload credentials or document content. These settings hide data in run history; they do not prevent subsequent actions from using it. Protect the email trigger's output too, where supported. Restrict who can edit the flow.

2. Find the tag and team UUIDs

You can run these setup requests using an API client or a temporary manually triggered flow with HTTP actions and the headers above.

  • Find existing tags: GET https://app.fynk.com/v1/api/tags?per_page=100.
  • Find teams: GET https://app.fynk.com/v1/api/teams?per_page=100.

Copy the UUIDs of the tag and team you want to use. Follow pagination if the results span more than one page. If a setup request returns a permissions error, check the endpoint's required token roles in the API reference.

To create a new tag, send POST https://app.fynk.com/v1/api/tags with:

{
  "name": "From Email",
  "color": "#615fff"
}

Keep its returned UUID. Do not put tag creation inside the recurring import flow. Remove the temporary setup flow when finished and remove Tag Manager from the token if it is no longer needed. Tags are optional; omit tag_uuids from the final request if you do not want one.

3. Watch the shared mailbox

Create an automated cloud flow with the Office 365 Outlook trigger When a new email arrives in a shared mailbox (V2).

  • Original Mailbox Address: your shared mailbox address.
  • Folder: select the inbox using the folder picker; its name may be localized.
  • Include Attachments: Yes.
  • Only with Attachments: Yes.

Add Apply to each using the trigger's Attachments output. Rename the loop to EachAttachment before adding expressions.

Inside the loop, add an AND condition with both checks:

  • items('EachAttachment')?['isInline'] equals the boolean expression false (not the text “false”).
  • toLower(items('EachAttachment')?['name']) ends with .pdf.

Add all three HTTP actions below inside the If yes branch, in order. Leave If no empty. This skips inline images and non-PDF attachments; a PDF filename alone does not guarantee that the contents are a valid PDF.

4. Request an upload slot

Add an HTTP action named Get upload URL. The expressions below refer to its internal name Get_upload_URL; adjust the expressions if your designer assigns a different name.

  • Method: POST
  • URI: https://app.fynk.com/v1/api/file-uploads/document-pdf
  • Headers: the fynk API headers from step 1.
  • Body: {}

The response supplies data.url, data.fields and data.uuid. Use the returned values for this attachment, rather than saving them as constants: the upload credentials are temporary.

5. Upload the PDF

Add an HTTP action named Upload PDF. Set the method to POST and use this URI:

@{body('Get_upload_URL')?['data']?['url']}

Leave the HTTP headers empty. In particular, do not send your fynk bearer token to the storage URL or manually set the multipart boundary. Use this body:

{
  "$content-type": "multipart/form-data",
  "$multipart": [
    {
      "headers": {
        "Content-Disposition": "form-data; name=\"key\""
      },
      "body": "@{body('Get_upload_URL')?['data']?['fields']?['key']}"
    },
    {
      "headers": {
        "Content-Disposition": "form-data; name=\"acl\""
      },
      "body": "@{body('Get_upload_URL')?['data']?['fields']?['acl']}"
    },
    {
      "headers": {
        "Content-Disposition": "form-data; name=\"Content-Type\""
      },
      "body": "@{body('Get_upload_URL')?['data']?['fields']?['Content-Type']}"
    },
    {
      "headers": {
        "Content-Disposition": "form-data; name=\"X-Amz-Security-Token\""
      },
      "body": "@{body('Get_upload_URL')?['data']?['fields']?['X-Amz-Security-Token']}"
    },
    {
      "headers": {
        "Content-Disposition": "form-data; name=\"X-Amz-Algorithm\""
      },
      "body": "@{body('Get_upload_URL')?['data']?['fields']?['X-Amz-Algorithm']}"
    },
    {
      "headers": {
        "Content-Disposition": "form-data; name=\"X-Amz-Credential\""
      },
      "body": "@{body('Get_upload_URL')?['data']?['fields']?['X-Amz-Credential']}"
    },
    {
      "headers": {
        "Content-Disposition": "form-data; name=\"X-Amz-Date\""
      },
      "body": "@{body('Get_upload_URL')?['data']?['fields']?['X-Amz-Date']}"
    },
    {
      "headers": {
        "Content-Disposition": "form-data; name=\"policy\""
      },
      "body": "@{body('Get_upload_URL')?['data']?['fields']?['policy']}"
    },
    {
      "headers": {
        "Content-Disposition": "form-data; name=\"X-Amz-Signature\""
      },
      "body": "@{body('Get_upload_URL')?['data']?['fields']?['X-Amz-Signature']}"
    },
    {
      "headers": {
        "Content-Disposition": "form-data; name=\"file\"; filename=\"@{items('EachAttachment')?['name']}\""
      },
      "body": "@base64ToBinary(items('EachAttachment')?['contentBytes'])"
    }
  ]
}

Send every form field returned by the upload-slot response, with its exact name and value. The example includes X-Amz-Security-Token; if your API response uses a different field set, adapt the multipart entries accordingly. Keep the file part last.

The file body must be binary. In the JSON above, @base64ToBinary(...) is a whole expression. Do not change it to string interpolation with @{...}. When entering it through the designer's Expression tab, enter base64ToBinary(items('EachAttachment')?['contentBytes']) without the leading @.

6. Create the document in fynk

Add an HTTP action named Create document, configured to run only after the upload succeeds.

  • Method: POST
  • URI: https://app.fynk.com/v1/api/documents/create-from-pdf
  • Headers: the fynk API headers from step 1.

Use this body, replacing the tag and team placeholders with real UUIDs:

{
  "file_upload_uuid": "@{body('Get_upload_URL')?['data']?['uuid']}",
  "file_name": "@{items('EachAttachment')?['name']}",
  "initial_stage": "draft",
  "tag_uuids": [
    "<tag-uuid>"
  ],
  "team_uuids": [
    "<team-uuid>"
  ]
}

Add further team UUIDs to the array if needed. Include the intended teams explicitly; accounts requiring team assignment can reject requests without them.

Use draft for documents that still need work. For already completed contracts, use done instead. This setting does not initiate signing or add signatures to the uploaded PDF.

7. Test the complete flow

  1. Send a small, non-sensitive PDF to the shared mailbox.
  2. Confirm that all three HTTP actions succeed. The customer's example returned 200 for the upload slot and 204 for the storage upload.
  3. Open the created document in fynk. Verify its contents, filename, stage, tag and team access.
  4. Send an email with two PDFs and an inline image. Confirm that it creates two documents and skips the image.
  5. Test a non-PDF attachment and a failed import, then confirm that your recovery process works without duplicating successful documents.

Before using it as a production inbox

  • Prevent duplicates: add a persistent processing record keyed by mailbox, message ID and attachment ID. Store the created fynk document UUID after success. The basic flow above does not implement deduplication. A timeout after creation may still mean a document was created; reconcile the result before resubmitting.
  • Handle failures per attachment: add an error-handling scope with “Configure run after” for failed or timed-out actions, and notify the flow owner. Track successful and failed attachments separately so that one failure does not require reimporting everything.
  • Plan retries: respect fynk's Retry-After response when rate-limited. Avoid blindly retrying document creation, and request a fresh upload slot if its temporary credentials have expired.
  • Check attachment limits: test realistic file sizes and volume against Microsoft connector and fynk API limits. Password-protected or encrypted files need separate testing; this example has no password-handling step.
  • Keep an owner: monitor token expiry and mailbox connection health. Archive or move emails only after all intended attachments are confirmed imported.

For busy mailboxes, Microsoft's connector documentation recommends retrieving attachment content separately to reduce trigger timeouts. In that variant, set Include Attachments to No and use Get Attachment (V2) inside the loop with the message ID, attachment ID and shared mailbox address. Replace the upload's content expression with the content returned by that action; the example above assumes attachment content is included in the trigger.

Troubleshooting

  • “Root folder not found”: confirm Full Access for the account used by the Outlook connection, allow permissions to propagate, then reconnect and select the mailbox folder again.
  • 401 or 403 from fynk: check the bearer token, expiry, API access and roles.
  • 422 mentioning team UUIDs: supply valid team UUIDs in team_uuids and check the response for other validation errors.
  • Invalid PDF or 409 during creation: verify that the upload succeeded, the source is a valid PDF, and the multipart file body uses the binary expression.
  • Storage upload rejected: check that all returned form fields are present, unmodified and unexpired. Request a new slot if necessary.
  • Expression or input validation errors: check action names, loop names and JSON syntax. Names such as Get_upload_URL_2 need matching expressions.
  • Inputs or outputs hidden in run history: this is expected with secure logging enabled. Use non-sensitive test files and inspect status codes and error messages without exposing tokens or upload credentials.