Payhawk → Google Drive receipt sync avatar

Payhawk → Google Drive receipt sync

Pricing

Pay per usage

Go to Apify Store
Payhawk → Google Drive receipt sync

Payhawk → Google Drive receipt sync

Automatically archive Payhawk expense receipts (PDFs) to a Google Drive folder. Incremental, idempotent, schedule-friendly — every new receipt lands in Drive without duplicates.

Pricing

Pay per usage

Rating

0.0

(0)

Developer

Apify

Apify

Maintained by Apify

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

2 days ago

Last modified

Categories

Share

What is the Payhawk → Google Drive receipt sync?

This Actor automatically copies every expense receipt PDF from your Payhawk account into a Google Drive folder. You set it up once, run it on a schedule, and every new receipt your team uploads to Payhawk lands in Drive — ready for your accountant, your bookkeeping system, or long-term archival. No more downloading attachments one expense at a time.

The Actor uses Payhawk's official Developer API to list expenses that have not yet been exported, downloads each receipt, uploads it to a Google Drive folder of your choice, and tells Payhawk that the receipt has been exported — all without duplicates.

What can this Payhawk to Google Drive Actor do?

  • Incremental sync. Only processes expenses Payhawk reports as not exported, so each run is fast and skips work already done.
  • Idempotent. Files are named deterministically (payhawk-<expenseId>.pdf). If a file with the same name already exists in the destination folder, the Actor reuses it instead of creating a duplicate.
  • Multi-file expenses. Expenses with several attached receipt pages are uploaded as payhawk-<expenseId>-1.pdf, payhawk-<expenseId>-2.pdf, and so on.
  • Marks expenses as exported in Payhawk. Writes an entry to the Payhawk export history so each expense disappears from the not exported list and your team can see where the receipt was sent.
  • Dry-run mode. Validate everything is wired up correctly before any file is written to Drive.
  • Detailed run report. Every processed expense becomes one row in the dataset (status, file name, Drive link, error if any) for run-by-run auditing.
  • Powered by the Apify platform. Schedule runs, monitor failures, integrate with your other tools, and access results via the Apify API — all out of the box.

How does the Payhawk to Google Drive sync work?

On each run, the Actor:

  1. Calls Payhawk GET /accounts/:accountId/expenses with the filter export.status = not-exported, paginating with $skip/$take.
  2. For each expense, reads expense.document.files[] and downloads each attached receipt PDF.
  3. Uploads each PDF to your Google Drive folder. The folder must live in a Shared Drive so the Google service account can write to it.
  4. Calls Payhawk POST /expenses/:expenseId/export-history with exportStatus: succeeded and a link to the Drive file, marking the expense exported.
  5. Records the synced expense ID in a named key-value store as a safety net against duplicates across runs.

How much will it cost to sync Payhawk receipts to Google Drive?

The Actor is billed in Apify Compute Units (CUs). It does no heavy CPU work — every run is mostly waiting on Payhawk and Google Drive responses — so usage is low even with hundreds of receipts. As a rough order of magnitude, a few hundred receipts per run on default memory settings will consume a small fraction of a CU. The free tier on Apify is plenty for evaluating the Actor on a typical month of expenses.

