docs
/
AI skills

Send records to another business

Copy or move whole collections, a filtered part of one, or picked rows from this business into another Appmint business. The other business reviews the request and accepts or declines it. Covers checking the business ID, sending the request, accepting it on the other side, following progress, reading what failed and why, withdrawing a request, and what a transferred record keeps.

A transfer goes from one Appmint business to another. It is a request: the sending business names what goes and where, and nothing moves until the receiving business accepts it. On accept, the engine copies the records in the background, 200 at a time. It writes progress and the result onto the request, and emails both sides when it ends. The API is appengine org-management/transfer/requests (src/org-management/org-transfer.service.ts).

sender: request (pending) ──notice + email──→ receiver: review
                                                ├─ Decline (with a reason) → rejected
                                                └─ Accept → running → completed / partial / failed
sender: Withdraw while pending → cancelled        (pending for 7 days, then expired)
StateMeans
pendingSent, waiting for the receiving business.
runningAccepted, being copied. Accepting goes straight here.
completedEvery record arrived.
partialSome arrived, some failed. The request lists why.
failedNone arrived, or the job stopped (error).
rejectedDeclined by the receiving business, with its reason.
cancelledWithdrawn by the sender while pending.
expiredNobody answered within 7 days. Expiry shows the next time the request is read.

Copy or move. A copy leaves the originals where they are. A move deletes each original once its copy has landed; the originals go to the sender's trash (Restore from trash). The Studio screen always sends a copy. A move is API-only.

Ask first

  • Where to? The receiving business's ID (the id its people sign in with), not its name.
  • What goes? Which collections (products, contacts, a custom collection). For each one: all of it, the records matching one filter, or particular rows.
  • Copy or move? Default to copy. A move empties those records out of this business.
  • Reason and note. The receiving business sees both while it decides.
  • Who accepts? Someone at the receiving business has to accept. Ask who to tell.

Steps

1. Studio › Data Transfers: check the business ID

call_appengine GET /org-management/transfer/requests/check-org/<id>. It answers { exists, orgId, name }. Otherwise it gives a reason: "No organization with that id", or "That is this organization" (both tested).

Hands on: the receiving business's ID and name. Check: exists: true, and the name is the business the person means. Read the name back to them.

2. Studio › Data Transfers: what goes

Collect the scope. One entry per collection:

EntrySends
{ "datatype": "product" }Every product.
{ "datatype": "contact", "filter": { "data.tags": "wholesale" } }Only matching records. The filter is a find query, the same shape as repo_find's query.
{ "datatype": "product", "ids": ["<sk>", "<sk>"] }Only these records. Each must be in this business.

Count each one first with repo_find (the request refuses a collection or filter with nothing in it: " has nothing to transfer in "). One request carries at most 100,000 records. Above that it refuses with "That is N records; one request carries at most 100000. Narrow it with a filter or split it up."

Hands on: the scope list and each count.

3. Studio › Data Transfers: send the request

Stop: sending notifies the receiving business by banner and email, and accepting it puts the records into their business. Show the person:

  • the receiving business's name and ID;
  • each collection with its count;
  • copy or move;
  • the reason and the note.

Send only after a clear yes.

call_appengine POST /org-management/transfer/requests
{ "targetOrgId": "<their id>", "mode": "copy",
  "scope": [ { "datatype": "product" }, { "datatype": "contact", "filter": { "data.tags": "wholesale" } } ],
  "reason": "Catalog for the Plano store", "message": "Prices are retail; adjust before publishing." }

The answer is the request: requestId, status: "pending", scope with each count, totalRecords, expiresAt (7 days on). The receiving business gets an in-app notice, "Review request", linking to the request. Its admins (or, when it has none, its company email) get the org-transfer-request email.

On screen: Configuration › Data Transfers (/org-transfers) › Send data to another business. Add collections, or the rows ticked in a collection's table. The table also has Send to another organization, which starts a request with the ticked rows. Then enter the Business ID; it is checked as you type. Press Send now. The screen sends all of a collection or the ticked rows, never a filter.

Hands on: the requestId. Check: GET /org-management/transfer/requests/<requestId> shows pending. The We sent tab lists it.

4. The receiving business: accept or decline

This happens in the receiving business, by one of its admins. When the person you are working for is the receiving business:

  • GET /org-management/transfer/requests?direction=incoming&status=pending lists what is waiting. GET …/<requestId> shows the scope, counts, mode, reason and note.
  • Stop: accepting copies the records into this business at once, and for a move it deletes them from the sender. It can't be undone from the request. Show the person what is in it and whether it is a move, and accept only after a clear yes.
  • Accept: POST /org-management/transfer/requests/<requestId>/accept. The answer comes back running straight away.
  • Decline: POST …/<requestId>/reject with { "reason": "…" }. The sender sees the reason and gets an email.

On screen: Configuration › Data Transfers, Coming to us tab: open the request, then Accept (Accept and transfer) or Decline.

The sender can withdraw a pending request: POST …/<requestId>/cancel (Withdraw on screen). After that it can't be accepted.

Check: the request's status and acceptedBy / rejectedBy / cancelledBy.

5. Data Transfers: follow it to the end

GET /org-management/transfer/requests/<requestId> while it runs:

  • processedRecords of totalRecords;
  • per collection, successCount and failCount in scope;
  • results, which has one row per record: assetId, success, the newId in the receiving business, or the error.

At the end it reads completed, partial or failed, with completedAt. Both businesses get the org-transfer-status email.

A record that already exists in the receiving business with the same unique value (a product's SKU, a name) fails. The screen shows that as "already in with the same ", under Why they did not land.

Check: in the receiving business, repo_find on each collection with { "data.transferredFrom.orgId": "<sender id>" } returns the arrivals.

What a transferred record keeps

  • Its data, under a new id. The copy is a new record with the same data and a new sk. It gets data.transferredFrom { orgId, originalId, transferredAt, transferredBy, mode }.
  • Not its links by id. Anything that points at another record by its id (an order's customer, a product's category id) still holds the sender's id. Send related collections together, and check the links after.
  • Not its history. Activity, comments and trash stay with the sender.

When it's done

Tell the person:

  • the request's final state;
  • per collection, how many arrived and how many failed, with the reasons;
  • for a move, that the originals are in this business's trash;
  • how the receiving business finds the new records (data.transferredFrom).

Open Configuration › Data Transfers on the request.

What it can't do yet

  • Customers, users, reservations and events don't transfer. Every such record fails, because the engine won't create them through a transfer. Staff users, bookings, events and companies fail too. The exception is customers that are only contacts (accountType: "contact"), which do arrive. Bring real customers over with a sign-up or import in the receiving business (Import records into a collection).
  • No filter or move on screen. The Studio screen sends whole collections or ticked rows, always as a copy. Filters and moves are API-only.
  • No undo. A copy stays in the receiving business until someone deletes it there. A move's originals can be restored from the sender's trash, but the copies stay.
  • No accept by email link. The email points to the Data Transfers screen.
  • Expiry is lazy. A request past 7 days shows expired only when it is next read.
  • A job that stops sends no email. When the copy itself breaks (failed with an error), neither business is emailed. Read the request.

Don'ts

  • Don't send a request without the person's yes on the business, the counts and the mode.
  • Don't accept a request on the receiving side without the person's yes. And never for a move they haven't understood.
  • Don't use a move to "try it". Copy first, check, then delete what you meant to remove.
  • Don't send customers (other than contacts), users, reservations or events expecting them to arrive.
  • Don't resend a whole collection to fill in what failed. Duplicates fail again. Send the failed rows by ids after fixing them.