# xPlant API > The xPlant REST API (v1) lets a lab's own systems read and write its xPlant workspace: plants, explants, tasks, transfers and stages, SOP runs, labels, devices, sensor readings and equipment events. - API base URL: https://app.xplantpro.com/api/v1 - Auth: `Authorization: Bearer `; workspace keys start `xpk_`, device tokens start `xpd_`. - Every response is `{"ok":true,"data":...}` or `{"ok":false,"data":null,"error":"...","code":"STABLE_CODE"}`; branch on `code`, never on `error`. - JavaScript SDK: `npm install @shmaplex/xplant-sdk` (https://github.com/shmaplex/xplant_sdk) - Product: xPlant, lab management for plant tissue culture: https://www.xplantpro.com - Plans (which include the API): https://www.xplantpro.com/en/subscriptions - Everything on one page: https://docs.xplantpro.com/llms-full.txt - Support: support@xplantpro.com ## Get started - [Overview](https://docs.xplantpro.com/docs.md): What the xPlant API is for, how it's shaped, and where to start. - [Quickstart](https://docs.xplantpro.com/docs/quickstart.md): Create an API key and make your first three calls, in about five minutes. - [Use with AI tools](https://docs.xplantpro.com/docs/ai-tools.md): Every page is available as plain Markdown, and the whole API fits in one file for an assistant to read. ## Essentials - [Authentication and API keys](https://docs.xplantpro.com/docs/authentication.md): How to create a key, send it, keep it safe, and tell the two kinds of credential apart. - [Scopes](https://docs.xplantpro.com/docs/scopes.md): What each of the 34 scopes allows, and the endpoints it unlocks. - [Device tokens](https://docs.xplantpro.com/docs/device-tokens.md): Give each device an xpd_ token that can post its own readings and nothing else. Never put a workspace key on a device. - [Requests and responses](https://docs.xplantpro.com/docs/requests-and-responses.md): The base URL, headers, and the one response envelope every endpoint uses. - [Errors](https://docs.xplantpro.com/docs/errors.md): Every error code the API returns, what it means, and what your integration should do about it. - [Rate limits](https://docs.xplantpro.com/docs/rate-limits.md): 1,000 requests a minute per key, 3,000 per workspace, and what happens when you go over. - [Idempotency](https://docs.xplantpro.com/docs/idempotency.md): Send an Idempotency-Key on a write so retrying it after a timeout can't create a duplicate. - [Pagination](https://docs.xplantpro.com/docs/pagination.md): Every list pages by cursor. Pass meta.next_cursor back as cursor until it's null. ## Guides - [Guides](https://docs.xplantpro.com/docs/guides.md): Worked examples for the integrations labs build most often. - [Sync tasks](https://docs.xplantpro.com/docs/guides/sync-tasks.md): Create, prioritise and complete bench work from your own scheduler, without overriding the order people set by hand. - [Push demand signals](https://docs.xplantpro.com/docs/guides/demand-signals.md): Send xPlant a demand number per genus, from orders, sales or forecasts, so it can weigh the task queue toward what sells. - [Record transfers and stages](https://docs.xplantpro.com/docs/guides/transfers-and-stages.md): Log subcultures to fresh media and move plants and explants through tissue-culture stages from a script or a scanner. - [Run an SOP from a bench station](https://docs.xplantpro.com/docs/guides/sop-runs.md): Start a run of the SOP in force, confirm steps with scans, and record measurements with their units. - [Label scanning](https://docs.xplantpro.com/docs/guides/label-scanning.md): Resolve a scanned QR code or barcode to the plant or explant it labels, and record that the scan happened. - [Sensors and devices](https://docs.xplantpro.com/docs/guides/sensors-and-devices.md): Register a device, give it a device token, and post batched sensor readings, heartbeats and events from a Raspberry Pi or an ESP32. - [Equipment events](https://docs.xplantpro.com/docs/guides/equipment-events.md): Let an autoclave, a balance or a pH meter report when it was used, calibrated or maintained. - [Pull change history](https://docs.xplantpro.com/docs/guides/change-history.md): Mirror every plant and explant edit into your own database, incrementally. ## Reference - API reference - [API overview](https://docs.xplantpro.com/docs/api.md): Every v1 endpoint, the scope it needs, and what it returns. - Account - [Get the calling key](https://docs.xplantpro.com/docs/api/account/get-me.md): Who the calling key is: its name, the workspace it acts in, the scopes it holds, and which of them it can use right now. Make this the first call an integration makes: it confirms the key works and tells you in one answer what it may do, instead of one 403 at a time. - [Get the workspace](https://docs.xplantpro.com/docs/api/account/list-workspaces.md): The lab this key acts in, with its name — so an integration can show which lab it is writing to, and stop if it has been pointed at the wrong one. - Plants - [List plants](https://docs.xplantpro.com/docs/api/plants/list-plants.md): The workspace's plants, newest first, a page at a time. Pass externalId to find the one plant filed under your own identifier instead; the answer is still a list, with that plant or nothing, and meta.next_cursor is always null. - [Create a plant](https://docs.xplantpro.com/docs/api/plants/create-plant.md): Adds a plant to the workspace, recorded as created by the key's owner, and starts it in initial_stage. - [Get a plant](https://docs.xplantpro.com/docs/api/plants/get-plant.md): One plant, with the lab's own fields. - [Update a plant](https://docs.xplantpro.com/docs/api/plants/update-plant.md): Changes only the fields you send. Send null to clear an optional one. - Explants - [List explants](https://docs.xplantpro.com/docs/api/explants/list-explants.md): The workspace's explants, newest first, a page at a time. Pass externalId to find the one culture filed under your own identifier instead; the answer is still a list, with that explant or nothing, and meta.next_cursor is always null. - [Create an explant](https://docs.xplantpro.com/docs/api/explants/create-explant.md): Adds an explant to the workspace, recorded as created by the key's owner. Link it to the plant it was taken from with plant_id. - [Get an explant](https://docs.xplantpro.com/docs/api/explants/get-explant.md): One explant, with the lab's own fields. - [Update an explant](https://docs.xplantpro.com/docs/api/explants/update-explant.md): Changes only the fields you send. Send null to clear an optional one. - Transfers and stages - [List stages](https://docs.xplantpro.com/docs/api/transfers-and-stages/list-stages.md): Every stage one plant or explant has been through, newest first — where it is now and how it got there. Send exactly one of plant_id or explant_id. - [Advance a stage](https://docs.xplantpro.com/docs/api/transfers-and-stages/create-stage.md): Moves a plant or explant into a new stage in one call: the stage it is in now is marked completed, the new one is recorded, and it becomes the current stage. Send exactly one of plant_id or explant_id. - [List transfers](https://docs.xplantpro.com/docs/api/transfers-and-stages/list-transfers.md): 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. - [Record a transfer](https://docs.xplantpro.com/docs/api/transfers-and-stages/create-transfer.md): Records a transfer — a subculture onto fresh media — for one plant or explant. Send exactly one of plant_id or explant_id. Everything else is optional: the date defaults to today and the cycle to the next one in the record's history. - Change history - [List change history](https://docs.xplantpro.com/docs/api/change-history/list-change-events.md): What has happened to the workspace's plants or explants, oldest first: transfers, stage changes, contamination records, observations, printed labels. - Contaminations - [List contaminations](https://docs.xplantpro.com/docs/api/contaminations/list-contaminations.md): The workspace's contamination logs, newest first. Narrow to one plant or explant, to one status, or to what was logged since a point in time. Withdrawn logs are never listed. - [Record a contamination](https://docs.xplantpro.com/docs/api/contaminations/create-contamination.md): Records a contamination seen on one plant or explant, as the key's owner. It is the same record the app makes: it appears in the plant's or explant's history, and for an explant the stage and room the culture was in when it was seen are recorded with it, which is what lets the app show that room's conditions over the week before. - [Get a contamination](https://docs.xplantpro.com/docs/api/contaminations/get-contamination.md): One contamination log, with the plants and explants it is linked to. - Tasks and demand - [List tasks](https://docs.xplantpro.com/docs/api/tasks/list-tasks.md): The workspace's tasks, earliest due first. Filter by board column or assignee; with neither, you get the whole queue a page at a time. - [Create a task](https://docs.xplantpro.com/docs/api/tasks/create-task.md): Adds a task to the workspace. Set priority, priority_rank and assigned_to in the same call so a scheduler can place work in one request. Order set this way counts as automatic, so a later hand-reorder in the app takes precedence over your next sync. - [Get a task](https://docs.xplantpro.com/docs/api/tasks/get-task.md): One task, including the plant or explant it is linked to. - [Update a task](https://docs.xplantpro.com/docs/api/tasks/update-task.md): Changes only the fields you send. Move a task along the board with workflow_status; complete it with "done". - [List demand signals](https://docs.xplantpro.com/docs/api/tasks/list-demand-signals.md): Demand signals pushed for the workspace, newest first, a page at a time. Add genus to see one genus, and current=true as well to get its current demand as a single reading; that answer is never paged, and meta.next_cursor is always null. - [Record a demand signal](https://docs.xplantpro.com/docs/api/tasks/create-demand-signal.md): Records how much demand there is for a genus — orders, sales velocity, a forecast — from any source you run. xPlant uses the latest signal per genus when it scores the task queue. Send one whenever your number changes; history is kept. - Comments - [List comments](https://docs.xplantpro.com/docs/api/comments/list-comments.md): The discussion on one plant, explant, contamination log, task, media recipe or SOP, oldest first. Replies carry parent_id. A deleted comment keeps its place, with its text removed, so the replies to it still read in order. - [Add a comment](https://docs.xplantpro.com/docs/api/comments/create-comment.md): Adds a comment to a plant, explant, contamination log, task, media recipe or SOP, as the key's owner. It is the same comment the app makes: members it names are notified, the author of the comment it replies to is told, the people following a task hear about it, and it appears in the record's activity. - Media - [List media files](https://docs.xplantpro.com/docs/api/media/list-assets.md): The photos and files attached to one plant, explant, contamination log or SOP, newest first. Each carries a view_url: a link to the file itself that works for 15 minutes. List again for fresh links, and never store one. - [Attach a media file](https://docs.xplantpro.com/docs/api/media/create-asset.md): Attaches an image to a plant, explant, contamination log or SOP in the workspace. It appears on that record in xPlant exactly like a photo added in the app. Send the image as image_url or as image_base64 — exactly one. - [Get a media file](https://docs.xplantpro.com/docs/api/media/get-asset.md): One photo or file, with a view_url that works for 15 minutes from this response. Fetch it again whenever you need the file; never store the link. - [List media recipes](https://docs.xplantpro.com/docs/api/media/list-media-recipes.md): The workspace's culture media recipes that the key's owner can see — their own, and those shared with the workspace or published — newest first, each with its components. Another member's private recipe is not listed. Filter by status. - [Create a media recipe](https://docs.xplantpro.com/docs/api/media/create-media-recipe.md): Creates a recipe in the workspace with the key's owner as its creator. It starts at version 1 and is private to its creator unless visibility is team. - [Get a media recipe](https://docs.xplantpro.com/docs/api/media/get-media-recipe.md): One recipe with its components and current version. - [Update a media recipe](https://docs.xplantpro.com/docs/api/media/update-media-recipe.md): Changes only the fields you send. Only the recipe's creator can change it. - SOPs and runs - [Start an SOP run](https://docs.xplantpro.com/docs/api/sops/create-sop-run.md): Starts a run of an SOP: the record that a procedure was carried out, step by step, against the version the lab had in force. - [Get an SOP run](https://docs.xplantpro.com/docs/api/sops/get-sop-run.md): One run: the SOP and version it follows, where it stands, and every piece of evidence posted against its steps, oldest first — the trail to read forwards when you need to know what was done, in what order. - [Record step evidence](https://docs.xplantpro.com/docs/api/sops/create-sop-step-event.md): Records what happened at one step of a run: someone confirmed it, scanned a label or vessel, skipped it, or left a note, or an instrument reported its state. - [Record a step measurement](https://docs.xplantpro.com/docs/api/sops/create-sop-step-measurement.md): Records a numeric reading against one step of a run — the pH of a medium, the mass of an ingredient, a temperature — with its unit, as the bench station running the SOP reads it from a balance, pH meter or probe. - [List SOPs](https://docs.xplantpro.com/docs/api/sops/list-sops.md): The workspace's standard operating procedures, most recently updated first — drafts and archived ones included, with status saying which. Summaries only: fetch one SOP to read the steps of the version in force. - [Get an SOP](https://docs.xplantpro.com/docs/api/sops/get-sop.md): One SOP and the version the lab works from right now, with its steps — what a bench station shows the person at the hood. - Labels - [Record a label scan](https://docs.xplantpro.com/docs/api/labels/create-label-scan.md): Records that a code was scanned — where, and when. Resolving a label only reads; this writes the visit down. - [Resolve a label](https://docs.xplantpro.com/docs/api/labels/resolve-label.md): Turns a scanned or typed code into the record it identifies, for scanners and bench hardware. xPlant checks, in order: plant labels, explant labels, container labels, then your own plant and explant identifiers — so a code your lab writes on the jar itself, such as LINE-0412, resolves too. - Devices - [Record a device event](https://docs.xplantpro.com/docs/api/devices/create-device-event.md): Records something that happened on a device — an alert, an error, a firmware update or a configuration change — with whatever detail you put in payload. Send it with the device's own token, which may only write about that device, or with a workspace key. - [List devices](https://docs.xplantpro.com/docs/api/devices/list-devices.md): Every device registered to the workspace, newest first, a page at a time. Pages hold up to 200 devices by default, so most workspaces receive every device in the first answer; follow meta.next_cursor until it comes back null to be sure you have them all. - [Register a device](https://docs.xplantpro.com/docs/api/devices/create-device.md): Adds a sensor, controller or gateway to the workspace so it can send heartbeats, readings and events. Then mint a device token for it and put that token on the device, rather than a workspace key. - [Send a heartbeat](https://docs.xplantpro.com/docs/api/devices/send-heartbeat.md): Tells xPlant the device is alive and stamps its last-seen time. xPlant shows a device as offline once 15 minutes pass without hearing from it, so send a heartbeat every minute or two. The request has no body. - [List device tokens](https://docs.xplantpro.com/docs/api/devices/list-device-tokens.md): Every token minted for the device, active and revoked, newest first. Each carries its prefix, name, status and last use — what you need to tell tokens apart and decide which to revoke. The secret itself is never returned after the token is minted. - [Create a device token](https://docs.xplantpro.com/docs/api/devices/create-device-token.md): Creates a credential for one device. Put it on the device in place of a workspace key: it can send that device's heartbeats, readings and events, and nothing else. - [Revoke a device token](https://docs.xplantpro.com/docs/api/devices/revoke-device-token.md): Stops one device token working: the next request made with it is refused as unauthorized. The token stays in the device's token list, marked revoked with the time it was revoked, so the list remains a complete history of the device's credentials. - Sensor readings - [List sensor readings](https://docs.xplantpro.com/docs/api/sensor-readings/list-sensor-readings.md): The workspace's environmental readings, newest first, a page at a time. Narrow them to one device, one growing room or one kind of measurement, and use since and until to fetch only the readings taken within a window. - [Submit sensor readings](https://docs.xplantpro.com/docs/api/sensor-readings/create-sensor-readings.md): Stores readings from a device. Send one reading, or up to 500 at once as { "readings": [...] }. Batch them: a gateway that buffers readings and posts every 30 to 60 seconds uses a small fraction of the requests of one that posts each reading as it is taken. - Equipment - [List equipment](https://docs.xplantpro.com/docs/api/equipment/list-equipment.md): The workspace's equipment library, newest first, with each item's calibration and maintenance due dates. Filter by category and status; with neither you get every item, archived ones included. - [Get a piece of equipment](https://docs.xplantpro.com/docs/api/equipment/get-equipment.md): One piece of equipment, with its calibration and maintenance due dates. - [List equipment events](https://docs.xplantpro.com/docs/api/equipment/list-equipment-events.md): A piece of equipment's history, newest first: what it was used on, and its calibration and preventive maintenance records. Each event has the fields of its kind; the others are null. - [Record an equipment event](https://docs.xplantpro.com/docs/api/equipment/create-equipment-event.md): Records that a piece of equipment was used, calibrated or serviced — from the instrument itself, or from any system that knows. Events are history: there is no update or delete, and a correction is another event. - Pricing and sell-through - [List order lines](https://docs.xplantpro.com/docs/api/commerce/list-order-lines.md): Your store's sales, line by line, most recent first: which product sold, the culture line it is matched to, how many, at what unit price, and when. Filter with from and to for a period and product_link_id for one product. - [Get sell-through](https://docs.xplantpro.com/docs/api/commerce/get-sell-through.md): Units sold and revenue per culture line over a period, highest units first. Filter with from and to for the period and plant_id for one culture line. - [List culture line prices](https://docs.xplantpro.com/docs/api/commerce/list-culture-line-prices.md): Each priced culture line's current list and wholesale price and its pricing tier, newest first by when the line was first priced. Filter to one culture line with plant_id, or to one tier with pricing_tier. - [List price changes](https://docs.xplantpro.com/docs/api/commerce/list-price-events.md): Every change to a culture line's price, newest first: what it moved from, what it moved to, when, who or what moved it. Filter with plant_id for one culture line and from and to for a period. - [JavaScript SDK](https://docs.xplantpro.com/docs/sdk.md): @shmaplex/xplant-sdk: a typed server-side client for Node.js 18+ and other fetch runtimes, with retries, timeouts, idempotency and paging built in. - [Hardware and examples](https://docs.xplantpro.com/docs/hardware.md): Open-source firmware, gateways and example scripts for connecting lab devices to xPlant.