# GeoPackage Handoff Report (`l3digital/geopackage-handoff-report`) Actor

Experimental small-file declared metadata handoff report for ArcGIS Online Content direct GeoPackage upload.

- **URL**: https://apify.com/l3digital/geopackage-handoff-report.md
- **Developed by:** [L3Digital](https://apify.com/l3digital) (community)
- **Categories:** Developer tools, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.05 / useful geopackage handoff report

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## GeoPackage Handoff Report

Identify which declared GeoPackage contents need a separate delivery method
before handing the file to an ArcGIS Online publisher. Supply one exported file
of at most **2 MiB (2,097,152 bytes)** as Base64. The structured report names tile
tables and views, distinguishes supported-in-principle from undocumented content,
and gives the owner specific questions to resolve before delivery.

This experimental metadata report supplies preparation questions, not a
guarantee of successful publication. Check the actual published result with the owner.

### Prepare an input

Start with the [public GeoPackage example](https://apify.com/l3digital/geopackage-handoff-report/examples/preview-geopackage-delivery-questions)
to inspect the synthetic input and report fields. The demo has no report-event
charge; it does not establish that your file will be accepted by a recipient.

Choose one of these JSON inputs. The synthetic example needs no file or permission
attestation:

```json
{"demo": true}
```

For your own file, encode a standalone, exported/checkpointed GeoPackage as
ordinary padded Base64 and provide:

```json
{
  "fileBase64": "REPLACE_WITH_CANONICAL_BASE64",
  "processingPermission": true
}
```

The placeholder is not runnable input. Replace it with the file's Base64 string.
The decoded file must be nonempty and at most **2 MiB (2,097,152 bytes)**; the
encoded string must be at most **2,796,204 characters**. Use ASCII Base64 without
whitespace, a data-URI prefix, URL-safe characters or noncanonical padding.
A standalone file cannot establish whether transactions in an external WAL file
are missing: export/checkpoint your source before encoding it.

`processingPermission: true` asserts that you may transfer and process this file
on Apify. It does not verify ownership or consent. `demo` defaults to `false` and
`processingPermission` defaults to `false`. Both must be JSON booleans.

The routes are exclusive. Productive input requires `fileBase64`, permission
`true`, and `demo` omitted or `false`. Demo input requires `demo: true`, no
`fileBase64` key (even `null` is refused), and permission omitted or `false`.
Unknown fields are refused. There is no URL, batch, SQL, credential or profile
input. The service does not fetch another file or forward yours to Esri.

### Understand the scope

The sole profile is **ArcGIS Online Content → New item → direct GeoPackage
upload**, based on [Esri's publish-features guidance](https://doc.arcgis.com/en/arcgis-online/manage-data/publish-features.htm)
checked October 2, 2026. ArcGIS Pro and Map Viewer publishing routes are outside
this profile.

| Declared contents | Report classification and next step |
| --- | --- |
| Registered nonspatial attributes table | `supported_in_principle`; inspect the actual recipient result. |
| Registered features with `POINT`, `MULTIPOINT`, `LINESTRING`, `MULTILINESTRING`, `POLYGON` or `MULTIPOLYGON`, with Z/M both zero | `supported_in_principle` for the declared family; inspect the actual result. |
| Tile table or user view | `documented_omission`; ask the owner to choose a separate delivery method. |
| Unregistered table, other content/geometry type, or declared Z/M dimensions | `undocumented`; confirm recipient handling with the owner. |

Tiles and views are documented examples of omissions, not an exhaustive exclusion
list. The report does not prescribe tile upload, conversion or view
materialization. View columns and geometry are not inspected; a view's `geometry`
is `null`. Extension registrations receive a count and an owner-review question
when present; their effects and recipient coverage remain unknown. No observed
registrations does not prove that no extensions exist.

Every completed report asks whether this route's documented publication in Web
Mercator fits the owner's purpose. Check its applicability to the actual outputs;
other transformations may occur.

Inspection reads bounded metadata declarations. It does not decode geometry,
validate the whole GeoPackage, convert it, certify it or predict acceptance.
Conventional RTree indexes are virtual tables and are refused by this prototype.
Historical `GP10`/`GP11` application IDs are unsupported. Malformed, ambiguous or
over-limit inspection shapes receive a safe noncompleted report.

### Read a report

The report uses `reportVersion`, `profile`, `status`, `reasonCode`, `scopeComplete`,
`example`, `useful`, `inputBytes`, `items`, `actions`, `extensionRegistrations`,
`limitations` and `retention`. `profile` identifies the dated route through `id`,
`checkedDate` and `sourceUrl`.

| Status | How to use it |
| --- | --- |
| `completed` | Scoped inspection finished. Read each item's classification and owner actions; completion still permits undocumented recipient coverage. |
| `refused` | Input or a known inspection gate prevented mapping. Check `reasonCode`; there are no item/action findings. |
| `incomplete` | Inspection could not finish reliably. Items/actions are empty so partial findings cannot become delivery advice. |
| `failed` | Setup, protection, billing, persistence or an internal failure prevented the promised result. Run failure may remain visible even if output storage fails. |

Only completion has `scopeComplete: true` and `reasonCode: null`. Productive
completion has `useful: true`; the demo has `example: true`, `useful: false`.
`useful` is an eligibility flag, not proof of customer value.

Items preserve exact table/view `name`, `objectKind`, `registered`,
`declaredContentType`, declared `geometry`, `classification` and `ruleCodes`.
Geometry declarations expose `column`, `type`, `srsId`, `z` and `m`.
Actions contain a fixed `code`, exact `subjects` and an `ownerQuestion`.
`choose_separate_delivery` names omitted content; `confirm_undocumented_content`
names unresolved content; `inspect_recipient_result` asks you to check supported
content after publication. Global questions have empty `subjects`.

Retrieve the report from the run's default dataset or the key-value store's
`OUTPUT` key. Both stores receive the same logical report when both writes
succeed. Inspect `status` and the owner questions before using the findings.

### Sample output

This complete synthetic example corresponds to `{"demo": true}`. The named
tiles and views need separate delivery; the attributes table still needs the
publisher to inspect the actual recipient result. It does not establish customer
use, recipient acceptance or a billable report.

```json
{
  "reportVersion": "1",
  "profile": {
    "id": "arcgis-online-content-new-item-direct-geopackage-2026-10-02",
    "checkedDate": "2026-10-02",
    "sourceUrl": "https://doc.arcgis.com/en/arcgis-online/manage-data/publish-features.htm"
  },
  "status": "completed",
  "reasonCode": null,
  "scopeComplete": true,
  "example": true,
  "useful": false,
  "inputBytes": 36864,
  "items": [
    {
      "name": "imagery",
      "objectKind": "table",
      "registered": true,
      "declaredContentType": "tiles",
      "geometry": null,
      "classification": "documented_omission",
      "ruleCodes": [
        "documented_tiles_omission"
      ]
    },
    {
      "name": "joined_features",
      "objectKind": "view",
      "registered": true,
      "declaredContentType": "features",
      "geometry": null,
      "classification": "documented_omission",
      "ruleCodes": [
        "documented_view_omission",
        "extension_coverage_undocumented",
        "view_columns_not_inspected"
      ]
    },
    {
      "name": "notes",
      "objectKind": "table",
      "registered": true,
      "declaredContentType": "attributes",
      "geometry": null,
      "classification": "supported_in_principle",
      "ruleCodes": [
        "supported_attributes"
      ]
    },
    {
      "name": "unlisted_view",
      "objectKind": "view",
      "registered": false,
      "declaredContentType": null,
      "geometry": null,
      "classification": "documented_omission",
      "ruleCodes": [
        "documented_view_omission",
        "unregistered_content",
        "view_columns_not_inspected"
      ]
    }
  ],
  "actions": [
    {
      "code": "review_declared_extensions",
      "subjects": [],
      "ownerQuestion": "Has the publisher confirmed recipient coverage of the declared extension registrations?"
    },
    {
      "code": "review_web_mercator_transformation",
      "subjects": [],
      "ownerQuestion": "Does this route's documented publication in Web Mercator fit the owner's purpose, after checking its applicability to actual outputs?"
    },
    {
      "code": "choose_separate_delivery",
      "subjects": [
        "imagery"
      ],
      "ownerQuestion": "Which separate delivery method will the publisher choose for this documented omitted content?"
    },
    {
      "code": "choose_separate_delivery",
      "subjects": [
        "joined_features"
      ],
      "ownerQuestion": "Which separate delivery method will the publisher choose for this documented omitted content?"
    },
    {
      "code": "inspect_recipient_result",
      "subjects": [
        "notes"
      ],
      "ownerQuestion": "Does the actual published result preserve this declared content for the owner's purpose?"
    },
    {
      "code": "choose_separate_delivery",
      "subjects": [
        "unlisted_view"
      ],
      "ownerQuestion": "Which separate delivery method will the publisher choose for this documented omitted content?"
    }
  ],
  "extensionRegistrations": 1,
  "limitations": [
    "metadata_declarations_only",
    "geometry_validity_not_checked",
    "recipient_acceptance_unverified",
    "exclusion_examples_nonexhaustive",
    "checkpointed_snapshot_required",
    "extension_coverage_undocumented"
  ],
  "retention": {
    "platformNotice": "Apify stores run input and output under platform and account retention controls; this Actor does not delete platform input, output, backups or histories.",
    "platformDeletionPerformed": false,
    "localTemporaryCleanup": "completed"
  }
}
```

### Pricing and privacy

The initial experimental price is **$0.05 per useful completed productive
report**. In pay-per-event runs, the Actor checks report-event capacity before
decoding a productive file and requests at most one `report-produced` event
after both output writes succeed. Refused, incomplete, failed and demo reports
do not request that event. Platform compute/storage costs may still apply,
including to demo runs.

Persistence failure never requests the report event. If charging is rejected or
its outcome is unknown after invocation, the run fails with a fixed billing
category; the already-persisted completed report stays unchanged. Retrieve the
existing result instead of automatically repeating the run. Separate invocations
are separate requests, and no cross-run settlement guarantee or automatic charge
retry is provided.

The Actor creates a private temporary decoded file and removes it after
processing; cleanup failure makes the result failed and nonbillable. Reports
intentionally reveal actual table/view names, geometry-column names and the
allowed declarations above. These identifiers can themselves be sensitive.
Reports omit feature values, coordinates, metadata payloads, SQL and raw errors.

Apify stores run input, including the Base64 file, and output under platform and
account retention controls. The Actor does not delete platform input, output,
backups or histories. `retention.platformDeletionPerformed` is `false`;
`localTemporaryCleanup` reports `not_required`, `completed` or `failed`.
Temporary cleanup is not a zero-retention or security guarantee. For files you
cannot transfer, use local inspection plus the recipient's guidance.

# Actor input Schema

## `fileBase64` (type: `string`):

Canonical standard Base64 only, no data URI/whitespace/URL. Omit entirely when demo is true.

## `demo` (type: `boolean`):

No fileBase64 or processing permission on this route. Always example=true/useful=false and no report event.

## `processingPermission` (type: `boolean`):

Must be true for your supplied file; confirms you may submit it for processing and platform retention. Must be absent/false for demo.

## Actor input object example

```json
{
  "demo": false,
  "processingPermission": false
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `report` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("l3digital/geopackage-handoff-report").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("l3digital/geopackage-handoff-report").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call l3digital/geopackage-handoff-report --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,l3digital/geopackage-handoff-report"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ivv8Yih7yo4Dggsw7/builds/DDBgxCZrpBJWa0UgY/openapi.json
