Export inspection PDFs

Generate an inspection PDF with shared export options, using either GET or POST.

Generate an inspection PDF with one export request by calling either GET /v3/inspections/{inspectionId}/export or POST /v3/inspections/{inspectionId}/export.

Before you start

  1. Get the inspection ID for the inspection you want to export.
  2. Set your Vision API base URL, such as https://vision-api.truepic.com/v3.
  3. Send requests with your Bearer token.
  4. Choose the request style that matches your integration:
    • Use GET for the shortest request when you are testing or exporting a PDF with query parameters.
    • Use POST when you need to send more export options in a JSON request body.
    • Use synchronous export when your application needs the generated PDF in the response.
    • Use async export when your application can process the completed PDF through polling or webhooks.

1. Choose GET or POST

MethodBest forHow options are sentDefault response
GETQuick tests and smaller exportsQuery parameters200 OK with the PDF, unless queued
POSTExports with several options or nested filter dataJSON request body200 OK with the PDF, unless queued

Synchronous export returns the generated PDF in the response. Async export queues the work and returns an operation that you can poll or track through webhooks. Synchronous requests time out after 2 minutes.

👍

Use async=1 with GET or "async": true with POST when your application can process the PDF after the export request completes.

2. Configure the PDF export

Both export endpoints support the same export options. With GET, pass them as query parameters. With POST, pass the same fields in the JSON request body.

OptionTypeDefaultDetails
asyncbooleanfalse or omittedOptional. Queues the export instead of returning the PDF inline. For GET, set async=1 to queue the export. For POST, send "async": true to queue the export. If you omit it or send 0/false, the API returns the PDF synchronously.
filterobjectinclude all photos and videosLimits which photos or videos are included. Use filter.photos as an array of integer photo or video IDs.
includearray of stringsnoneAdds sections that are not included by default. Allowed value: inspectionNotes. The legacy alias inspectionNote is also accepted for existing integrations.
excludearray of stringsnoneRemoves sections that are included by default. Common values: inspectionItems, imageDetails, timeline, captureLocation, aiAnalysis, and captureDevices. Other accepted values are cover, contents, and inspectionNotes. Legacy values questions and thumbnails are also accepted; questions maps to inspectionItems, and thumbnails does not remove an active section.
captureLocationMapsarray of stringsoutside, within, and no_locationControls which per-capture location maps appear in Image Details. Allowed values are outside, within, and no_location. Send an empty array ([]) to suppress all per-capture location maps.
showUnansweredItemsbooleantrueControls whether unanswered questions and captures with no upload appear in the Inspection Items section. Set this to false for a submitted-only report.
tzstringUTCSets the IANA time zone used for dates and times in the PDF, such as America/New_York.

For array options:

  • With GET, pass include[], exclude[], and captureLocationMaps[] as query parameters.
  • With POST, send include, exclude, and captureLocationMaps as JSON arrays.
  • If you need to send several array values or nested filter data, prefer POST so you do not run into URL length limits.

Here is an example POST body that uses the shared export options:

{
  "async": true,
  "filter": {
    "photos": [123, 456]
  },
  "include": ["inspectionNotes"],
  "exclude": ["timeline", "captureDevices"],
  "captureLocationMaps": ["outside", "within"],
  "showUnansweredItems": false,
  "tz": "America/New_York"
}

Optional: Queue the export asynchronously

Use async export when your integration can process the completed PDF after the export request returns. Async export returns an Operation (an object that tracks background work) that you can poll or associate with webhook events.

Use this option when you do not need the PDF in the initial response. Synchronous requests time out after 2 minutes.

With POST, queue the export by setting async to true in the JSON request body:

curl --request POST \
  --url 'https://vision-api.truepic.com/v3/inspections/{inspectionId}/export' \
  --header 'Authorization: Bearer YOUR_API_TOKEN' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{
    "async": true,
    "filter": {
      "photos": [123, 456]
    },
    "include": ["inspectionNotes"],
    "exclude": ["timeline", "captureDevices"],
    "captureLocationMaps": ["outside", "within"],
    "showUnansweredItems": false,
    "tz": "America/New_York"
  }'

What success looks like

  • 202 Accepted
  • The export job is queued instead of completed inline
  • The response body is a standard ResponseData envelope with the operation under result

Save result.id from the 202 response. This is the operation ID you use to poll the operation status or match the completed export to an ACTION_PDF_READY webhook.

{
  "response_code": 202,
  "message": "Success",
  "api_version": "3.88.0",
  "result": {
    "id": 907643,
    "type": "events.export_pdf",
    "status": "WAITING",
    "resource_type": "Event",
    "resource_id": 2840082,
    "result": null,
    "created_at": "2026-09-16T13:55:58.584Z",
    "updated_at": "2026-09-16T13:55:58.584Z",
    "completed_at": null
  }
}

You can also queue an async export with GET by setting async=1 in the query string:

curl --request GET \
  --url 'https://vision-api.truepic.com/v3/inspections/{inspectionId}/export?async=1' \
  --header 'Authorization: Bearer YOUR_API_TOKEN' \
  --header 'Accept: application/json'

Optional: Export synchronously

Use synchronous export when your application needs the PDF returned directly in the response. The request must finish within 2 minutes.

Use async export instead when your workflow can process the completed PDF later through polling or webhooks.

