The API performs basic authentication (username, password) to authenticate API users before they can use API. Please coordinate with the 23andMe Fulfillment team to obtain API credentials.
The API allows partners to retrieve available orders, fulfill them, and mark them as shipped. The API user primarily will interact with the shipment endpoint (api/v1/shipment/) to update information regarding the progress of fulfilling an order, including when adding tracking numbers, carrier information, part numbers, etc.
Fulfillment partners are able to use the API to ship cartons of samples from distribution centers to a lab destination. Partners can create and update a carton of samples. An example of information to update a carton with includes shipping tracking information or a list of vendor codes associated with the samples. Refer to the entry on the carton (/api/v1/carton) endpoint for additional details.
Updates to a sample throughout its lifecycle can be sent communicated through the API. Once a sample arrives at a distribution center, partners can communicate this by using the sample (/api/v1/sample) endpoint. Partners can use the return (/api/v1/return) endpoint to mark samples as having returned to 23andMe's inventory. When samples are disposed of, fulfillment partner can invoke the scrap_kit (/api/v1/scrap_kit) endpoint to mark them as scrapped.
Lists all shipments that can be fulfilled or are being fulfilled by the warehouse.
Send shipment_status
as an optional URL filter parameter ('N'
for
all new shipments, 'R'
for shipments currently in fulfillment but not yet shipped).
No provided shipment_status will return all shipments with either status.
# Call curl https://fulfillment.23andme.io/api/v1/shipment/?shipment_status=N&format=json # Response { "meta": { "limit": 20, "next": "/api/v1/shipment/?offset=20&limit=20&format=json", "offset": 0, "previous": null, "total_count": 22 }, "objects": [ { "id": "744631937068271-2", "resource_uri": "/api/v1/shipment/744631937068271-2/", }, ... ] }
Lists an individual shipment's data.
View curl example# Call curl https://fulfillment.23andme.io/api/v1/shipment/716248990674159-1/?format=json # Response { "comments": "", "customer_id": "983", "freight_term": "Third Party", "id": "716248990674159-1", "number_line_items": 1, "order_items": [ { "commodity_code": "3926.90.9910", "country_of_origin": "CA", "description": "Personal Genome Service", "discounted_price": "99.00", "extended_price": "99.00", "id": 765828782327386, "kit_label_description": "", "part_number": "OGI-500", "quantity": 1, "unit_price": "15.00", "unit_weight": 150, "vendor_code": 12345678901234, } ], "order_status": "F", "order_status_label": "Fulfillment", "resource_uri": "/api/v1/shipment/716248990674159-1/", "ship_account_number": "846547419", "ship_address_1": "PO Box 333", "ship_address_2": "", "ship_address_3": "", "ship_city": "San Juan", "ship_company": "", "ship_country": "PR", "ship_first_name": "Anita", "ship_last_name": "Mann", "ship_method": "dhl", "ship_phone": "1111111111", "ship_state": "gg", "ship_zip": "00026", "shipment_status": "N", "total_order_value": "15.00" }
Marks an order for fulfillment or update the tracking number.
Send shipment_status
as a URL parameter to mark the order for fulfillment.
Send tracking_number
to update the tracking number for this order.
You don't have to send both parameters.
# Call for shipment_status curl "https://fulfillment.23andme.io/api/v1/shipment/716248990674159-1/ \ ?format=json&shipment_status=R" -X PATCH # Call for tracking_number curl "https://fulfillment.23andme.io/api/v1/shipment/716248990674159-1/ \ ?format=json" -X PATCH -d '{"tracking_number":012345678901234}' # Response (Returns a 204 NO CONTENT on success; use the GET to verify changed data.)
Add a shipping receipt to a shipment item.
Send shipping_method, time_shipped, tracking_number, items
,
and optional bulk_tracking_number
.
items
is a list of dicts; each element contains id, return_tracking_number,
vendor_code, part_number
, and optional carrier
.
Three API formats are supported. In the first, each of the 5 top-level parameters is supplied separately JSON encoded. In the second format, a single JSON encoded dictionary is supplied. The third format is a bulk style API which use bulk_order_line id.
View curl example# Call using older API curl https://fulfillment.23andme.io/api/v1/shipment/716248990674159-1/?format=json \ -d "shipping_method=USPS" \ -d "time_shipped=2014-04-01 12:12:12" \ -d "tracking_number=1234567890123456789012345678901234" \ -d "items=[{\"id\": 1237123, \"return_tracking_number\": 4891729871, \"vendor_code\": 12345678901234, \"part_number\": \"OGI-500\", \"carrier\": \"DHL\"}]" # Or call using newer (9/2014) API curl https://fulfillment.23andme.io/api/v1/shipment/716248990674159-1/?format=json \ -d '{"shipping_method:USPS","time_shipped":2014-04-01 12:12:12' \ ',"tracking_number": "1234567890123456789012345678901234"' \ ',"items":[{"id": 1237123, "return_tracking_number": "4891729871"' \ ', "vendor_code": "12345678901234", "part_number": "OGI-500", "carrier": "DHL"}]}' # Or call using bulk style (3/2016) API curl https://fulfillment.23andme.io/api/v1/shipment/716248990674159-1/?format=json \ -d '{"shipping_method":"USPS","time_shipped":"2017-11-07 12:12:12",'\ '"tracking_number": "1234567890123456789012345678901234","items":[{"bulk_line_id": 687834569072218,'\ '"part_number": "HUXX-00-N05","carrier":"DHL"}, [{"return_tracking_number":'\ '"4891729871", "vendor_code": "12345678901234"}]]}' # Response (Returns a 204 NO CONTENT on success; use the GET to verify changed data.) # Or call with the "post_async" parameter (Dec 2019) to asynchronously POST a shipment. # Expect a HTTP 202 response with an estimate of how long the shipment will take to complete. # Wait until the estimate elapses before repeatedly making the same POST request (with the "post_async" parameter) # to receive updates about the result of the shipment request until you receive a HTTP 204 # or an error code (HTTP 40X or 50X). curl https://fulfillment.23andme.io/api/v1/shipment/716248990674159-1/?format=json \ -d '{"shipping_method:USPS","time_shipped":2014-04-01 12:12:12'\ ',"tracking_number": 1234567890123456789012345678901234'\ ',"post_async": 1'\ ',"items":[{"id": 1237123, "return_tracking_number": "4891729871"'\ ',"vendor_code": "12345678901234", "part_number": "OGI-500", "carrier": "DHL"}]}' # Response (Returns a 202 ACCEPTED when first receiving the request with the "post_async" parameter.) (Returns a 204 NO CONTENT on success upon successive shipment POST requests. Use GET method to verify changed data.)
Lists all cartons associated with this distribution center (default for this user).
Send status
as a URL parameter (‘S’
to get all shipped cartons,
‘N’
for all new, unshipped cartons).
# Call curl "https://fulfillment.23andme.io/api/v1/carton/?format=json&status=N" # Response { "meta": { "limit": 20, "next": null, "offset": 0, "previous": null, "total_count": 2 }, "objects": [ { "id": null, "resource_uri": "/api/v1/carton/1/", "status": "N", "external_carton_id": "ABC23", }, ... ] }
Lists an individual carton’s data.
View curl example# Call curl https://fulfillment.23andme.io/api/v1/carton/2/?format=json # Response { "carrier": "DHL", "date_shipped": "2014-05-09T11:38:38", "external_carton_id": "ABC23", "id": "2", "lab_id": 2, "resource_uri": "/api/v1/carton/2/", "samples": [ "84769754409636", "53673257725370", "72175981970240", "96641311095096", "78784546468567" ], "status": "S", "tracking_number": "456789456123" }
Creates a new carton. Optional external_carton_id
parameter
can be sent with the POST. If not provided, defaults to null.
Optional from
parameter can be sent to indicate carton is from the non-default
location for this API user, e.g. "bedford", "oss", or "think".
# Call curl -X POST https://fulfillment.23andme.io/api/v1/carton/?format=json \ -d "external_carton_id=ABC23" \ # Response (Returns a 201 CREATED on success with the object in the body. The object url is also listed in the Location header) { "carrier": null, "date_shipped": null, "external_carton_id": "ABC23", "id": "3", "lab_id": 2, "resource_uri": "/api/v1/carton/3/", "samples": [], "status": "N", "tracking_number": null }
Updates all attributes, adds samples, and marks the carton as shipped.
Send lab_id, carrier, status
('S' for Shipped), tracking_number,
date_shipped
, and samples
which is a JSON-encoded list of barcodes.
Tracking number must be present but can be an empty string to be patched in later.
View curl example# Call curl https://fulfillment.23andme.io/api/v1/carton/3/?format=json \ -d "lab_id=2" \ -d "carrier=DHL" \ -d "status=S" \ -d "tracking_number=456789456124" \ -d "date_shipped=2014-05-09 11:38:38" \ -d "samples=[78923498743267, 78923498743268, 78923498743269, ...]" # Response (Returns a 204 NO CONTENT on success; use the GET to verify changed data.)
Updates some attributes on a previously shipped carton.
Can be any of passed carrier, tracking_number, date_shipped, external_carton_id
.
# Call curl https://fulfillment.23andme.io/api/v1/carton/3/?format=json -X PATCH \ -d "carrier=DHL" \ -d "tracking_number=456789456124" # Response (Returns a 204 NO CONTENT on success; use the GET to verify changed data.)
Mark a sample barcode as arrived at the Distribution Center. 'YYY' is
the sample barcode. Send arrival_time
as a parameter.
# Call curl "https://fulfillment.23andme.io/api/v1/sample/84769754409636/ \ ?format=json" -X PATCH \ -d "arrival_time=2014-05-12 11:38:38" # Response (Returns a 204 NO CONTENT on success)
Return a kit to inventory. 'YYY' is the sample barcode.
View curl example# Call curl "https://fulfillment.23andme.io/api/v1/return/84769754409636/ \ ?format=json" -X PATCH \ # Response (Returns a 200 OK on success)
Process a scrap end user return. 'YYY' is the sample barcode. An optional 'note' can be included in the request data to override the default "Scrap End User Return Invalidation", but the default is preferred.
View curl example# Call curl "https://fulfillment.23andme.io/api/v1/scrap_kit/84769754409636/ \ ?format=json" -X PATCH \ -d "note=Scrap End User Return Invalidation" \ # Response(s) (Returns a 200 OK on success, indicating the kit can be discarded) (Returns a 422 UNPROCESSABLE ENTITY on failure, with additional message indicating a review party has been contacted and to hold the kit and any related material until said party can review the case)
Requests information on previous ACH-mediated bulk retail order: 'YYY' is
either the retail_order_id
or the shipment_id
returned from the POST which created the request.
# Call curl "https://fulfillment.23andme.io/api/v1/bulk/716248990674159-1?format=json" # Response { "ach_order_id": "12345678", "other_field": "2014-05-09T11:38:38", ... }
Creates a new ACH-mediated bulk retail order.
Required parameters include ach_order_id
, lines
.
The request returns both the retail_order_id
and the shiment_id
.
The shipment_id
will generally be in status NEW
and will not show
as eligible for fulfillment for some time.
# Call curl https://fulfillment.23andme.io/api/v1/bulk/?format=json \ -d '{"ach_order_id" :"12345678"","VendorID" :"myFavoriteVendor" \ ', "PONumber": 1234567890123456789012345678901234', '"WarehouseID": 5'\ ',"lines":[{"quantity": 456, "part_number": "RUXX-00-N05"'\ ', "RetailSKU": 12345678901234, "UPC": "165100004324" },\ {"quantity": 444, "part_number": "RUXX-00-N05"'\ ', "RetailSKU": 12345678901234, "UPC": "165100004324" } ]}' # Response { "ach_order_id": "12345678", "retail_order_id": "813228966672189", "shipment_id": "716248990674159-1", }
Retrieves barcodes grouped by their status and a count of the number of barcodes in each status. The API expects the barcodes be provided in one of two ways. The barcodes can be a query parameter string separated by commas or as a JSON array. To provide barcodes in the JSON request body, it would have to adhere to the following pattern:
View request body example# Call curl https://fulfillment.23andme.io/api/v1/barcode_status?format=json { "barcodes": [1,2,3,4,5,6] }
If barcodes are not provided or barcodes that don't correspond to a sample are provided, the API will return a HTTP 400 Bad Request response. Below is an example of a call to the barcode_status API with barcodes provided in the query parameters.
View call example# Call curl https://fulfillment.23andme.io/api/api/v1/barcode_status?barcodes=123,124,125&format=json # Response { "objects": [{ "Invalid": { "barcodes": ["124"], "can_return_to_inventory": false, "count": 1, }, "Valid": { "barcodes": ["123", "125"], "can_return_to_inventory": true, "count": 2, }}]}
Creates a new sales order with the provided data parameters. Returns a JSON payload of the order, if created properly, and its attributes. This is a way of creating bulk orders that are sold by business parties (e.g. Amazon US).
View call example# Call curl -X POST https://fulfillment.23andme.io/api/v1/retail_order/ \ -d '{' \ '"ns_internal_id": "1234124", "business_party": "sales_us_amazon",' \ '"category": "expense_sales",' \ '"lines": [{"quantity": 10, "part_number": "HUXX-00-N08", "product_id": 64}]' \ ... }' # Response { "ns_internal_id": "1234124", "business_party": "sales_us_amazon", "category": "expense_sales", ... "time_created": "2021-01-01T12:00:00" }
Returns a JSON payload that describes a sales order that matches the provided query parameters.
View call example# Call curl -X GET https://fulfillment.23andme.io/api/v1/retail_order/ \ ?ns_internal_id=XYZ # Response { "ns_internal_id": "XYZ", "business_party": "sales_us_amazon" "category": "expense_sales" "order_status": "FULFILLMENT", "shipment_status": "IN_FULFILLMENT", ... "time_created": "2021-01-01T12:00:00", }
We use HTTP basic authentication.
Send an Authorization: Basic b64encode(username:password)
along with requests to the endpoints.
Contact us for a username and password.
Note: We have both orders and shipments. A single order can have multiple shipments (for reshipments only; we do not currently split kits from an order into separate shipments). A shipment will only be associated with one order. The status of both the Order and the Shipment matter for many fulfillment steps. These will be pointed out when pertinent. A list of possible statuses can be found at the end of this document.
Get all new shipments ready for shipping that are assigned to your warehouse:
GET /api/v1/shipment/?shipment_status=N&format=json
Adding the shipment_status=N parameter ensures that only orders that have not yet been claimed for fulfillment will show up.
Note that you can also see all shipments that have been claimed for fulfillment by your warehouse by changing the shipment_status parameter to ‘R’. ‘N’ and ‘R’ are the only allowable shipment_status filters. Not including a shipment_status parameter will return all shipments in status ‘R’ OR ‘N’ for your warehouse.
You can see detailed data for a particular shipment by sending a GET request with the ID (in format XXX-Y):
GET /api/v1/shipment/XXX-Y/?format=json
This will return information about the shipment. Included in this information is the order_status and shipment_status for this shipment.
When you are ready to import a shipment into your system, send a PATCH request to that particular shipment endpoint. This should be done before any actual work is done to ship the shipment. Until this step is performed, a customer can still cancel their order.
PATCH /api/v1/shipment/XXX-Y/?format=json&shipment_status=R
Include the shipment_status=R parameter.
For the PATCH to succeed, the starting shipment_status must be ‘N’ and the order_status must be ‘A’ or ‘C’. After a successful request, the shipment_status will become ‘R’ and the order_status will become ‘F’ (if it was ‘A’) or stay ‘C’ (if it was ‘C’).
When a shipment is packaged and ready to ship, send a POST request to the particular shipment endpoint with all necessary parameters.
POST /api/v1/shipment/XXX-Y/?format=json
See the documentation for this endpoint for the necessary parameters. Note that the item id’s come from the shipment detail GET (step 2) -- they are within the order_items list.
The starting shipment_status must be ‘R’ for this POST to succeed. After a successful POST, the shipment_status will be ‘S’. Note that ALL order items (kits) associated with this shipment must be sent in a single POST request or the POST will fail.
After the customer has spit into his/her kit and returned it to the distribution center, the steps below should be followed:
When a sample (kit) is received at the distribution center, a PATCH request should be sent to the sample endpoint:
PATCH /api/v1/sample/YYY/?format=json
YYY is the sample barcode (not the tracking number). The arrival time should be included as a parameter.
The sample must have starting status ‘V’ for the request to be successful. You will not have control over or visibility into the sample status, but will receive an error message back if the starting status is incorrect. You should contact 23andMe if this happens so we can trace what went wrong.
Create a new, empty carton by sending a POST request:
POST /api/v1/carton/?format=json
An optional external_carton_id parameter can be provided if you have an internal ID number for this carton. 23andMe will create its own carton number and return this back to you in the body of the response and also in the Location header.
To view details for the newly created carton:
GET /api/v1/carton/XXX/?format=json
XXX comes from the 23andMe carton id returned to you from the POST in step 2.
Also relevant: if you wish to view all cartons that are associated with your distribution center:
GET /api/v1/carton/?format=json
Add an optional ‘status’ parameter if desired: ‘S’ for all shipped cartons, ‘N’ for all new, unshipped cartons.
To ship a carton, send a POST request to the specific carton endpoint with all necessary parameters, including the sample barcodes in the carton.
POST /api/v1/carton/XXX/?format=json
XXX is the carton id returned from the creation POST in step 2. The required attributes can be found in the documentation for this endpoint.
Samples being added to the carton must have a status of ‘C’ (which they should have if the PATCH from step 1 was successful). The carton must be in status ‘N’. All samples that are being shipped in a carton must be added at the same time in one POST request (this request both adds the samples to the carton and marks the carton as shipped). A successful POST will change the carton status to ‘S’.
STATUS_NEW = 'N'
STATUS_HELD = 'H'
STATUS_APPROVED = 'A'
STATUS_CANCELLED = 'X'
STATUS_IN_FULFILLMENT = 'F'
STATUS_COMPLETED = 'C'
STATUS_AUTO_FULFILLED = 'U'
STATUS_NEW = 'N'
STATUS_IN_FULFILLMENT = 'R'
STATUS_CANCELLED = 'X'
STATUS_FULFILLED = 'F'
STATUS_SHIPPED = 'S'
STATUS_NEW = 'N'
STATUS_SHIPPED = 'S'
STATUS_RECEIVED = 'R'
STATUS_CANCELLED = 'X'