Skip to content

Instantly share code, notes, and snippets.

@westdavidr
Last active May 7, 2022 15:41
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save westdavidr/c8890e46a8f06b92df85 to your computer and use it in GitHub Desktop.
Save westdavidr/c8890e46a8f06b92df85 to your computer and use it in GitHub Desktop.
Young Living API reference

##API URLS


##Authentication

To obtain a token, issue a request to POST https://youngliving.com/api/accounts/token

  • The request must be a HTTP POST request.
  • The request must include a Content-Type header with the value of application/json.
  • The body of the request must in JSON format with memberId and password.

Request body

{
    "memberId": "",
    "password": ""
}

Example request

POST /api/accounts/token HTTP/1.1
Host: youngliving.com
Content-Type: application/json

{
    "memberId": "123456",
    "password": "sosecret"
}

##Organization Base URL: https://youngliving.com/vo.dlv.api/downline ###Endpoints

  • GET /children/user/{periodid}
  • GET /children/member_id/{periodid}
  • GET /detail/user/{periodid}
  • GET /detail/{memberid}/{periodid}

###Examples

  • (0 can be used in place of {periodid} for current period)

####Get downline for authorized user. Example Request:

GET
https://youngliving.com/vo.dlv.api/downline/children/user/405

Example Response:

{
	"customerid": "1449977",
	"currentperiodid": 406,
	"periodid": 405,
	"chartstartperiod": 398,
	"chartendperiod": 405,
	"totalchildren": 74,
	"legs": [ ]
}

####Get downline for specific user Example Request:

GET
https://youngliving.com/vo.dlv.api/downline/children/1223344/405

Example Response:

{
	"customerid": 1223344,
	"currentperiodid": 406,
	"periodid": 405,
	"chartstartperiod": 398,
	"chartendperiod": 405,
	"totalchildren": 15,
	"legs": [ ]
}

####Get details for authorized user. Example Request:

GET 
https://youngliving.com/vo.dlv.api/downline/detail/user/405

Example Response:

{
	"customerid": 123456,
	"name": "BLOW, JOE",
	"customertype": 2,
	"email": "test@example.com",
	"mainphone": "1234567891",
	"datesignedup": "5/1/2013 12:27:52 PM",
	"dateactivated": "5/1/2013 12:27:52 PM",
	"onhold": false,
	"activitystatusid": 1,
	"holdreason": "",
	"avatarimage": "",
	"volume": { },
	"rank": { },
	"address": { },
	"autoship": { },
	"sponsor": { },
	"enroller": { }
}

####Get details for a specific user. Example Request:

GET 
https://youngliving.com/vo.dlv.api/downline/detail/user/405

Example Response:

{
	"customerid": 1223344,
	"name": "MEMBER, COOL",
	"customertype": 2,
	"email": "test@example.net",
	"mainphone": "1234567891",
	"datesignedup": "11/16/2013 12:19:32 PM",
	"dateactivated": "11/16/2013 12:19:32 PM",
	"onhold": false,
	"activitystatusid": 1,
	"holdreason": "",
	"avatarimage": "",
	"volume": { },
	"rank": { },
	"address": { },
	"autoship": { },
	"sponsor": { },
	"enroller": { },
	"sponsorpath": [ ]
}

##Commission Base URL: https://youngliving.com/vo.dlv.api/commission ###Endpoints

  • GET: /check/summary/{periodid}
  • GET: /check/unilevel/{periodid}/{levelnum}
  • GET: /history/{periodid}

###Examples

  • (0 can be used in place of {periodid} for current period)

####Get commission check summary for a specific commission period. Example Request:

GET
https://youngliving.com/vo.dlv.api/commission/check/summary/405

Example Result:

{
  "customerid":"123456",
  "checkid":"12345678",
  "checkdate":"11/17/2014",
  "periodid":"405",
  "checktotal":"314.39",
  "totalcommission":"317.39",
  "currencyunit":"USD",
  "dgyf":"0",
  "paidasrankid":2,
  "maxrankid":2,
  "volume":{
    "ogv":4635.5,
    "pv":290.25,
    "pgv":4635.5
  },
  "retail":{
    "commission":"11.84"
  },
  "unilevel":{
    "commission":"229.71",
    "levels":[
      {
        "levelnum":1,
        "commission":"$142.83"
      },
      {
        "levelnum":2,
        "commission":"$63.49"
      },
      {
        "levelnum":3,
        "commission":"$23.39"
      }
    ]
  },
  "faststart":{
    "commission":"75.84",
    "levels":[
      {
        "levelnum":1,
        "commission":"$8.44"
      },
      {
        "levelnum":2,
        "commission":"$67.40"
      }
    ]
  },
  "personalgen":{
    "commission":"0"
  },
  "generations":{
    "commission":"0"
  },
  "risingstar":{
    "commission":"0"
  },
  "leadership":{
    "commission":"0"
  },
  "diamondexpress":{
    "commission":"0"
  },
  "starterkit":{
    "commission":"0"
  },
  "adjustments":{
    "total":"-3",
    "items":[
      {
        "description":"Maintenance Fee",
        "amount":"-3",
        "commledgertypeid":2
      }
    ]
  }
}

