API Reference (deprecated)
These endpoints have been deprecated. While they are are still suppported, we encourage you to check out our new API endpoints!
API requests use OAuth 2.0 bearer tokens over SSL, in
the Authorization
header (read through our authorization reference to find out how
to get a token. See here for a list of supported scopes).
If you get a non-200 response, check this list
of errors.
Your token gets genetic data from the customer who authorized it. If the "customer" was a demo account and not
genotyped, you can still get mock genetic data (from two anonymous humans) by prepending /demo/
to
most endpoints. For example:
curl https://api.23andme.com/1/user/ -H "Authorization: Bearer 081239h0f71hf" # customer's real data curl https://api.23andme.com/1/demo/user/ -H "Authorization: Bearer 081239h0f71hf" # anonymized data
User
Genetics
Phenotypes
Endpoints
endpoint | scope required | example call and result |
---|---|---|
GET /1/user/ GET /1/demo/user/ Back To Top ↑ |
basicemail(opt) |
Gets the user
The optional
The optional
A service model object is made up of a unique service This endpoint is great for using an app anonymously because there is no personally identifying information. curl https://api.23andme.com/1/user/ -H "..." # JSON response: { "id": "a42e94634e3f7683", "profiles": [ { "genotyped": true, "id": "c4480ba411939067" }, ... ] } ?services=true # JSON response: { "id": "a42e94634e3f7683", "profiles": [ { "genotyped": true, "id": "c4480ba411939067", "services": [ { "description": "Health", "label": "pgs_health", "id": 1 }, ... ] }, ... ] } ?email=true w/ email scope #JSON response: { "id": "a42e94634e3f7683", "email": "gregormendel@23andme.com", "profiles": [ { "genotyped": true, "id": "c4480ba411939067" }, ... ] } |
GET /1/names/profile_id/ GET /1/demo/names/profile_id/ Back To Top ↑ |
names | For the user and user's profile, gets first and last names. If your user wants to remain anonymous, you shouldn't request this scope. You can optionally filter by profile_id to get the names for just that profile.
curl https://api.23andme.com/1/names/ -H "..." # JSON response: { "first_name": "Gregor", "last_name": "Mendel", "id": "a42e94634e3f7683", "profiles": [ { "first_name": "Johann", "last_name": "Mendel", "id": "c4480ba411939067" }, ... ] } |
GET /1/profile_picture/profile_id/ POST /1/profile_picture/profile_id/ Back To Top ↑ |
We're no longer supporting this endpoint, please use the v3 profile endpoint | |
GET /1/genotypes/profile_id/?locations=&unfiltered=&format=... GET /1/demo/genotypes/profile_id/?locations=&unfiltered=&format=... Back To Top ↑ |
rsXX for each SNP requested, or genomes |
For the user's profile, returns the base-pairs, like AA , for the given locations . The value can have D s or I s for deletions and insertions (for example, DD or DI ). It can be __ if the customer is not on a chip that calls that location, or hasn't yet unlocked their call since it corresponds to a sensitive report. It can be -- if the customer is on a chip that calls that location, but we could not determine it. To keep consistency with the /genomes endoint, which always returns two base pairs, hemizygous calls (such as on X-linked genes in males) will also return two base pairs. The scope of your token must include each location you request (i.e., getting the below data requires a scope of at least rs3094315 i3000001 ). This list of SNPs (44MB) shows which SNPs our customers are genotyped for.
The unfiltered parameter can be used for completely sex-unfiltered data.
The format parameter can be used to alter the JSON output format of this endpoint.
Since this is a GET endpoint, you may hit the browser-imposed URL limit with a lot of SNPs. We recommend splitting your requests into 100-SNP chunks.
curl https://api.23andme.com/1/genotypes/c44.../?locations=rs3094315%20i3000001 -H "..." # JSON response: { "i3000001": "II", "rs3094315": "AA" "id": "c4480ba411939067" } ?format=embedded # JSON response: { "id": "c4480ba411939067" "genotypes": [ { "location": "i3000001", "call": "II" }, { "location": "rs3094315", "call": "AA" } ] } |
GET /1/phenotypes/profile_id/phenotype_id/ Back To Top ↑ |
phenotypes:read:<phenotype_id> E.g. phenotypes:read:sex
|
For the user's profile, returns the requested phenotype. Which phenotypes can I get?curl https://api.23andme.com/1/phenotypes/c44.../sex/ -H "..." # JSON response: { "phenotype_id": "sex", "value": "male", "profile_id": "c4480ba411939067" } |
PUT /1/phenotypes/profile_id/phenotype_id/ Back To Top ↑ |
phenotypes:write:<phenotype_id> E.g. phenotypes:write:date_of_birth |
For the user's profile, sets the requested phenotype data. Which phenotypes can I get? The response will be identical to the GET so that you can verify the data is set properly.curl -X PUT https://api.23andme.com/1/phenotypes/c44.../date_of_birth/ -d "value=1976-06-30" -H "..." # JSON response: { "phenotype_id": "date_of_birth", "value": "1976-06-30", "profile_id": "c4480ba411939067" } |
GET /1/genomes/profile_id/ GET /1/demo/genomes/profile_id/ Back To Top ↑ |
genomes | Returns the entire profile's genome as a packed string of base pairs "AACTGA..." . This ~2MB request returns over a million SNP locations, so you must specify profile_id . See the /genotypes endpoint for possible values. Each SNP is represented with two base pairs, and to know which SNP corresponds to which index, see this key.
The endpoint may return a result with "status": "PENDING" and "genome": null due to internal caching. If this happens, the result should be ready in a few minutes.
When our genotyping chip is upgraded, the packed string and corresponding key will grow, but the changes will be backwards-compatible additions. curl https://api.23andme.com/1/genomes/c44.../ -H "..." # JSON response: { "id": "c4480ba411939067", "genome": "ACTAGTAG__TTGADDAAIICCTT", # ... (2MB string!) "status": "READY" } # "Not ready" response: { "id": "c4480ba411939067", "genome": null, "status": "PENDING" } |
About the unfiltered
parameter
For the /genotypes endpoint, the optional parameter unfiltered
returns raw calls from our probes. It's unlikely you'd need it, unless you want to perform your own biological sex checks, or are developing a sex-specific app such as a check for Klinefelter's Syndrome. Without the parameter, we filter out calls based on the genotype's sex, but if ?unfiltered=true
, we will not filter:
- Y calls for women
- Heterozygous X calls for men on the non-pseudoautosomal region
- Heterozygous mitochondrial calls
List of phenotypes you can get/set
For the /phenotypes read and write endpoints, your phenotype_id
can be any of the following:
bd_pgen_patient_id
: Participation in Harvard (HSPH) study of personal genomics (PGen)date_of_birth
: date of birth (YYYY-MM-DD)family_tree_url
: family tree urlheight_mm
: height in millimetersplatform
: platformsex
: sexweight_g
: weight in grams