The HTTP Client extension allows us to execute HTTP requests against a webserver.
This tutorial lesson demonstrates how to fetch data from an external API, by:
Retrieving the members of an email list from Mailchimp's REST API, extracting their emails, and doing something with this data
Retrieving repositories from GitHub's GraphQL API
The docs for Mailchimp's API explain that we must send a GET
request against the REST API, to fetch an email list members' data:
curl --request GET \
--url 'https://us7.api.mailchimp.com/3.0/lists/{LIST_ID}/members' \
--user 'username:password'
Copy
Let's replicate this in Gato GraphQL.
We execute an HTTP request via global field _sendHTTPRequest
(provided via the HTTP Client extension):
query {
_sendHTTPRequest ( input : {
url : "https://us7.api.mailchimp.com/3.0/lists/{LIST_ID}/members" ,
method : GET ,
options : {
auth : {
username : "{USER}" ,
password : "{API_TOKEN}"
}
}
}) {
body
contentType
statusCode
headers
serverHeader : header ( name : "Server" )
}
}
Copy
Field _sendHTTPRequest
returns an object of type HTTPResponse
. After executing the query, notice that the body
field (of type String
) contains the raw content of the response:
{
"data" : {
"_sendHTTPRequest" : {
"body" : "{ \" members \" :[{ \" id \" : \" mSjGOg5qSb3dKTxPU9lhRZCxHGug8Mrt \" , \" email_address \" : \" vinesh@yahoo.com \" , \" unique_email_id \" : \" KObAXbEO3X \" , \" contact_id \" : \" JiCdz5EY67m3PKugW3bRE9VI1WjiBbjq \" , \" full_name \" : \" Vinesh Munak \" , \" web_id \" :443344389, \" email_type \" : \" html \" , \" status \" : \" subscribed \" , \" consents_to_one_to_one_messaging \" :true, \" merge_fields \" :{ \" FNAME \" : \" Vinesh \" , \" LNAME \" : \" Munak \" , \" ADDRESS \" :{ \" addr1 \" : \"\" , \" addr2 \" : \"\" , \" city \" : \"\" , \" state \" : \"\" , \" zip \" : \"\" , \" country \" : \" IN \" }, \" PHONE \" : \"\" , \" BIRTHDAY \" : \"\" }, \" stats \" :{ \" avg_open_rate \" :0.8, \" avg_click_rate \" :0.6}, \" ip_signup \" : \"\" , \" timestamp_signup \" : \"\" , \" ip_opt \" : \" 218.115.112.129 \" , \" timestamp_opt \" : \" 2020-12-31T06:55:17+00:00 \" , \" member_rating \" :4, \" last_changed \" : \" 2020-12-31T06:55:17+00:00 \" , \" language \" : \"\" , \" vip \" :false, \" email_client \" : \"\" , \" location \" :{ \" latitude \" :2.18, \" longitude \" :99.47, \" gmtoff \" :8, \" dstoff \" :8, \" country_code \" : \" MY \" , \" timezone \" : \" asia/kuala_lumpur \" , \" region \" : \" 10 \" }, \" source \" : \" Admin Add \" , \" tags_count \" :0, \" tags \" :[], \" list_id \" : \" 9nrwpfj0ou \" , \" _links \" :[{...}]},{...}], \" total_items \" :4927, \" _links \" :[{...}]}" ,
"contentType" : "application/json; charset=utf-8" ,
"statusCode" : 200 ,
"headers" : {
"Server" : "openresty" ,
"Content-Type" : "application/json; charset=utf-8" ,
"Vary" : "Accept-Encoding" ,
"X-Request-Id" : "177551d0-82e9-3d61-a664-177f61b91f80" ,
"Link" : "<https://us7.api.mailchimp.com/schema/3.0/Lists/Members/Collection.json>; rel= \" describedBy \" " ,
"Date" : "Thu, 13 Jul 2023 04:57:42 GMT" ,
"Transfer-Encoding" : "chunked" ,
"Connection" : "keep-alive,Transfer-Encoding"
},
"serverHeader" : "openresty"
}
}
}
Copy
As the content-type of the response is application/json
, we can transform the raw body content from String
to JSONObject
via field _strDecodeJSONObject
(from the PHP Functions Via Schema extension):
query {
_sendHTTPRequest ( input : {
url : "https://us7.api.mailchimp.com/3.0/lists/{LIST_ID}/members" ,
method : GET ,
options : {
auth : {
username : "{USER}" ,
password : "{API_TOKEN}"
}
}
}) {
body @remove
bodyJSONObject : _strDecodeJSONObject ( string : $__body )
}
}
Copy
The body is now accessible as a JSON object:
{
"data" : {
"_sendHTTPRequest" : {
"bodyJSONObject" : {
"members" : [
{
"id" : "mSjGOg5qSb3dKTxPU9lhRZCxHGug8Mrt" ,
"email_address" : "vinesh@yahoo.com" ,
"unique_email_id" : "KObAXbEO3X" ,
"contact_id" : "JiCdz5EY67m3PKugW3bRE9VI1WjiBbjq" ,
"full_name" : "Vinesh Munak" ,
"web_id" : 443344389 ,
"email_type" : "html" ,
"status" : "subscribed" ,
"consents_to_one_to_one_messaging" : true ,
"merge_fields" : {
"FNAME" : "Vinesh" ,
"LNAME" : "Munak" ,
"ADDRESS" : {
"addr1" : "" ,
"addr2" : "" ,
"city" : "" ,
"state" : "" ,
"zip" : "" ,
"country" : "IN"
},
"PHONE" : "" ,
"BIRTHDAY" : ""
},
"stats" : {
"avg_open_rate" : 0.8 ,
"avg_click_rate" : 0.6
},
"ip_signup" : "" ,
"timestamp_signup" : "" ,
"ip_opt" : "218.115.112.129" ,
"timestamp_opt" : "2020-12-31T06:55:17+00:00" ,
"member_rating" : 4 ,
"last_changed" : "2020-12-31T06:55:17+00:00" ,
"language" : "" ,
"vip" : false ,
"email_client" : "" ,
"location" : {
"latitude" : 2.18 ,
"longitude" : 99.47 ,
"gmtoff" : 8 ,
"dstoff" : 8 ,
"country_code" : "MY" ,
"timezone" : "asia/kuala_lumpur" ,
"region" : "10"
},
"source" : "Admin Add" ,
"tags_count" : 0 ,
"tags" : [],
"list_id" : "9nrwpfj0ou" ,
"_links" : [
{
// ...
},
// ...
]
},
{
// ...
}
],
"list_id" : "9nrwpfj0ou" ,
"total_items" : 4927 ,
"_links" : [
{
// ...
},
// ...
]
}
}
}
}
Copy
HTTP Client also provides function fields that already handle responses of content-type application/json
, making these suitable for connecting to REST APIs:
_sendJSONObjectItemHTTPRequest
: When the content pertains a single JSON object
_sendJSONObjectCollectionHTTPRequest
: When the content pertains a collection of JSON objects
These fields already convert the response to JSONObject
or [JSONObject]
.
These fields expect the status code of the response to be successful (i.e. in the 200-299
range, such as 200
, 201
or 202
), as it enables them to already return a JSONObject
containing the decoded-as-JSON body of the response.
When this is not the case, the GraphQL response will contain a corresponding error.
For instance, when fetching a non-existing post from the WP REST API's endpoint /wp-json/wp/v2/posts/{postId}/
, the response will be:
{
"errors" : [
{
"message" : "Client error: `GET https://newapi.getpop.org/wp-json/wp/v2/posts/88888/` resulted in a `404 Not Found` response: \n { \" code \" : \" rest_post_invalid_id \" , \" message \" : \" Invalid post ID. \" , \" data \" :{ \" status \" :404}} \n " ,
"locations" : [
{
"line" : 3 ,
"column" : 17
}
],
"extensions" : {
"path" : [
"externalData: _sendJSONObjectItemHTTPRequest(input: {url: \" https://newapi.getpop.org/wp-json/wp/v2/posts/88888/ \" }) @export(as: \" externalData \" )" ,
"query ConnectToAPI { ... }"
],
"type" : "QueryRoot" ,
"field" : "externalData: _sendJSONObjectItemHTTPRequest(input: {url: \" https://newapi.getpop.org/wp-json/wp/v2/posts/88888/ \" }) @export(as: \" externalData \" )" ,
"id" : "root" ,
"code" : "PoP/ComponentModel@e1"
}
}
],
"data" : {
"externalData" : null
}
}
Copy If we do not want to treat any non-200s
status code (such as 302
, 404
or 500
) as an error, we must use the _sendHTTPRequest
field.
Adapting the previous query:
query {
_sendJSONObjectItemHTTPRequest ( input : {
url : "https://us7.api.mailchimp.com/3.0/lists/{LIST_ID}/members" ,
method : GET ,
options : {
auth : {
username : "{USER}" ,
password : "{API_TOKEN}"
}
}
})
}
Copy
...produces this response:
{
"data" : {
"_sendJSONObjectItemHTTPRequest" : {
"members" : [
{
"id" : "mSjGOg5qSb3dKTxPU9lhRZCxHGug8Mrt" ,
"email_address" : "vinesh@yahoo.com" ,
"unique_email_id" : "KObAXbEO3X" ,
"contact_id" : "JiCdz5EY67m3PKugW3bRE9VI1WjiBbjq" ,
"full_name" : "Vinesh Munak" ,
"web_id" : 443344389 ,
"email_type" : "html" ,
"status" : "subscribed" ,
"consents_to_one_to_one_messaging" : true ,
"merge_fields" : {
"FNAME" : "Vinesh" ,
"LNAME" : "Munak" ,
"ADDRESS" : {
"addr1" : "" ,
"addr2" : "" ,
"city" : "" ,
"state" : "" ,
"zip" : "" ,
"country" : "IN"
},
"PHONE" : "" ,
"BIRTHDAY" : ""
},
"stats" : {
"avg_open_rate" : 0.8 ,
"avg_click_rate" : 0.6
},
"ip_signup" : "" ,
"timestamp_signup" : "" ,
"ip_opt" : "218.115.112.129" ,
"timestamp_opt" : "2020-12-31T06:55:17+00:00" ,
"member_rating" : 4 ,
"last_changed" : "2020-12-31T06:55:17+00:00" ,
"language" : "" ,
"vip" : false ,
"email_client" : "" ,
"location" : {
"latitude" : 2.18 ,
"longitude" : 99.47 ,
"gmtoff" : 8 ,
"dstoff" : 8 ,
"country_code" : "MY" ,
"timezone" : "asia/kuala_lumpur" ,
"region" : "10"
},
"source" : "Admin Add" ,
"tags_count" : 0 ,
"tags" : [],
"list_id" : "9nrwpfj0ou" ,
"_links" : [
{
// ...
},
// ...
]
},
{
// ...
}
],
"list_id" : "9nrwpfj0ou" ,
"total_items" : 4927 ,
"_links" : [
{
// ...
},
// ...
]
}
}
}
Copy
Connecting to the WP REST API, whether from an external server or from this same site, follows the same procedure.
For instance, this GraphQL query connects to the WP REST API from the local site with ?context=edit
mode (for which it must provide the application password credentials):
query GetPostEditingDataFromRESTAPI (
$postId : ID!,
$username : String!,
$applicationPassword : String!
) {
siteURL : optionValue ( name : "siteurl" )
@remove
endpoint : _sprintf (
string : "%s/wp-json/wp/v2/posts/%d/?context=edit" ,
values : [
$__siteURL ,
$postId ,
]
)
@remove
_sendJSONObjectItemHTTPRequest ( input : {
url : $__endpoint ,
method : GET ,
options : {
auth : {
username : $username ,
password : $applicationPassword
}
}
})
}
Copy Passing these variables:
{
"postId" : 1 ,
"username" : "{username}" ,
"applicationPassword" : "{application password}"
}
Copy ...the response is:
{
"data" : {
"_sendJSONObjectItemHTTPRequest" : {
"id" : 1 ,
"date" : "2020-04-17T13:06:58" ,
"date_gmt" : "2020-04-17T13:06:58" ,
"guid" : {
"rendered" : "https://mysite.com/?p=1" ,
"raw" : "https://mysite.com/?p=1"
},
"modified" : "2020-04-17T13:06:58" ,
"modified_gmt" : "2020-04-17T13:06:58" ,
"password" : "" ,
"slug" : "hello-world" ,
"status" : "publish" ,
"type" : "post" ,
"link" : "https://mysite.com/hello-world/" ,
"title" : {
"raw" : "Hello world!" ,
"rendered" : "Hello world!"
},
"content" : {
"raw" : "<!-- wp:paragraph --> \n <p>Welcome to WordPress. This is your first post. Edit or delete it, then start writing!</p> \n <!-- /wp:paragraph -->" ,
"rendered" : " \n <p>Welcome to WordPress. This is your first post. Edit or delete it, then start writing!</p> \n " ,
"protected" : false ,
"block_version" : 1
},
"excerpt" : {
"raw" : "" ,
"rendered" : "<p>Welcome to WordPress. This is your first post. Edit or delete it, then start writing!</p> \n " ,
"protected" : false
},
"author" : 2 ,
"featured_media" : 0 ,
"comment_status" : "open" ,
"ping_status" : "open" ,
"sticky" : false ,
"template" : "" ,
"format" : "standard" ,
"meta" : [],
"categories" : [
1
],
"tags" : [],
"permalink_template" : "https://mysite.com/%postname%/" ,
"generated_slug" : "hello-world" ,
"_links" : {
// ...
}
}
}
}
Copy
HTTP Client also provides a function field to conveniently connect to GraphQL APIs.
Field _sendGraphQLHTTPRequest
accepts those inputs expected by GraphQL (the query, variables and operation name), executes the GraphQL query against the provided endpoint, and converts the response to JSONObject
.
This query connects to GitHub's GraphQL API and retrieves the list of repos for the indicated owner:
query FetchGitHubRepositories (
$authorizationToken : String!
$login : String!
$numberRepos : Int! = 3
) {
_sendGraphQLHTTPRequest ( input :{
endpoint : "https://api.github.com/graphql" ,
query : "" "
query GetRepositoriesByOwner($login: String!, $numberRepos: Int!) {
repositoryOwner(login: $login) {
repositories(first: $numberRepos) {
nodes {
id
name
description
}
}
}
}
""" ,
variables : [
{
name : "login" ,
value : $login
},
{
name : "numberRepos" ,
value : $numberRepos
}
],
options : {
auth : {
password : $authorizationToken
}
}
})
}
Copy
Passing these variables
:
{
"authorizationToken" : "{ GITHUB ACCESS TOKEN }" ,
"login" : "leoloso"
}
Copy
...produces this response:
{
"data" : {
"_sendGraphQLHTTPRequest" : {
"data" : {
"repositoryOwner" : {
"repositories" : {
"nodes" : [
{
"id" : "MDEwOlJlcG9zaXRvcnk2NjcyMTIyNw==" ,
"name" : "PoP" ,
"description" : "Monorepo of the PoP project, including: a server-side component model in PHP, a GraphQL server, a GraphQL API plugin for WordPress, and a website builder"
},
{
"id" : "MDEwOlJlcG9zaXRvcnkxODQ1MzE5NzA=" ,
"name" : "PoP-API-WP" ,
"description" : "Bootstrap a PoP API for WordPress"
},
{
"id" : "MDEwOlJlcG9zaXRvcnkxOTYwOTk0MzQ=" ,
"name" : "leoloso.com" ,
"description" : "My personal site, based on Hylia (https://hylia.website)"
}
]
}
}
}
}
}
}
Copy
If we must execute the same HTTP request repeatedly, we can use the @cache
directive (provided by the Field Resolution Caching ) to store the result in disk for a requested amount of time, thus speeding up the query resolution.
When executing this query twice within a span of 10 seconds (as indicated via argument @cache(time:)
), the second time will retrieve the cached result; this will make it faster, as it will not connect to the external host:
query ConnectToGitHub ( $authorizationToken : String!)
{
_sendGraphQLHTTPRequest ( input :{
endpoint : "https://api.github.com/graphql" ,
query : "" "
{
repositoryOwner(login: " leoloso ") {
url
}
}
""" ,
options : {
auth : {
password : $authorizationToken
}
}
})
# Cache the response to disk, indicating for how many seconds
@cache ( time : 10 )
}
Copy The @cache
directive:
Works with any of the fields returning a JSON response, including _sendJSONObjectItemHTTPRequest
and _sendGraphQLHTTPRequest
Is independent (i.e. it does not care about the logic of the fields where it is applied), hence it works whether the HTTP request method is GET
or POST
It does not work with _sendHTTPRequest
, as the HTTPResponse
object it returns is a "transient" object (i.e. it is not stored in the WordPress database), that only lives during the current request
We can send HTTP requests to multiple URLs, fetching data from all of them at the same time.
Every one of the HTTP request fields explored above has a corresponding "multiple" field:
_sendHTTPRequests
_sendJSONObjectItemHTTPRequests
_sendJSONObjectCollectionHTTPRequests
_sendGraphQLHTTPRequests
All these fields have argument async
, to indicate if to execute the multiple HTTP requests asynchronously or synchronously:
Asynchronously: The HTTP requests are executed all together, in parallel
Synchronously: Each HTTP request is sent out only after the previous one is completed
This GraphQL query retrieves weather forecast data for multiple regions:
query {
_sendJSONObjectItemHTTPRequests ( inputs : [
{
url : "https://api.weather.gov/gridpoints/TOP/31,80/forecast"
},
{
url : "https://api.weather.gov/gridpoints/TOP/41,55/forecast"
}
])
}
Copy
...producing:
{
"data" : {
"_sendJSONObjectItemHTTPRequests" : [
{
"@context" : [
"https://geojson.org/geojson-ld/geojson-context.jsonld" ,
{
"@version" : "1.1" ,
"wx" : "https://api.weather.gov/ontology#" ,
"geo" : "http://www.opengis.net/ont/geosparql#" ,
"unit" : "http://codes.wmo.int/common/unit/" ,
"@vocab" : "https://api.weather.gov/ontology#"
}
],
"type" : "Feature" ,
"geometry" : {
"type" : "Polygon" ,
"coordinates" : [
[
[
-97.137207 ,
39.7444372
],
[
-97.1367549 ,
39.7223799
],
[
-97.1080809 ,
39.7227252
],
[
-97.10852700000001 ,
39.7447825
],
[
-97.137207 ,
39.7444372
]
]
]
},
"properties" : {
"updated" : "2023-07-13T05:39:07+00:00" ,
"units" : "us" ,
"forecastGenerator" : "BaselineForecastGenerator" ,
"generatedAt" : "2023-07-13T06:44:24+00:00" ,
"updateTime" : "2023-07-13T05:39:07+00:00" ,
"validTimes" : "2023-07-12T23:00:00+00:00/P7DT2H" ,
"elevation" : {
"unitCode" : "wmoUnit:m" ,
"value" : 456.8952
},
"periods" : [
{
"number" : 1 ,
"name" : "Overnight" ,
"startTime" : "2023-07-13T01:00:00-05:00" ,
"endTime" : "2023-07-13T06:00:00-05:00" ,
"isDaytime" : false ,
"temperature" : 68 ,
"temperatureUnit" : "F" ,
"temperatureTrend" : null ,
"probabilityOfPrecipitation" : {
"unitCode" : "wmoUnit:percent" ,
"value" : null
},
"dewpoint" : {
"unitCode" : "wmoUnit:degC" ,
"value" : 21.666666666666668
},
"relativeHumidity" : {
"unitCode" : "wmoUnit:percent" ,
"value" : 100
},
"windSpeed" : "5 mph" ,
"windDirection" : "NE" ,
"icon" : "https://api.weather.gov/icons/land/night/few?size=medium" ,
"shortForecast" : "Mostly Clear" ,
"detailedForecast" : "Mostly clear, with a low around 68. Northeast wind around 5 mph."
},
{
"number" : 2 ,
"name" : "Thursday" ,
"startTime" : "2023-07-13T06:00:00-05:00" ,
"endTime" : "2023-07-13T18:00:00-05:00" ,
"isDaytime" : true ,
"temperature" : 90 ,
"temperatureUnit" : "F" ,
"temperatureTrend" : null ,
"probabilityOfPrecipitation" : {
"unitCode" : "wmoUnit:percent" ,
"value" : null
},
"dewpoint" : {
"unitCode" : "wmoUnit:degC" ,
"value" : 21.11111111111111
},
"relativeHumidity" : {
"unitCode" : "wmoUnit:percent" ,
"value" : 100
},
"windSpeed" : "5 to 10 mph" ,
"windDirection" : "NE" ,
"icon" : "https://api.weather.gov/icons/land/day/sct?size=medium" ,
"shortForecast" : "Mostly Sunny" ,
"detailedForecast" : "Mostly sunny, with a high near 90. Northeast wind 5 to 10 mph."
},
// ...
]
}
},
{
"@context" : [
"https://geojson.org/geojson-ld/geojson-context.jsonld" ,
{
"@version" : "1.1" ,
"wx" : "https://api.weather.gov/ontology#" ,
"geo" : "http://www.opengis.net/ont/geosparql#" ,
"unit" : "http://codes.wmo.int/common/unit/" ,
"@vocab" : "https://api.weather.gov/ontology#"
}
],
"type" : "Feature" ,
"geometry" : {
"type" : "Polygon" ,
"coordinates" : [
[
[
-96.8406778 ,
39.1956467
],
[
-96.8402904 ,
39.1735282
],
[
-96.811767 ,
39.1738261
],
[
-96.8121485 ,
39.1959446
],
[
-96.8406778 ,
39.1956467
]
]
]
},
"properties" : {
"updated" : "2023-07-13T05:39:07+00:00" ,
"units" : "us" ,
"forecastGenerator" : "BaselineForecastGenerator" ,
"generatedAt" : "2023-07-13T07:07:02+00:00" ,
"updateTime" : "2023-07-13T05:39:07+00:00" ,
"validTimes" : "2023-07-12T23:00:00+00:00/P7DT2H" ,
"elevation" : {
"unitCode" : "wmoUnit:m" ,
"value" : 403.86
},
"periods" : [
{
"number" : 1 ,
"name" : "Overnight" ,
"startTime" : "2023-07-13T02:00:00-05:00" ,
"endTime" : "2023-07-13T06:00:00-05:00" ,
"isDaytime" : false ,
"temperature" : 69 ,
"temperatureUnit" : "F" ,
"temperatureTrend" : null ,
"probabilityOfPrecipitation" : {
"unitCode" : "wmoUnit:percent" ,
"value" : null
},
"dewpoint" : {
"unitCode" : "wmoUnit:degC" ,
"value" : 22.22222222222222
},
"relativeHumidity" : {
"unitCode" : "wmoUnit:percent" ,
"value" : 97
},
"windSpeed" : "5 to 10 mph" ,
"windDirection" : "NE" ,
"icon" : "https://api.weather.gov/icons/land/night/few?size=medium" ,
"shortForecast" : "Mostly Clear" ,
"detailedForecast" : "Mostly clear, with a low around 69. Northeast wind 5 to 10 mph."
},
{
"number" : 2 ,
"name" : "Thursday" ,
"startTime" : "2023-07-13T06:00:00-05:00" ,
"endTime" : "2023-07-13T18:00:00-05:00" ,
"isDaytime" : true ,
"temperature" : 93 ,
"temperatureUnit" : "F" ,
"temperatureTrend" : null ,
"probabilityOfPrecipitation" : {
"unitCode" : "wmoUnit:percent" ,
"value" : null
},
"dewpoint" : {
"unitCode" : "wmoUnit:degC" ,
"value" : 22.22222222222222
},
"relativeHumidity" : {
"unitCode" : "wmoUnit:percent" ,
"value" : 100
},
"windSpeed" : "5 to 10 mph" ,
"windDirection" : "NE" ,
"icon" : "https://api.weather.gov/icons/land/day/sct?size=medium" ,
"shortForecast" : "Mostly Sunny" ,
"detailedForecast" : "Mostly sunny, with a high near 93. Northeast wind 5 to 10 mph."
},
// ...
]
}
}
]
}
}
Copy
Back to Mailchimp's API, let's extract the list of all the email addresses from the response. These are contained under the email_address
property on each item of the members
list:
{
"data" : {
"_sendJSONObjectItemHTTPRequest" : {
"members" : [
{
"email_address" : "vinesh@yahoo.com" ,
// ...
},
{
"email_address" : "thiago@hotmail.com" ,
// ...
},
// ...
]
}
}
}
Copy
The Field Value Iteration and Manipulation extension provides composable directives that iterate over the inner elements of arrays or objects, and apply their nested directive(s) under those elements:
@underArrayItem
: Operate on a specific item from the array
@underJSONObjectProperty
: Operate on a specific entry from the JSON object
@underEachArrayItem
: Operate on all items from the array
@underEachJSONObjectProperty
: Operate on all entries from the JSON object
This GraphQL query navigates to each of the email_address
properties, and exports their value to dynamic variable $mailchimpListMemberEmails
:
query GetDataFromMailchimp {
mailchimpListMembersJSONObject : _sendJSONObjectItemHTTPRequest ( input : {
url : "https://us7.api.mailchimp.com/3.0/lists/{LIST_ID}/members" ,
method : GET ,
options : {
auth : {
username : "{USER}" ,
password : "{API_TOKEN}"
}
}
})
@underJSONObjectProperty ( by : { key : "members" })
@underEachArrayItem
@underJSONObjectProperty ( by : { key : "email_address" })
@export ( as : "mailchimpListMemberEmails" )
}
Copy
We can visualize the entries by printing the value of the dynamic variable:
query PrintMailchimpSubscriberEmails
@depends ( on : "GetDataFromMailchimp" )
{
mailchimpListMemberEmails : _echo ( value : $mailchimpListMemberEmails )
}
Copy
...producing:
{
"data" : {
"mailchimpListMembersJSONObject" : {
// ...
},
"mailchimpListMemberEmails" : [
"vinesh@yahoo.com" ,
"thiago@hotmail.com" ,
// ...
]
}
}
Copy
Notice that, even though dynamic variable $mailchimpListMemberEmails
is a list, @export
does not have argument type: LIST
.
This is because whenever @export
is nested below @underEachArrayItem
(or @underEachJSONObjectProperty
), the exported value will already be an array .
Let's say that our Mailchimp subscribers also have a user in our website, and that their email address is the common ID for both applications.
We can then use the email addresses retrieved from Mailchimp (by now placed under dynamic variable $mailchimpListMemberEmails
) to fetch the corresponding user data stored in our site:
query GetUsersUsingMailchimpSubscriberEmails
@depends ( on : "GetDataFromMailchimp" )
{
users ( filter : { searchBy : { emails : $mailchimpListMemberEmails } } ) {
id
name
email
}
}
Copy
The response will be:
{
"data" : {
"mailchimpListMembersJSONObject" : {
// ...
},
"users" : [
{
"id" : 88 ,
"name" : "Vinesh Munak" ,
"email" : "vinesh@yahoo.com"
},
{
"id" : 705 ,
"name" : "Thiago Barbossa" ,
"email" : "thiago@hotmail.com"
}
]
}
}
Copy
Having retrieved the users, we can apply any desired operation on them (execute a mutation to update their data, send an email, etc).