The Payhawk and Google Drive APIs the Actor calls are free to use within their published rate limits (Payhawk's developer API is rate-limited to 15 requests per second). The sync is well under that ceiling.

How to set up the Payhawk to Google Drive Actor

Step 1: Get your Payhawk API key

In Payhawk, go to Settings → Integrations → API → Create key. Copy the key (it is sent in the X-Payhawk-ApiKey header). The account ID is shown alongside the key and also appears in any Payhawk URL.

Put the values into payhawkApiKey and payhawkAccountId.

Step 2: Create a Google service account

Service accounts are how a long-running Actor can write to Drive without an interactive Google login.

  1. In the Google Cloud Console: IAM & Admin → Service Accounts → Create service account. Any name works (e.g. payhawk-sync).
  2. Open the new service account → Keys → Add key → Create new key → JSON. Save the downloaded JSON; you will paste it into googleServiceAccount.
  3. In APIs & Services → Library, search for and enable the Google Drive API for the project.

Step 3: Create a Shared Drive folder and share it with the service account

This step is required. Service accounts have no storage quota in a personal My Drive. Uploads to a regular My Drive folder fail with Service Accounts do not have storage quota. A Shared Drive is the supported way to give a service account a place to write.

  1. In Google Drive, open the left sidebar → Shared drives → + New. Name the drive anything you like (for example, Payhawk receipts).
  2. Inside the Shared Drive, create a folder for the receipts.
  3. Open the Shared Drive → Manage members → add your service account's email (xxx@<project>.iam.gserviceaccount.com, found in the JSON you downloaded) with the Content manager role.
  4. Open the destination folder and copy the ID from the URL: drive.google.com/drive/folders/<id>. Paste it into driveFolderId.

Step 4: Run with dry-run enabled

For the first run, set dryRun to true. The Actor will list expenses and download receipts but will not write to Drive or Payhawk. Confirm the logs look right (e.g. the expected number of expenses are found), then flip dryRun to false and run for real.

Step 5: Schedule it

Once a real run succeeds, create an Apify schedule at the cadence you want (daily and hourly are common choices).

Input

The Actor takes the following inputs — see the Input tab for the full schema with descriptions and secret handling.

  • payhawkApiKey — Payhawk API key.
  • payhawkAccountId — Payhawk account ID.
  • googleServiceAccount — Service account JSON for Google Drive access.
  • driveFolderId — Destination Drive folder ID (must live inside a Shared Drive).
  • exportedInto (optional) — Label written to Payhawk's export history. Defaults to Google Drive.
  • dryRun (optional) — When true, skip all writes. Defaults to false.

Output

The Actor writes one dataset row per processed expense, with the upload status and a link to the file in Drive. You can download the dataset in JSON, CSV, Excel, HTML, RSS, or XML — same as any Apify Actor.

[
{
"expenseId": "224",
"status": "uploaded",
"fileName": "payhawk-224.pdf",
"driveFileId": "1a2BcDeFgHIjkLmnOPqRsTuvWxYz",
"driveFileUrl": "https://drive.google.com/file/d/1a2BcDeFgHIjkLmnOPqRsTuvWxYz/view"
},
{
"expenseId": "225",
"status": "reused",
"fileName": "payhawk-225.pdf",
"driveFileId": "9Z8YxWvUtSrQpOnMlKjIhGfEdCbA",
"driveFileUrl": "https://drive.google.com/file/d/9Z8YxWvUtSrQpOnMlKjIhGfEdCbA/view"
},
{
"expenseId": "226",
"status": "no-receipt"
}
]

Status values: uploaded, reused (file already existed in Drive), skipped-already-synced (already in local dedupe state), no-receipt (expense had no attached document), error.

FAQ

Why does the upload fail with "Service Accounts do not have storage quota"?

The destination folder is in a personal My Drive instead of a Shared Drive. Service accounts can be granted access to a My Drive folder, but they cannot own files there, and Drive will refuse the upload. Move the folder into a Shared Drive (see Step 3 of Setup) and use that folder ID instead.

Can I sync to a personal My Drive folder?

Not with a service account. The alternative is OAuth domain-wide delegation, which makes the service account impersonate a Workspace user, so uploaded files use that user's quota. This requires a Google Workspace administrator to grant the delegation. Most teams find creating a Shared Drive easier.

Will running the Actor twice create duplicate files in Drive?

No. The Actor checks for an existing file with the same payhawk-<expenseId>.pdf name in the destination folder before uploading, and Payhawk's export.status filter excludes already-exported expenses. As an extra safety net, synced expense IDs are tracked in a named key-value store.

What happens to expenses without an attached receipt?

They are reported as no-receipt in the dataset and skipped. The expense is not marked exported in Payhawk, so it will be re-evaluated on the next run (giving your team a chance to upload the receipt).

Is this a two-way sync?

No, it's one-way: Payhawk → Google Drive. Files deleted from Drive are not re-uploaded on the next run, because the expense has already been marked exported in Payhawk.

How do I change the label that appears in Payhawk's export history?

Set the exportedInto input. It defaults to Google Drive. During testing, change it to something like Test sync so test runs are clearly distinguishable in Payhawk's UI from real ones.

How do I run the Actor locally?

Clone the repo, run npm install, put your inputs in storage/key_value_stores/default/INPUT.json, then run npx apify run. Use dryRun: true to validate the setup without touching Drive or Payhawk.