BytewellsDocs

Preview documentation. Bytewells is in private beta. These pages are incomplete and will change often. Do not use them for production integrations.

Apify API compatibility

Known differences from the Apify API.

Bytewells aims to mirror Apify's wire format for the endpoints that external clients (notably apify-client SDK consumers) call directly. This doc tracks every known divergence with one of three statuses:

  • DONE — gap closed; clients see the same shape Apify provides.
  • TODO — gap known and accepted; will be closed in a future release.
  • WONTFIX — Bytewells explicitly diverges; document why.

Run dispatch (POST /v2/acts/:actorId/runs)

GapStatusNotes
webhooks field accepted in bodyDONE (next release)Per-run webhooks via webhooks.run_id column. See packages/api/src/db/migrate.ts (run_id ALTER) and packages/runner/src/queue.ts triggerWebhooks (match-query union with run_id IS NULL OR run_id = $3).
headersTemplate field on per-run webhooksDONE (next release)JSON-string parsed at INSERT, stored in webhooks.headers JSONB. Stringified before INSERT to match the existing admin webhook code path (routes/webhooks.ts POST handler).
build field for build pinningTODOCurrently always uses latest SUCCEEDED build. Most clients use 'latest' so non-blocking; pin support requires actor_versions.build_tag lookup.
metadata / userData fieldWONTFIXUse envVars (per-run, container env) or per-run webhooks instead.
username~actor-name addressingDONEStore Actors can be addressed Apify-style; ids and your own Actor names work too.
402 on missing rental or creditsWONTFIXBytewells returns 402 with error type rental-required (and data.listingSlug) or insufficient-credits before a run is created. Apify's own errors for these cases differ; clients should surface the message.

Webhook delivery

GapStatusNotes
resource.usageTotalUsd fieldTODOCurrently always 0 in webhook payloads. Runs now carry usage_micro_usd after settlement, so the field can be filled from it. Mirrored across packages/runner/src/queue.ts defaultPayload.resource and packages/api/src/routes/webhooks.ts buildWebhookPayload (KEEP IN SYNC pair).
ACTOR.RUN.TIMED_OUT event typeDONE (next release)Apify uses HYPHEN for run.status ('TIMED-OUT') but UNDERSCORE for event type ('ACTOR.RUN.TIMED_OUT'). Bytewells matches both: status stays hyphen-form (Apify-canonical), event-type construction translates via status.replace(/-/g, '_') in packages/runner/src/queue.ts (triggerWebhooks).
Apify-compatible payload-template engineDONE (v0.9.1)Dot-notation, quoted/unquoted forms, mid-string interpolation, fallback-on-error. See packages/api/src/webhooks/apply-template.ts and the mirrored packages/runner/src/webhook-template.ts.
Per-run webhooks (webhooks field on run create)DONE (next release)See above.
Runtime templating of headersTemplate ({:vars})TODOCurrently only payloadTemplate runs through engine. Per-run headers are JSON.parsed at INSERT-time and delivered statically. Non-blocking for known clients; full templating engine application is the right long-term parity.
ACTOR.RUN.CREATED + ACTOR.RUN.RESURRECTED eventsTODOBytewells only fires the four terminal events (SUCCEEDED, FAILED, TIMED_OUT, ABORTED). The Zod enum in packages/api/src/schemas/webhooks.ts (SUPPORTED_WEBHOOK_EVENTS) rejects subscriptions to the two missing events with a 400 — louder than accepting rows that silently never deliver. Closing the gap = fire CREATED at run-insert (best-effort, off the critical path) in packages/api/src/routes/actors.ts, and fire RESURRECTED in packages/api/src/routes/runs.ts (the POST /v2/actor-runs/:runId/resurrect handler).
HMAC webhook signature headerTODOSecurity hardening for follow-up. Bearer auth on the receiver side is sufficient short-term.

Auth

GapStatusNotes
Token-in-query (?token= for read endpoints)DONE (v0.7)packages/api/src/auth/middleware.ts (authenticate) accepts ?token= for any authenticated route.
API keys with cp_ prefixDONEpackages/api/src/auth/index.ts (API_KEY_PREFIX).
JWT tokens with 7-day TTLDONEpackages/api/src/auth/index.ts (JWT_EXPIRES_IN).
Run-scoped APIFY_TOKEN inside ActorsWONTFIXActors get rt_<runId>.<hmac> instead of the user's API key (packages/api/src/auth/run-token.ts). It only works on the endpoints an Actor needs while its run is active; anything else is 403.

Dataset / KV / runs read APIs

GapStatusNotes
GET /v2/datasets/:id/items shapeDONEReturns array; paginates via x-apify-pagination-* response headers.
?clean=true&format=json query paramsDONE (no-op)The items endpoint already returns clean JSON; flags accepted but ignored by Fastify (loose querystring handling).
POST /v2/actor-runs/:id/rerunN/A (extension)Not an Apify endpoint — a platform extension (since 1.7.0). Clones a terminal run into a NEW run (fresh id/storages, copied INPUT + per-run webhooks + envVars, originRunId lineage). Exists because resurrect reuses the run id, which webhook consumers with per-run-id idempotency treat as a duplicate and drop. apify-client won't call it; the dashboard and custom tooling do.

Client SDK compat

GapStatusNotes
apify-client SDK pointed via baseUrlPARTIALRun-trigger + dataset items verified end-to-end. Other SDK methods (storage CRUD, build operations) not exhaustively tested.

How to add a row

When integrating a new client and discovering a new gap:

  1. Add a row to the relevant section above with status TODO.
  2. If you fix it in the same PR, set status to DONE and reference the changing files.
  3. If the divergence is intentional, set status to WONTFIX and document the reason.

This doc is the canonical bookkeeping for cross-platform compat — keep it in sync with implementation as gaps are closed.

On this page