# AroFlo connector

Source: /docs/connectors/aroflo.md

Use this as an implementation starting point: adapt the worked example to the requested dataset and the source documentation. See [Custom API](/docs/connectors/custom-api) for the shared SDK pattern and document-upload workflow.

## What this connector is for [#what-this-connector-is-for]

Field service jobs, work orders, schedules, asset records, and invoicing.

Use this guide to choose the resources and row meanings for a Vortexify source integration. Connection ownership belongs to a connector; each dataset gets its own sync, configuration, and extraction behavior.

## Data and tables you can pull [#data-and-tables-you-can-pull]

The following table families are a starting point for source selection. They describe possible datasets to implement using the [vendor reference](https://docs.api.aroflo.com/), not a guarantee that the example implements every table. Actual availability depends on the product edition, deployment, account permissions, and API/schema version.

| Suggested table | One row represents |
| --- | --- |
| `clients` | a client |
| `tasks` | a task |
| `assets` | a asset |
| `timesheets` | a timesheet |
| `purchase_orders` | a purchase order |
| `invoices` | a invoice |

### Relationships and extraction considerations [#relationships-and-extraction-considerations]

These are proposed dataset names, not a universal schema guaranteed by the vendor. Preserve source object IDs and relationship references, and split nested child collections into separate tables when appropriate. Choose the concrete endpoint/report and row meaning from the vendor reference before implementing a sync.

## Connecting to AroFlo [#connecting-to-aroflo]

Use the API enabled for the customer and follow its current authentication/signing requirements. Confirm whether using the legacy API or newer developer API; request and response formats differ.

For HTTP reads, configure the connector client with the concrete API origin and source-authorized headers or authentication object. Actual credentials belong in platform secret configuration, not in this document or committed source.

### requirements.in [#requirementsin]

Declare these packages in the resource's `requirements.in`. Use the published `vortexify` package for the SDK and the source-specific driver/client shown below. Choose compatible dependency versions for your runtime; the [connector and sync reference](/docs/reference/python/connectors-and-syncs) explains where each file belongs.

```text
vortexify==0.1.1
pandas>=2,<3
httpx
```

This HTTP starting point needs no native database driver. Add the source-specific SDK, signer, or XML parser if the selected interface requires it.

## Worked example: adapt the documented read/query operation [#worked-example-adapt-the-documented-readquery-operation]

This request recipe is for an agent to fill from the selected product/deployment reference. The resource path, request body, and record-array path remain explicit inputs because the source interface or account contract determines them. It executes one documented JSON read and shapes its records; it does not assert a universal endpoint or schema for this source.

`request_spec` uses HTTPX request arguments, for example `method`, `url`, `params`, and `json`. Select a read/query operation even when its HTTP method is POST. `rows_path` is the actual sequence of JSON object keys leading to its records array (an empty list selects a root array). For XML/SOAP or asynchronous exports, adapt the transport/decoder first using the source-specific notes below.

### Source read [#source-read]

```python
import pandas as pd


def read_documented_page(client, request_spec: dict, rows_path: list[str]):
    # Fill request_spec from a documented READ operation for this deployment.
    # It contains method, url, and optional params/json/content/headers.
    method = request_spec["method"].upper()
    if method not in {"GET", "POST"}:
        raise ValueError("Select the documented read/query operation")
    response = client.request(**request_spec)
    response.raise_for_status()
    payload = response.json()
    if isinstance(payload, dict) and (
        payload.get("errors") or payload.get("success") is False
    ):
        raise ValueError("Source returned an application error")
    rows = payload
    for key in rows_path:
        rows = rows[key]
    if not isinstance(rows, list) or any(not isinstance(row, dict) for row in rows):
        raise ValueError("rows_path must select the documented record array")
    return pd.json_normalize(rows)
```

### What to adapt [#what-to-adapt]

Identify the current developer API versus legacy interface, then copy the documented read zone/operation and request-signing rules. Signing must use the exact outgoing request. Choose the matching JSON or XML response decoder rather than assuming bearer-auth JSON lists.

Use the [custom API SDK starting point](/docs/connectors/custom-api#worked-example-cursor-paginated-json-records) to connect the read operation to `Connector` and `Sync`. For a source with its own driver, retain that client in `Connector.client()` and replace the HTTP request with the driver read. An `extract(*, avg_row_size_bytes=None)` implementation yields bounded DataFrames. An independent `preview()` uses a fresh connector and a small read; it must not call extraction or advance real state.

Choose explicit output columns and stable IDs for the requested table. The examples use `json_normalize` where useful to illustrate row shaping; nested arrays still need deliberate child tables and a stable declared output schema. A first-page sample is useful for development, while a full sync must follow all relevant continuation/parent-resource paths. Design incremental watermarks, update/deletion behavior, and rate-limit handling for the actual source before enabling incremental mode.

The purpose is to give a coding agent a concrete pattern to adapt, including for similar sources. These snippets are examples rather than a claim of complete vendor coverage. Check the [source operation reference](https://docs.api.aroflo.com/) and representative responses before running with a customer's account; live vendor execution has not been verified here.

## Sources and further reading [#sources-and-further-reading]

- [Vendor connection and resource reference](https://docs.api.aroflo.com/) — The interface/access prerequisites underlying this connection path; follow the selected resource's documentation for fields, queries, and pagination.
- [Vortexify connectors and syncs](/docs/reference/python/connectors-and-syncs) — Connector ownership, schemas, preview isolation, extraction, and checkpoint contracts.
- [Vortexify CLI workflow](/docs/reference/cli/overview) — Registering resources, committing source, and providing credential configuration.