#####Get commission check details for a specific level in a commission period. Example Request:

GET
https://youngliving.com/vo.dlv.api/commission/check/unilevel/405/1

Example Result:

{
  "customerid":123456,
  "periodid":406,
  "commissionvolume":1785,
  "percentage":8,
  "commissionearned":"$142.83",
  "unilevel":{
    "levels":[
      {
        "membernum":123445,
        "membername":"MEMBER, COOL",
        "commissionvolume":75.25,
        "percentage":8.0,
        "commissionsearned":6.02
      },
      ...
    ]
  }
}

#####Get commission check details for a specific level in a commission period. Example Request:

GET
https://youngliving.com/vo.dlv.api/commission/history/405

Example Result:

{
  "customerid":1449977,
  "checks":[
    {
      "periodid":405,
      "checknumber":"12345678",
      "checkdate":"11/17/2014",
      "amount":317.39,
      "amountformatted":"$317.39",
      "currency":"USD"
    },
    ...
  ]
}

##Qualification Endpoints


##Essential Rewards Base URL: https://youngliving.com/api/shopping/essential-rewards ###Endpoints

  • GET: /info

###Examples

####Get essential rewards information Example Request:

GET
https://youngliving.com/api/shopping/essential-rewards/info

Example Result:

{
	"totalPoints": 96,
	"totalExpiringPoints30Days": 0,
	"consecutiveMonthsOfErOrders": 12,
	"earningPercentage": 15,
	"availableMonthlyPoints": 96,
	"monthsBeforePercentageIncrease": 0,
	"nextEarningRate": 0,
	"isEnrolled": true,
	"payments": [ ],
	"legacyOtgProcessingDayOfMonth": 1,
	"legacyNfrProcessingDayOfMonth": 1,
	"isErTemplateConfirmed": true,
	"areErDeliveriesValid": true,
	"doesTemplateMeetMinPv": true,
	"otg": {
		"processingDate": {
			"year": 2014,
			"month": 12,
			"day": 1
		}
	},
	"nfr": {
		"processingDate": {
			"year": 2014,
			"month": 11,
			"day": 1
		}
	}
}

##Helpers

function getPeriodId(date) { // Defaults to Current Period if you leave 'date' empty
    date = date instanceof Date ? date : new Date();
    return (date.getFullYear() * 12 + date.getMonth() + 1) - (2014 * 12 + 5) + 400;
}
@rob-richards
Copy link

@westdavidr I was testing the API calls with postman, and YL updated the base URL and the required fields in the payload. I forked and updated your gist. Can you review an merge it?

@svdhorst
Copy link

Has anybody produced a .Net client for the YL api yet? If not then I will develop it. Also is there an api that shows all of my orders. Finally is there an api that shows all products and their prices

@sjcrook
Copy link

sjcrook commented Jul 31, 2018

@westdavidr, @rob-richards: I've successfully managed to get the token - I got a JSON object back. What from the JSON object do I use as a key to make the call to the API proper? Do I add a param to the query string of the URL, the POST body or something else? What's the format? Help appreciated.

@sampsasomerma
Copy link

sampsasomerma commented Sep 29, 2018

I just tried out the API. For some reason it gives me "HTTP Error 405: Method Not Allowed". Could someone confirm that it still works.

POST to https://youngliving.com/api/accounts/token with JSON payload containing username and password.

UPDATE 09.30.2018

  1. Apparently URL is https://www.youngliving.com/api/accounts/token (changed)
  2. I'm getting HTTP/1.1 401 Unauthorized from the server

@Xefrok
Copy link

Xefrok commented May 14, 2019

Hello guys, i got the token but now how do i get all the info?
im new in json requests, any guide or something i need to know? i dont know how to properly search in google because i dont know what i need to know exactly to make de GET request after the POST token.
Help a newbie

@jstanleydev
Copy link

I too would like to know more about the shopping api. Is there a way to get products and pricing?

@pizzapanther
Copy link

@westdavidr your work helped speed up my own usage of the API but it looks like it changed quite a bit.

