Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
(unofficial) Guide to Viome API Endpoints, Data Export and Backup

(unofficial) Guide to Viome API Endpoints, Data Export and Backup

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:

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 of undefined, matching the API call described above

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.


So what should I back up?

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:

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment