Skip to main content

Authentication

All public Phonefarm endpoints currently use one shared bearer secret.

Request Authentication

Send:
Authorization: Bearer <shared secret>
In the current implementation, this shared secret is configured as INGEST_SECRET in the runtime environment, even for non-ingest APIs. For docs and integrations, treat it as one shared public API bearer secret.

Authenticated Endpoints

  • POST /capability-requests/enqueue
  • POST /maintenance/requests
  • GET /processes/{process_id}
  • POST /processes/{process_id}/cancel
  • POST /ingest
  • POST /cancel
  • POST /runtime-snapshots/upsert

Example

curl "$PHONEFARM_BASE_URL/processes/$PROCESS_ID" \
  -H "Authorization: Bearer $PHONEFARM_API_KEY"

Callback Signing

If PHONE_FARM_WEBHOOK_SECRET is configured, Phonefarm signs outbound callbacks with:
  • X-PhoneFarm-Timestamp
  • X-PhoneFarm-Signature
Signature input:
${timestamp}.${rawJsonBody}
Signature algorithm:
HMAC-SHA256

Example Verification

import crypto from "node:crypto";

function verifyPhonefarmSignature({ timestamp, rawBody, signature, secret }) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${timestamp}.${rawBody}`)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(expected, "utf8"),
    Buffer.from(signature, "utf8"),
  );
}

Failure Behavior

  • Missing auth header returns 401.
  • Invalid bearer token returns 401.
  • Missing server-side secret configuration returns 500.