Authentication
Every request is authenticated with an API key that belongs to one integration in one workspace. There is no OAuth, no user login and no separate developer account. The key is the whole mechanism.
Where keys live
Section titled “Where keys live”Keys are created, shown and managed only inside the BytePhase app, under Settings → Integrations — for the workspace harbor-repair that is https://harbor-repair.bytephase.com/settings/integrations. This documentation site never shows, stores or asks for a key.
An integration gets exactly one key. It is created for you when you connect a provider, and it is shown once:
- on the Connect step of the setup wizard, with the notice “Copy this key now. You will not be able to see it again.”
- again after Rotate key, with the notice “Copy the new key now — it is shown only once. Update your plugin, webhook, or workflow with it.”
Everywhere else in the app the key is masked. If you lose it, rotate it — there is no other way to get a usable key back. Keys start with bp_. Only people who can open Settings → Integrations in your workspace can see one, and only at those two moments.
The setup wizard
Section titled “The setup wizard”Choosing a provider on Settings → Integrations opens a short wizard. The steps, in order:
-
What should happen when someone submits this form? — pick Lead (“Someone is only enquiring. Save them to follow up later.”) or Self check-in (“Someone checks in a device for repair. You can track it right away.”). IndiaMART and Justdial only send enquiries, so those always become leads.
-
Connect — the integration is created and the key is shown. What else appears depends on the provider:
Provider Shown on the Connect step WordPress API key, BytePhase API address and Store ID — “Paste this into the plugin’s … field” REST API, n8n API key and an Endpoint URL — “Send submissions to this URL with the X-API-Key header” Zapier API key, an Endpoint URL and an API base URL — “In Zapier, search for BytePhase, then connect your account using the API Key and API Base URL” Website, Typeform, JotForm, Tally.so API key and a Webhook URL — “Paste this URL into the provider’s webhook settings. It includes your key — copy it now.” Typeform, Tally.so additionally a Signing secret — “Paste this into the provider’s webhook secret field so we can verify each delivery” IndiaMART, Justdial A Webhook URL with the key as its last path segment, to paste into the marketplace’s panel The step then waits for a test submission from your form or tool so it can detect the field names.
-
Review field matches — “Left is what your form sends. Right is where it lands in BytePhase.” Required for providers that send their own field names (Typeform, JotForm, Tally.so, WordPress forms, your own website form). Skipped when your code already sends BytePhase’s field names.
-
If this customer already exists… — “We match by mobile number or email.” Choose Skip the submission or Create a new record.
-
You’re ready to go live — “Nothing goes live until you press Activate.” Until then, submissions are logged as Received and no records are created.
After activation the integration’s Activity screen lists every submission with its status — Successful, Duplicate, Received or Failed — and offers Send test and Rotate key.
Sending the key
Section titled “Sending the key”Send it in a header, on every request. Two forms are accepted:
Authorization: Bearer bp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX-API-Key: bp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxAuthorization: Bearer is what the examples on this site use. X-API-Key is what the Connect step tells you to use, and it exists for tools that cannot set an Authorization header (or sit behind a proxy that strips it). If both are present, X-API-Key wins.
curl "https://harbor-repair.api.bytephase.com/api/integrations/ping" \ -H "Authorization: Bearer bp_your_api_key" \ -H "Accept: application/json"{ "status": "connected", "workspace": "Harbor Repair Co.", "provider": "REST API"}When the key is in the URL
Section titled “When the key is in the URL”Form builders and marketplaces cannot add headers to a webhook. For those providers the Webhook URL shown on the Connect step already carries the key — as a token query parameter for Website, Typeform, JotForm and Tally.so, and as the last path segment for IndiaMART and Justdial — and the receiving endpoints accept it there. That is the only place a key belongs in a URL.
The provider type is a security choice, not a label
Section titled “The provider type is a security choice, not a label”The provider you pick when you connect — Zapier, n8n, WordPress, Website, REST API, Typeform, JotForm, Tally.so, IndiaMART, Justdial — is stored on the key as its provider type, and it controls what the key can reach.
| Provider type | What the key can do |
|---|---|
| Zapier | Create leads and self check-ins, and read recent customers, leads, repairs, payments, status changes and outsourced repairs, and search customers |
| n8n | Create leads and self check-ins |
| WordPress | Create leads and self check-ins |
| Website, REST API | Create leads and self check-ins |
| Typeform, JotForm, Tally.so | Create leads and self check-ins through the matching receiver |
| IndiaMART, Justdial | Create leads through the matching receiver only — the key is rejected by any other receiver |
Every key, whatever its type, can create leads and self check-ins. Only a Zapier-typed key can read data. That read access is right for Zapier, where you are deliberately handing your workspace’s activity to an automation platform, and wrong for anything that lives on a web server.
The type is also enforced per receiver: an IndiaMART key cannot post through the Justdial receiver and vice versa. A key used against an endpoint its type is not allowed on gets 403 integration_not_permitted.
What no key can do
Section titled “What no key can do”Regardless of type, a key can only ever create leads and self check-ins and, for Zapier keys, read the recent records listed above. It cannot touch invoices, inventory, settings, billing, employees or anything else in the workspace. This is a fixed ceiling, not a permission that can be granted.
Signing secrets
Section titled “Signing secrets”Two providers can sign each webhook delivery so that BytePhase can prove it came from them and not from someone who learned the URL:
| Provider | Signature header | Secret shown in BytePhase |
|---|---|---|
| Typeform | Typeform-Signature |
Yes — on the Connect step |
| Tally.so | Tally-Signature |
Yes — on the Connect step |
| JotForm, IndiaMART, Justdial, Website | none | No — the key (in the Webhook URL) is the only credential |
For Typeform and Tally.so the Connect step shows a Signing secret with the instruction “Paste this into the provider’s webhook secret field so we can verify each delivery.” Once a secret exists on the integration, every delivery must carry a valid signature — an HMAC-SHA256 of the raw body, base64-encoded, computed by the provider — or it is rejected with 401 invalid_signature. BytePhase does the verification; you implement nothing.
If you skip the secret, deliveries are accepted on the key alone. Do not skip it.
Rotation
Section titled “Rotation”Rotate key is on the integration’s Activity screen. Confirming it generates a new key and the app shows it once, with the notice to copy it now. The old key stops working immediately — there is no overlap period. Everything that used the old key fails with 401 credential_invalid until it has the new one:
| Where the key lives | What to update |
|---|---|
| WordPress plugin | BytePhase → Connection in wp-admin. Submissions made in the meantime are queued by the plugin and delivered once the new key is saved. |
| Zapier | Reconnect the BytePhase connection with the new key; every Zap on it errors until you do. |
| n8n | The Header Auth credential. |
| Typeform, JotForm, Tally.so, Website | The Webhook URL changes, because it contains the key — the app shows the new one (“Paste this new webhook URL into your provider — the old URL no longer works”). |
| IndiaMART, Justdial | The URL in the marketplace’s panel — for Justdial, through your account manager. |
| Your own code | Wherever you store the key. |
Rotate when a key may have leaked, when someone who knew it leaves, or when you have lost it. Plan a live rotation for a quiet moment, and have the new key pasted in within minutes.
Disconnect stops the integration’s key without deleting anything: “Its API key stops working and submissions will be rejected. The submission history is kept.” If an integration has been given an expiry date, its key is rejected after that date with credential_invalid.
When authentication fails
Section titled “When authentication fails”| Status | code |
Cause | Fix |
|---|---|---|---|
401 |
credential_missing |
No key arrived | Add the Authorization: Bearer bp_… header (or X-API-Key). If you are sure you sent it, something between you and BytePhase is stripping the Authorization header — switching to X-API-Key is a quick way to tell. |
401 |
credential_invalid |
The key is unknown, rotated, disconnected or expired — or it belongs to a different workspace than the URL points at | Check the base URL first (below), then use the key you copied from the Connect step or the rotate dialog. If you no longer have it, rotate. |
401 |
invalid_signature |
A Typeform or Tally.so delivery carried no signature, or one that did not match the signing secret | Paste the Signing secret from BytePhase into the provider’s webhook secret field, and make sure signing is turned on there. |
403 |
integration_not_permitted |
The key’s provider type is not allowed on this endpoint — for example a Website key on /api/zapier/… — or the key belongs to another provider’s receiver |
Use a key of the right type. Reads need a Zapier integration; each marketplace needs its own. |
412 |
— | The workspace could not be identified from the host you sent the request to | Fix the subdomain or domain. This happens before the key is even read. |
A rejected request is not written to the Activity screen — the key is checked before anything is logged — so a 401 in your own logs with nothing in BytePhase is expected. Every other response carries an X-Request-Id header; quote it to support. Full error format in Errors.
Base URL per environment
Section titled “Base URL per environment”A key only exists inside the workspace that issued it, and the workspace is identified by the host you send the request to — never by anything in the body. The workspace name is the subdomain you sign in with: signing in at harbor-repair.bytephase.com means the workspace is harbor-repair.
| Environment | Base URL |
|---|---|
| Production | https://{workspace}.api.bytephase.com/api |
| Staging (BytePhase’s own pre-release environment, not a customer sandbox) | https://{workspace}.api.bytephaserecovery.com/api |
| Local development (BytePhase engineers) | http://{workspace}.localhost:81/api |
| White-label custom domain | https://{custom_domain}/api |
A production key presented at a staging host, or at another workspace’s subdomain, fails with credential_invalid — the key simply is not there. A workspace on its own domain (white-label) does not use api.bytephase.com at all; its API is at that domain, for example https://repairs.example.com/api. The Endpoint URL, Webhook URL and API base URL shown on the Connect step are already correct for your workspace and environment, so copy them rather than typing them. More in Environments.
Business (branch) context
Section titled “Business (branch) context”A workspace can have more than one business — a branch or location. Intake requests accept an optional business_id; when it is absent the record goes to the workspace’s default business. An unknown id returns 404 business_not_found and an inactive one 403 business_not_active. See Concepts.

