Skip to main content
Instance import accepts an export package and restores keywords plus optional rank history into the project associated with a migration token. Use the single request endpoint for small packages and the session protocol for large packages. These versioned paths are included in /api/v1/openapi.json.

Endpoints

Authentication

Instance import uses a migration token, not a bsb_key_live_... API key. Every import endpoint requires Bearer authentication:
Invalid, expired, or already-used tokens return 419 with an unauthorized problem response. Missing or malformed tokens return 401. All import request objects reject unknown fields. Public IDs and checksums must use their exact lowercase representation without surrounding whitespace. Numbers and booleans must use native JSON types rather than strings.

Migration Tokens

A migration token is bound to one project by design: it authorizes importing into exactly the project it was minted for, is single use, and expires after BISIBILITY_MIGRATION_TOKEN_TTL_MINUTES. This is what lets the exporting side push data into a destination project without ever holding that project’s API key. There is no instance-global token; a broader credential would grant more than an import needs. Tokens are minted and managed through the ordinary project-scoped REST API using an Authorization: Bearer <api_key> key for the destination project: The raw mig_... value is returned only when minted. Tokens can also be minted from the in-app wizard. Migration-token identifiers are strict ferry_ v3 public IDs; import jobs and session identifiers are strict imp_ v3 public IDs.

Compatibility Preflight

Call the public compatibility endpoint before generating an export:
Response:
The endpoint is anonymous and rate limited. latest_migration is null when the migration table cannot be read.

Single Request Import

Post the export package directly to /api/v1/cloud/import:
The endpoint accepts strict v7 packages and compatible v6 packages. Version 7 exports identify every keyword location with location_key; the human-readable location label can name a country, region, or city. Version 6 continues to use the legacy country label. All versions accept only snake-case package fields, exact lowercase public IDs, and native JSON number and boolean types. They reject wrapper objects, body tokens, and unknown fields. A version 5 package is accepted only when every rankingHistory array is empty; update and re-export any version 5 package that carries ranking history. Top-level fields: Keyword fields: Each competitor record requires its source cmp_ public ID and canonical domain. The destination still matches and upserts competitors by domain. History fields: Only successfully completed source checks are exported as ranking history. Failed, running, and deferred attempts are not ranking observations and are not included. Imported rows preserve their provider, depth, and normalization version. Visibility measures volume-weighted ranking strength in Google’s Top 20. 100 means every measured keyword ranks #1. Rankings below #20 do not add Visibility. Shallow or failed checks are not treated as lost rankings. Top 10 checks do not update Visibility. Affected keywords still count toward its coverage total.
Export requestedDepth whenever the source instance has it. A null value remains valid when the source did not store a depth, and the completed import reports those rows as history_unknown_depth.
Version 5 history does not distinguish failed attempts from successful no-match observations. bisibility rejects it rather than importing ambiguous ranking data. Update the source instance and create a version 7 export.
Success returns 201.
Every v7 package includes every section, including empty arrays:

Chunked session import

Use sessions when the package is large enough that one request may exceed body limits or timeout. A session has three phases: create, upload chunks, finalize.

1. Create the Session

New exporters send version 7; a destination also accepts version 6 session manifests. chunk_count must be between 1 and 500. source_project_id is required and prevents importing a project into itself. totals is optional and is stored with the session manifest. Success returns 201.
Only one live receiving or importing session is allowed per token. A second live session returns 409.

2. Upload Chunks

Upload each chunk by zero-based index:
Keyword chunks carry keyword rows:
Section chunks carry non-keyword package sections and optional source keyword ids used to map imported alert targets:
The checksum is the v7 canonical chunk-content identity for idempotent retries. Retrying the same {sessionId, index} with the same checksum returns 200; retrying that index with a different checksum returns 409. Clients should compute the sha256: value over the canonical JSON body { version: 7, ...chunk }, excluding the checksum field, before gzip compression. To gzip a chunk, send the gzip-compressed JSON body with:
The body limit applies before and after decompression. Oversized chunks return 413. Success returns:

3. Finalize

Finalize after every chunk has been accepted:
The body may be empty or {}. If chunks are missing, finalize returns 409. If another finalize is already importing the session, it returns 409. Once the session is done, a repeated finalize call returns the completed job response.

Crash Resume

Persist session_id, chunk_count, and every chunk checksum on the client. After a client crash, re-upload all chunks whose success was not recorded. The server accepts already stored chunks when the checksum matches. If the connection drops during finalize, call finalize again. A 200 means the session completed. A 409 means chunks are still missing or a finalize is still running. Stale receiving and importing jobs are marked failed by maintenance after 30 minutes, after which a new migration token and session are required.

Status Codes

Environment Knobs

Existing App Surfaces

The app also implements instance-import state with server actions:

In-App Wizard

Open /cloud/import, generate or paste a migration token, then upload the JSON package from the wizard. The wizard uses the same import handlers as the REST endpoints.