I got the API working by doing the following:

  • make sure to use www in all calls instead of the bare domain name.
  • use a session and call https://www.youngliving.com/vo/ first to get cross site and other cookies. Use the subsequent session for the rest of the calls.
  • login for the token has multiple parameters:
{
        "userName": username,
        "email": username,
        "memberId": username,
        "password": password,
        "rememberMe": True,
}
  • When you do the login you get a json body, to create your token take the JSON string and base64 encode:
python:
token = base64.b64encode(response.content).decode()

js:
token = btoa(body)
  • use the token in headers as authtoken={token}

@brassnkeys
Copy link

Does anyone have more detail on this. I can get it to return data for on the login, but token is not one of the properties. There is a signature. Is that it? Also, are there API calls to view orders and items? One of the biggest difficulties with YL's online system is that all past orders are just pdfs with no way to get a list of items purchased in some easy format.

@pizzapanther
Copy link

The token is the whole body of the response after you call https://www.youngliving.com/api/accounts/token

@brassnkeys
Copy link

The token is the whole body of the response after you call https://www.youngliving.com/api/accounts/token

Thanks. I was able to determine what was wrong. It works with the base64.b64encode(res.content) after I realized that my module variable wasn't global so the token was empty when I went to use it again. Python mistake.

Any thoughts on other URLs though? I really would like to pull orders from the past. My goal is to pull all the items ordered in each order#, etc. All the URLs listed here seem to focus on just the organization structure, commissions, etc.

@pizzapanther
Copy link

I'm not certain about URLs since i'm not doing that but I was able to get the info I needed by running a report and exporting the data to a CSV. Then parsing the CSV. Maybe there is a similar report for items ordered?

This is dumping a user's contacts:

def get_contacts(self):
    # need the period ID from the summary to download a report
    summary_url = 'https://www.youngliving.com/vo.dlv.api//dashboard/summary'
    response = self.session.get(summary_url, headers=self.headers())
    self.raise_exception(response)
    summary = response.json()

    load_url = 'https://www.youngliving.com/vo.dlv.api//reportdata/v2/load'
    load_data = {
      "reportid": "all",
      "periodid": summary['organization'][0]['periodid'],
      "sortby":"",
      "sortdesc":1,
      "pagenumber":1,
      "filters":[],
      "columns":[{"id":"memberid"},{"id":"name"},{"id":"email"},{"id":"address"},{"id":"phone"}],
      "download":"true",
      "format":"CSV"
    }

    response = self.session.post(load_url, headers=self.headers(), json=load_data)
    self.raise_exception(response)

    csv_url = 'https://www.youngliving.com/vo.dlv.api/reports/download/All%20Accounts/{reportid}/{guid}/1/en-US'.format(
      **response.json()
    )
    response = self.session.get(csv_url, headers=self.headers())
    self.raise_exception(response)
    fh = io.StringIO(response.text)
    reader = csv.DictReader(fh)
    rows = []
    for row in reader:
      rows.append(row)
    fh.close()

    return rows

@artiisgithub
Copy link

Hello, does anyone have any CORS issue with Vuejs? Was trying to obtain the token but seeing
'Access to XMLHttpRequest at 'https://youngliving.com/api/accounts/token' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.'

Any advice? Thanks a lot.

@pizzapanther
Copy link

The token request has the header access-control-allow-origin: https://www.youngliving.com so that would cause problems.

Other APIs have the header access-control-allow-origin: * so they should work.

I've been making all my calls on my backend to avoid CORS issues and then just sending the frontend necessary data.

@gera3d
Copy link

gera3d commented May 26, 2020

Hello,
Has anyone tried loading this data into a google spreadsheet? What would doing that look like? As I add users to my downline I want to add them to my spreadsheet.

@pizzapanther
Copy link

You should be able to download that data in their back office as a CSV then loading into a spreadsheet. You could do this automatically with their API but you could also do it manually.

@7even84
Copy link

7even84 commented Jun 2, 2020

Hey hie guys! Thanks so much for this work! I been trying to get past the token phase but seems to be hitting an issue. Thanks in advance for the help :)

My steps:

  1. Obtain a token by issuing a request to POST https://youngliving.com/api/accounts/token
  2. Received the response with user details.
  3. Use the below info format (Using the details received and then encode into Base64) -- Do we need to encode the whole received message of the below fields are sufficient?

{
"userName": username,
"email": username,
"memberId": username,
"password": password,
"rememberMe": True,
}

  1. Use the base64 string as the header for key authtoken
  2. Get https://www.youngliving.com/vo.dlv.api/downline/children/user/405 (replace user with my userID)
  3. Get error below. Same issue for other get request. Any idea how to get past this?
<title>Runtime Error</title> <style> body { font-family: "Verdana"; font-weight: normal; font-size: .7em; color: black; }
	p {
		font-family: "Verdana";
		font-weight: normal;
		color: black;
		margin-top: -5px
	}

	b {
		font-family: "Verdana";
		font-weight: bold;
		color: black;
		margin-top: -5px
	}

	H1 {
		font-family: "Verdana";
		font-weight: normal;
		font-size: 18pt;
		color: red
	}

	H2 {
		font-family: "Verdana";
		font-weight: normal;
		font-size: 14pt;
		color: maroon
	}

	pre {
		font-family: "Consolas", "Lucida Console", Monospace;
		font-size: 11pt;
		margin: 0;
		padding: 0.5em;
		line-height: 14pt
	}

	.marker {
		font-weight: bold;
		color: black;
		text-decoration: none;
	}

	.version {
		color: gray;
	}

	.error {
		margin-bottom: 10px;
	}

	.expandable {
		text-decoration: underline;
		font-weight: bold;
		color: navy;
		cursor: hand;
	}

	@media screen and (max-width: 639px) {
		pre {
			width: 440px;
			overflow: auto;
			white-space: pre-wrap;
			word-wrap: break-word;
		}
	}

	@media screen and (max-width: 479px) {
		pre {
			width: 280px;
		}
	}
</style>
<span><H1>Server Error in '/vo.dlv.api' Application.<hr width=100% size=1 color=silver></H1>

        <h2> <i>Runtime Error</i> </h2></span>

<font face="Arial, Helvetica, Geneva, SunSans-Regular, sans-serif ">

	<b> Description: </b>An application error occurred on the server. The current custom error settings for this
	application prevent the details of the application error from being viewed remotely (for security reasons). It
	could, however, be viewed by browsers running on the local server machine.
	<br><br>

	<b>Details:</b> To enable the details of this specific error message to be viewable on remote machines, please
	create a &lt;customErrors&gt; tag within a &quot;web.config&quot; configuration file located in the root
	directory of the current web application. This &lt;customErrors&gt; tag should then have its &quot;mode&quot;
	attribute set to &quot;Off&quot;.<br><br>

	<table width=100% bgcolor="#ffffcc">
		<tr>
			<td>
				<code><pre>

<!-- Web.Config Configuration File -->

<configuration>
<system.web>
<customErrors mode="Off"/>
</system.web>
</configuration>

			</td>
		</tr>
	</table>

	<br>

	<b>Notes:</b> The current error page you are seeing can be replaced by a custom error page by modifying the
	&quot;defaultRedirect&quot; attribute of the application&#39;s &lt;customErrors&gt; configuration tag to point
	to a custom error page URL.<br><br>

	<table width=100% bgcolor="#ffffcc">
		<tr>
			<td>
				<code><pre>

<!-- Web.Config Configuration File -->

<configuration>
<system.web>
<customErrors mode="RemoteOnly" defaultRedirect="mycustompage.htm"/>
</system.web>
</configuration>

			</td>
		</tr>
	</table>

	<br>

</body>

@jrcano
Copy link

jrcano commented Aug 3, 2020

Here is a sample in .net c#

using (var client = new HttpClient())
{
string baseURL = @"https://www.youngliving.com/";
client.BaseAddress = new Uri(baseURL);
var credentials = new
{
memberId = @"your MemberId",
password = "your Password"
};
var jsonCredentials = JsonConvert.SerializeObject(credentials);
var requestBody = new StringContent(jsonCredentials);
requestBody.Headers.ContentType = new MediaTypeHeaderValue("application/json");
//HTTP POST
var getTask = client.PostAsync("api/accounts/token", requestBody);
getTask.Wait();
//res = getTask.Result.StatusCode.ToString();
if (getTask.Result.IsSuccessStatusCode)
{
var readTask = getTask.Result.Content.ReadAsStringAsync();
readTask.Wait();
var plainToken = System.Text.Encoding.UTF8.GetBytes(readTask.Result);
var token64 = System.Convert.ToBase64String(plainToken);
client.DefaultRequestHeaders.Add("authtoken", token64);
// The last parameter is the period Id, if you don't know it you can use 0 for the current Period
var getUser = client.GetAsync("vo.dlv.api/downline/children/yourMemberId/0");
getUser.Wait();
if (getUser.Result.IsSuccessStatusCode)
{
var readUser = getUser.Result.Content.ReadAsStringAsync();
readUser.Wait();
// The result is a json with your results
}
}
}

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