xPlantAPI
API referenceTransfers and stages

List transfers

The transfer history of one plant or explant, newest first: every move onto fresh media, where it went and which subculture it was. Send exactly one of plant_id or explant_id.

GET/api/v1/transfers
Scope read:transfers

Each transfer carries your lab's own fields in custom_fields.

The list is ordered by transfer_date, which changes when a planned transfer is postponed or edited: a transfer changed while you page through can move between pages. Transfers on the same date keep a fixed order.

Query parameters

NameTypeRequiredDescription
plant_idstring (uuid)NoThe plant whose transfers to list. Send exactly one of plant_id or explant_id.
explant_idstring (uuid)NoThe explant whose transfers to list.
limitintegerNoPage size. Values above 200 are capped at 200. Default 50. From 1 to 200.
offsetintegerNoNumber of records to skip. Prefer cursor where a list offers it: an offset shifts when records are added ahead of it. Default 0. At least 0.
cursorstringNoContinue from the previous page: pass its meta.next_cursor unchanged, with the same filters. Treat it as opaque. Not combinable with offset. Up to 2048 characters.

Example

curl "https://app.xplantpro.com/api/v1/transfers?explant_id=7c1d9e2a-3b4f-4a5c-8d6e-1f2a3b4c5d6e" \
  -H "Authorization: Bearer $XPLANT_API_KEY"

Response

200 with { "ok": true, "data": … }. data is an array. To get the next page, pass meta.next_cursor back as cursor; it is null on the last page. See Pagination.

FieldTypeRequiredDescription
idstring (uuid)Yes—
entity_type"plant" | "explant"YesWhether the transfer was of a plant or an explant.
entity_idstring (uuid)YesThe plant's or explant's id.
transfer_datestring | nullYesWhen the transfer was done, as an ISO 8601 timestamp.
transfer_cycleinteger | nullYesWhich subculture this was for the plant or explant — 1 for the first.
from_locationstring | nullYesWhere the culture was before the transfer.
to_locationstring | nullYesWhere the culture went.
statusstringYesactive for a transfer recorded through the API. Transfers scheduled in xPlant read pending until someone marks them completed or cancelled.
notesstring | nullYes—
created_atstring | nullYes—
custom_fieldsobjectYesYour lab's own fields on this transfer, keyed by field key. Always an object: {} when none were filled in, and always {} on a plant transfer.
Response
{
  "ok": true,
  "data": [
    {
      "id": "c7d8e9f0-a1b2-4c3d-8e4f-5a6b7c8d9e0f",
      "entity_type": "explant",
      "entity_id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "transfer_date": "2026-09-24T00:00:00+00:00",
      "transfer_cycle": 5,
      "from_location": "Growth room 1, shelf B2",
      "to_location": "Growth room 1, shelf C1",
      "status": "active",
      "notes": "LINE-0412 onto fresh multiplication medium. Two jars browning at the base, set aside.",
      "created_at": "2026-09-24T09:12:44.000Z",
      "custom_fields": {
        "vessel_lot": "LOT-2291",
        "hood": "Hood 2"
      }
    }
  ]
}

The envelope can also carry meta:

FieldTypeRequiredDescription
next_cursorstring | nullYesPass as cursor to fetch the next page. null means this is the last page.
Response headerMeaning
X-Request-IdIdentifies this request. Include it when you contact support.

Errors

StatusCodeWhen
401UNAUTHORIZEDThe key is missing, malformed or revoked, or its owner is no longer a member of the workspace.
402PAID_PLAN_REQUIREDThe workspace's plan does not include the API. The full API is included with xPlant+ Teams and Enterprise; on Hobby and Pro Lab, keys can connect devices only.
403FORBIDDENThe key lacks a scope this operation requires, or its owner's current role in the workspace cannot use it — a key never does more than its owner can in xPlant. error names the scope, and for a role, the role it needs.
403DEVICE_TOKEN_NOT_ACCEPTEDA device token was sent; this operation needs a workspace API key.
404NOT_FOUNDThe plant or explant is not in this workspace.
422VALIDATION_ERRORBoth cursor and offset were sent; use one.
422INVALID_CURSORThe cursor is malformed, or came from a different list or different filters. Start again without it.
422VALIDATION_ERRORNeither or both of plant_id and explant_id were sent.
429RATE_LIMIT_EXCEEDEDToo many requests for this key, device token or workspace. Wait Retry-After seconds.
500TRANSFER_QUERY_FAILEDThe transfers could not be read. Retry later.

Branch on code, never on the error text. See Errors.

On this page