Since Viome doesn't appear to offer us a way to export our data aside from as a PDF, I was inspired to have a look if I could see it any other way.
The CEO says that they don't release the raw data:
I did stumble upon another project that follows a similar method of extracting data:
Which appears to use the following URLs:
- https://my.viome.com/app/authenticate/credentials
- https://my.viome.com/app/dashboard/user/external/user/recommendation/combined/latest
This tool (assuming it still works, which it looks like it should) allows you to export a CSV and HTML report based on your Viome data.
Wanting to understand it a bit better myself, I decided to explore the Viome website and see if it had any interesting API endpoints/data requests being sent back and forth.
We can log into the Viome web dashboard at: https://my.viome.com/
After which we see the following requests get made:
POST /app/authenticate/credentials
{"email":"REDACTED","password":"REDACTED","rememberMe":true}
- JSON: userID, loginInfo (providerID, providerKey), firstName, lastName, fullName, phone, email, phiHash, birthDate
- Seems to be some basic user/profile data
GET /app/dashboard/user/external/user/dietPreference/vegetarian/get
{"response":"success","errorMessage":null,"payload":null}
- Doesn't seem to do anything?
GET /app/external/user/profile
- JSON: userId, email, fullName, firstName, lastName, birthDate, gender, address (adressID, userID, addressLine1, city, state, zip, country), phone
- Seems to be some basic user/profile data.. again?
GET /app/external/alacarte/110
- JSON: resourceVideos, resultsLink, recsLink, resultsAndRecsLink, scoresLink, notifications, chatChannelId, eventChannelId, uiMessages, cohorts, completedKits, fsResults, tests, introQuestions, upsell, completedTests, lockstatus, expiredStates, showVieNotification, pendingScores, hiUpsellForResults, hasPersonalizedSupplementRecommendations, canPurchaseSupplementsStandalone, isPregnant, iOSMinVersion, planSample, showSubscriptionUpsell, userAgeEligibleForSupplements, userLocationEligibleForSupplements, showAdditionalSupplementLink
- There is HEAPS of content here (almost 5000 lines of json when pretty printed).. these are just the top level keys
- Looks like this is a lot of the data required for the app to render the initial page, not sure if any of it is directly useful for us or not
GET /app/dashboard/user/external/user/recommendation/combined/latest
- JSON: response, errorMessage, payload (foodList, avoidFoods, superFoods, supplements, recommendedAmounts, foodPrepareTips, overview, foodListChanged, foodListChangeFlag, foodListHash, allergyDisclaimer)
- This seems to contain data about our foods, things to avoid, suggested supplements, etc (and is also the endpoint the project above uses)
foodPrepareTips
appears to be a giant block of HTML
GET /app/dashboard/user/external/user/notification/getAll
- JSON: response, errorMessage, payload (array of: userNotificationId, endDate, created, kitId, testId, action, title, name, body, icon, color, ctaButton, actionIcon, systemId)
- Seems to be any notifications for the user
GET /app/user/order/latestAddress
- JSON: addressID, userID, addressLine1, addressLine2, city, state, zip, country
- Seems to be the user's address
GET /app/dashboard/user/external/results/combinedResultLite/${viomeTestKitId}
- JSON: labAndPersonInfoForAllTests, allNewScores, mainScores
- This also seems like it has a lot of the data related to our tests, but seems to be more about the scores related to microbial activity, their ranges, etc
mainScores
seems to have the bulk of the useful looking data
GET /app/dashboard/user/external/expiredstates/getAll
- JSON: giTests (array of: kitId, newTestRegistered, notifications, onDays, registrationDate, releaseDate, sampleExternalId, testMessages, testTypeSystemId validPeriod), fsTests, existExpiredGITest
GET /app/dashboard/user/external/results/combinedResult/${viomeTestKitId}
- JSON: allNewScores, biologicalAgeScore, compareAllMicrobes, ecosystemInsights, foodSensitivity, hasBioAge, labAndPersonInFoForAllTests, labAndPersonInfo, mainScores, resultSummary, wellnessScoresAndInsight
- This seems to have even more data about our microbes, etc (~24,000 lines when pretty printed)
GET /app/dashboard/user/external/user/recommendation/nutrient/latest
- JSON: response, errorMessage, payload (nutrientTypes, nutrients, scoreNutrientMapping)
nutrientTypes
: contains entries for Vitamins +, Food Extracts, Prebiotics, Probiotics (these seem like categories/similar)nutrients
: id, name, nutrientTypeIds, volume, description, importance (nutrientTypeIds
seems to map to the 'categories' above)scoreNutrientMapping
: scoreId, ingredients (ingredients
seem to be ids that map to the nutrients above)- I'm not sure if this is just generalised info about nutrients, or specifically recommendations for nutrients/supplements that would benefit me.. I think the latter
Looking in Chrome DevTools, using Redux DevTools I can see all of the frontend data/state used by the application. Could be useful.
Clicking on 'My Foods' takes us to https://my.viome.com/foods/recommendations
But it didn't actually seem to fetch any new data, so it must be a frontend route. Force reloading the page just made similar request as listed above, which supports this theory.
Clicking on My Results -> All My Scores takes us to https://my.viome.com/results/scores
GET /app/dashboard/user/external/trackingTest/getAll
- JSON: response, errorMessage, payload (tests: kitId, testType, testTypeSystemId, planName, status, isActive, registrationDate, displayResults, textDescription, statusMessage, sampleExternalId, isQuestionnaireComplete, isSampleQuestionnaireComplete, states, testId)
- This seems to have data relating to each Viome test we ordered, including their
kitId
's (needed for some of the earlier API requests)
GET /app/dashboard/user/external/results/combinedResult/undefined
- I believe this should have included one of the
kitID
's instead ofundefined
, matching the API call described above
- I believe this should have included one of the
Changing the dropdown menu to select a different test date made the following request:
GET /app/dashboard/user/external/results/combinedResult/${viomeTestKitId}
So it just appears to request the appropriate data and/or use what is already in the frontend redux data store.
Clicking My Results -> My Microbe Activity takes us to https://my.viome.com/results/microbiome-activity and doesn't seem to make any new data requests (neither does changing the test shown, or changing the filter; so this all seems to be done in the frontend)
Clicking My Results -> My Sample takes us to https://my.viome.com/results/gi-sample and makes the following requests:
GET /app/systemVersion
- JSON: response, errorMessage, payload (version, deployedOn)
It didn't appear to make any new requests when changing the sample selected.
Throughout this, I also noticed a number of requests being POST'd to sentry.io, which appears to be an error tracking service. These error contained a number of "Minified React error"; which probably isn't interesting, but noting here in case.
Without spending more time looking deeply at all of the data, the endpoints that most look like they would be useful to keep in a backup are:
GET /app/dashboard/user/external/trackingTest/getAll
- mostly just to get the testKitId's for the other endpoints
- NB: replace
${viomeTestKitId}
with the correct ID in the endpoints below - https://my.viome.com/app/dashboard/user/external/trackingTest/getAll
GET /app/dashboard/user/external/user/recommendation/combined/latest
GET /app/dashboard/user/external/results/combinedResultLite/${viomeTestKitId}
GET /app/dashboard/user/external/results/combinedResult/${viomeTestKitId}
GET /app/dashboard/user/external/user/recommendation/nutrient/latest
And maybe:
GET /app/systemVersion
- because it contains a version number and date that might be useful to know what version of the system generated the results we've backed up (or similar)
GET /app/external/alacarte/110
- just because it has so much data in it and there might be something useful
When trying to minimise what headers were required, the minimal set I got down to before it appeared to invalidate my authentication was:
User-Agent
Accept-Language
Cookie: authenticator=AAABBCCDDETCETCETC
My theory is that the cookie may incorporate the User-Agent
and/or Accept-Language
data somehow to determine if the session should be considered valid.
Therefore, an example curl
command would look something like:
curl -s -k -X $'GET' \
-H $'Host: my.viome.com' \
-H $'Connection: close' \
-H $'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36' \
-H $'Accept-Language: en-GB,en-US;q=0.9,en;q=0.8' \
-H $'Cookie: authenticator=AAABBCCDDETCETCETC' \
$'https://my.viome.com/app/external/user/profile'
All up the exported json data for 2 Viome gut tests for me takes up about 1.1mb (134KB zipped)
@podjackel Glad to hear it was helpful! :)