curl --request GET \
  --url 'https://vision-api.truepic.com/v3/inspections/{inspectionId}/export' \
  --header 'Authorization: Bearer YOUR_API_TOKEN' \
  --header 'Accept: application/pdf' \
  --output inspection-{inspectionId}.pdf

If you want to queue the GET request instead of returning the PDF inline, add async=1 to the query string and expect an Operation response instead of a PDF.

What success looks like

  • 200 OK when the export runs synchronously
  • 202 Accepted when you set async=1
  • The response body is either the generated PDF (200) or a standard ResponseData envelope with the operation under result (202)

Optional: Poll the operation until it finishes

After an async export request returns an operation ID, poll GET /v3/operations/{operationId} to track progress. This applies whether you started the export with POST and "async": true or with GET and async=1.

curl --request GET \
  --url 'https://vision-api.truepic.com/v3/operations/{operationId}' \
  --header 'Authorization: Bearer YOUR_API_TOKEN' \
  --header 'Accept: application/json'

When the export completes, the operation has status set to SUCCESS. Download the PDF from result.result.url in this operation response:

{
  "response_code": 200,
  "message": "Success",
  "api_version": "3.88.0",
  "result": {
    "id": 907643,
    "type": "events.export_pdf",
    "status": "SUCCESS",
    "resource_type": "Event",
    "resource_id": 2840082,
    "result": {
      "url": "https://pdfs.truepic.com/pdfs/inspection-2840082-57734dd1ba57e875.pdf?...",
      "size": 843237
    },
    "created_at": "2026-09-16T13:55:58.584Z",
    "updated_at": "2026-09-16T13:56:30.204Z",
    "completed_at": "2026-09-16T13:56:30.202Z"
  }
}

The returned URL is a signed download URL. Use it to download the generated PDF; do not make another request to the export endpoint.

Repeat that request until the operation indicates it has completed or failed. In most integrations, polling every few seconds is enough.

Polling flow

  1. Send POST /v3/inspections/{inspectionId}/export with "async": true, or send GET /v3/inspections/{inspectionId}/export?async=1.
  2. Read the returned operation ID from the 202 Accepted response.
  3. Call GET /v3/operations/{operationId} on a short interval.
  4. Stop polling when the operation shows completion or failure.
  5. If the operation succeeds, download the finished PDF from operation.result.url in the completed operation response.
  6. If the operation fails, log the failure and retry or surface the error to your team.

If an export reaches the 2-minute synchronous request limit, retry it with async export. Then poll the operation or wait for the webhook and download the PDF from the URL returned by the completed operation.

Optional: Use webhooks instead of polling

If your integration already receives webhooks, you can track PDF generation through webhook events instead of relying only on polling:

  • ACTION_PDF_READY
  • ACTION_PDF_FAILED

Use polling when you need an immediate request-response workflow. Use webhooks when you want your system to react after the export finishes without repeatedly calling the operations endpoint.

When you receive ACTION_PDF_READY, the PDF is ready to download. Download the completed PDF from operation.result.url in the webhook payload. The top-level webhook result contains the inspection details; operation.result.url is the download link to use.

{
  "action": "ACTION_PDF_READY",
  "result": {
    // Full inspection details
  },
  "operation": {
    "id": 907643,
    "type": "events.export_pdf",
    "status": "SUCCESS",
    "resource_type": "Event",
    "resource_id": 2840082,
    "result": {
      "url": "https://pdfs.truepic.com/pdfs/inspection-2840082-57734dd1ba57e875.pdf?...",
      "size": 843237
    },
    "created_at": "2026-09-16T13:55:58.584Z",
    "updated_at": "2026-09-16T13:56:30.204Z",
    "completed_at": "2026-09-16T13:56:30.202Z"
  }
}

Use operation.result.url directly. Do not look for pdf.download_url, export_id, or another generated download field in this webhook payload.

⚠️

After you receive ACTION_PDF_READY, do not call GET /v3/inspections/{inspectionId}/export to download the file. Calling the export endpoint again starts a new PDF generation request. Use the URL returned in operation.result.url instead.

Troubleshooting

The export request times out

The synchronous request reached its 2-minute limit. Retry the export asynchronously with POST /v3/inspections/{inspectionId}/export and "async": true, or use GET /v3/inspections/{inspectionId}/export?async=1. Then poll the returned operation or wait for an ACTION_PDF_READY webhook.

The export request returns 202 Accepted

That means the export was queued successfully. Read the operation ID from result in the response and poll GET /v3/operations/{operationId} until it completes, or wait for an ACTION_PDF_READY webhook event.

The client receives ACTION_PDF_READY, but the next PDF request is still slow

After ACTION_PDF_READY, download the PDF from operation.result.url in the webhook payload. Do not call GET /v3/inspections/{inspectionId}/export again to fetch the file, because that starts a new PDF generation request.

The API returns 400

Check the request body or query parameters. This usually means the export options could not be parsed. For GET, verify your query parameters, especially array values and nested filter data. For POST, verify the JSON body shape.

The API returns 401 or 403

Verify the Bearer token and make sure the calling client has permission to access that inspection.

The API returns 404

Confirm that the inspection ID or operation ID exists and belongs to the right environment.

The API returns 412

Check for a missing required parameter or property.

API reference



Did this page help you?