Sign in Get started

Connectors

Import datasets from V7 (Darwin) and Roboflow into Pictograph. Annotations are converted to canonical Pictograph JSON automatically.

View as Markdown

Import remote datasets in two steps: validate the source API key → kick off the import. The import runs as an async job; the SDK polls until terminal status by default.

Every example below shows the Python SDK call and the equivalent raw REST request. The REST examples authenticate with an X-API-Key header; set PICTOGRAPH_API_KEY in your shell to copy-and-run them. The source provider’s key (V7 token / Roboflow key) is a separate value sent in the request body — it is used only for the call that needs it and never persisted.

from pictograph import Client
client = Client()  # reads PICTOGRAPH_API_KEY

Supported providers

providerSourceNotes
v7V7 DarwinPolygon paths, bboxes, polylines, keypoints, tags
roboflowRoboflowCOCO export → Pictograph JSON

validate

Verify the source API key and list available remote datasets. No quota consumed; the source API key is sent only on this call.

ArgTypeDefaultNotes
providerConnectorProviderrequired"v7" / "roboflow"
api_keystrrequiredThe source provider’s API key
result = client.connectors.validate(
    provider="v7",
    api_key="v7_api_token_…",
)
if result.valid:
    for ds in result.datasets:
        print(ds.id, ds.name, ds.image_count)
else:
    print("invalid:", result.error)
curl -s -X POST "https://api.pictograph.io/api/v1/developer/connectors/validate" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"provider": "v7", "api_key": "v7_api_token_…"}'

Returns ValidationResult — inspect .valid first; .datasets is populated only on success.

check_limits

Pre-flight tier-cap check before kicking off an import.

ArgTypeDefaultNotes
total_imagesintrequiredImages about to be imported
estimated_size_bytesintrequiredEstimated total import size, in bytes
check = client.connectors.check_limits(
    total_images=12500,
    estimated_size_bytes=4_000_000_000,   # 4 GB
)
if not check.allowed:
    print("blocked by:", check.exceeded)   # "images" / "storage" / "both"
curl -s -X POST "https://api.pictograph.io/api/v1/developer/connectors/check-limits" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"total_images": 12500, "estimated_size_bytes": 4000000000}'

Returns LimitCheckResult.

import_

Kick off the import. The trailing underscore avoids shadowing the Python import keyword. The REST endpoint returns an import_id immediately; the SDK then polls until terminal status when wait=True.

ArgTypeDefaultNotes
providerConnectorProviderrequired"v7" / "roboflow"
api_keystrrequiredSent only to fetch source data
datasetsSequence[RemoteDataset | dict]requiredRemoteDataset instances or raw dicts
waitboolTruePoll until terminal
poll_intervalfloat3.0seconds
timeoutfloat3600.0Max poll seconds (V7 large exports take 30+ min)
job = client.connectors.import_(
    provider="v7",
    api_key="v7_api_token_…",
    datasets=[
        {"id": "ds_abc", "name": "Road signs", "slug": "road-signs"},
        # OR pass RemoteDataset instances from validate():
        # *result.datasets[:2],
    ],
    wait=True,
    poll_interval=3.0,
    timeout=3600.0,                    # 1h default
)
print(job.import_id, job.status)
for ds in job.datasets:
    print(ds.name, ds.imported, "/", job.total_images)
curl -s -X POST "https://api.pictograph.io/api/v1/developer/connectors/import/start" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "v7",
    "api_key": "v7_api_token_…",
    "datasets": [
      {"id": "ds_abc", "name": "Road signs", "slug": "road-signs"}
    ]
  }'

Returns ImportJob. The raw REST response carries import_id plus the created project list; poll the status endpoint below for progress.

get_import

Fetch the current state of an import job.

job = client.connectors.get_import(import_id)
print(job.status, job.progress, job.imported_images)
curl -s "https://api.pictograph.io/api/v1/developer/connectors/import/status/{import_id}" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY"

Returns ImportJob. Status transitions processing → completed (or error / cancelled).

wait_for_import

Poll an import until it reaches a terminal status (SDK convenience over get_import; uses the same status endpoint).

job = client.connectors.wait_for_import(import_id, timeout=600.0)
# Poll the status endpoint until status is completed / error / cancelled.
curl -s "https://api.pictograph.io/api/v1/developer/connectors/import/status/{import_id}" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY"

cancel_import

Soft-cancel an in-flight import. Already-imported images are kept; the worker stops downloading new ones and the status transitions to cancelled.

job = client.connectors.cancel_import(import_id)
curl -s -X POST "https://api.pictograph.io/api/v1/developer/connectors/import/cancel/{import_id}" \
  -H "X-API-Key: $PICTOGRAPH_API_KEY"

Returns ImportJob.

CLI equivalents:

pictograph connectors validate v7 --key v7_api_token_…
pictograph connectors check-limits --images 12500 --bytes 4000000000
pictograph connectors import v7 --key v7_api_token_… --dataset ds_abc
pictograph connectors status <import_id>
pictograph connectors cancel <import_id>

Annotation conversion

V7 / COCOPictograph
V7 polygon.pathspolygon.paths (passthrough)
V7 bounding_box (no polygon)bounding_box
V7 line.pathpolyline.path
V7 keypointkeypoint
V7 tag / ellipse / maskskipped (no Pictograph equivalent)
COCO segmentation (flat array)polygon.paths (paired into points)
COCO bbox (no segmentation)bounding_box
COCO keypoints tripletskeypoint (skips v=0)

Tier caps

Imports are charged against your storage + image-count tier caps. See Credits and your plan in the web app.

Common errors

StatusExceptionCause
401AuthErrorSource provider API key rejected
402PaymentRequiredErrorTier cap exceeded
403ForbiddenErrorimport / cancel require member+ role
404NotFoundErrorimport_id missing
408PollTimeoutErrorwait=True exceeded timeout (job keeps running)
422ValidationErrorInvalid provider, empty datasets list
Copied to clipboard