Solidus
Search…
GraphQL API

GraphQL integration

GraphQL provides a query language that allows clients to ask a GraphQL-enabled server for data in whichever shape and structure it needs to consume. The Solidus team officially supports solidus_graphql_api, an extension adding a GraphQL endpoint to the application.
To use the GraphQL extension, you have to add it to the Gemfile:
1
gem 'solidus_graphql_api'
Copied!
After that, remember to run:
1
bundle
Copied!
Once done, and after (re)starting the rails server, you'll have a new route POST /graphql ready to answer your GraphQL queries. E.g.:
1
curl -X POST --data '{ "query": "{ currentStore { name } } "}' -H "Content-Type: application/json" http://localhost:3000/graphql
Copied!

Solidus' GraphQL playground

We have a dedicated playground that you can use to learn how to use the GraphQL endpoint on Solidus. It uses the data on Solidus' demo application as the backend.
You can click on the Docs tab on the playground to look at the GraphQL schema and discover all the queries and mutations you can perform. If you prefer, you can check the extension's documentation page instead.
Some of the operations require that you add a header to the request. Look for the Set Headers icon on the playground site.

Demo walkthrough

We're going to walk through a typical flow when interacting with a Solidus storefront. It will help you get familiar with GraphQL on Solidus. You can use our playground as a development platform.
You can use the playground to test all the points except for the Authenticated users section. That's because the demo application uses an on-the-fly user, which is not persisted in the database. For that section, you should use your own application.
For the same reason, understand that the changes you made here won't be visible if you visit http://demo.solidus.io in the browser, and vice-versa. Both requests are associated with different visitors; therefore, no data will be shared between them.

Listing products

One of the core information you need to present to the customers is what products are available to buy. As you might have a lot, probably it's a good idea to paginate them. Solidus' GraphQL works with Relay's cursor-based pagination, where each item gets a unique cursor that you use to get following or previous records. For instance, when implementing forward pagination for products, your first query would look something like the following:
GraphQL
Response
1
query listProducts {
2
products(first: 5) {
3
nodes {
4
name
5
slug
6
masterVariant {
7
defaultPrice {
8
amount
9
currency {
10
htmlEntity
11
}
12
}
13
images {
14
nodes {
15
smallUrl
16
}
17
}
18
}
19
}
20
pageInfo {
21
endCursor
22
hasNextPage
23
}
24
}
25
}
Copied!
1
{
2
"data": {
3
"products": {
4
"nodes": [
5
{
6
"name": "Solidus T-Shirt",
7
"slug": "solidus-t-shirt",
8
"masterVariant": {
9
"defaultPrice": {
10
"amount": "19.99",
11
"currency": {
12
"htmlEntity": "quot;
13
}
14
},
15
"images": {
16
"nodes": [
17
{
18
"smallUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/39/small/solidus_tshirt.jpg"
19
},
20
{
21
"smallUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/40/small/solidus_tshirt_back.jpg"
22
}
23
]
24
}
25
}
26
},
27
{
28
"name": "Solidus Long Sleeve",
29
"slug": "solidus-long-sleeve",
30
"masterVariant": {
31
"defaultPrice": {
32
"amount": "19.99",
33
"currency": {
34
"htmlEntity": "quot;
35
}
36
},
37
"images": {
38
"nodes": [
39
{
40
"smallUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/41/small/solidus_long.jpg"
41
},
42
{
43
"smallUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/42/small/solidus_long_back.jpg"
44
}
45
]
46
}
47
}
48
},
49
{
50
"name": "Solidus Girly",
51
"slug": "solidus-girly",
52
"masterVariant": {
53
"defaultPrice": {
54
"amount": "19.99",
55
"currency": {
56
"htmlEntity": "quot;
57
}
58
},
59
"images": {
60
"nodes": [
61
{
62
"smallUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/53/small/solidus_girly.jpg"
63
}
64
]
65
}
66
}
67
},
68
{
69
"name": "Solidus Snapback Cap",
70
"slug": "solidus-snapback-cap",
71
"masterVariant": {
72
"defaultPrice": {
73
"amount": "15.99",
74
"currency": {
75
"htmlEntity": "quot;
76
}
77
},
78
"images": {
79
"nodes": [
80
{
81
"smallUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/43/small/solidus_snapback_cap.jpg"
82
}
83
]
84
}
85
}
86
},
87
{
88
"name": "Solidus Hoodie Zip",
89
"slug": "solidus-hoodie-zip",
90
"masterVariant": {
91
"defaultPrice": {
92
"amount": "29.99",
93
"currency": {
94
"htmlEntity": "quot;
95
}
96
},
97
"images": {
98
"nodes": [
99
{
100
"smallUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/44/small/solidus_hoodie.jpg"
101
}
102
]
103
}
104
}
105
}
106
],
107
"pageInfo": {
108
"endCursor": "NQ",
109
"hasNextPage": true
110
}
111
}
112
}
113
}
Copied!
Notice the first variable that is being given to the query. It limits the number of records to be fetched to 5. Also, please pay attention to the endCursor and hasNextPage fields within pageInfo as we're going to use them shortly.
Now, take a look at the Response tab. Notice that NQ value for pageInfo -> endCursor. It uniquely identifies the last received product, i.e., Solidus Hoodie Zip. On the other hand, hasNextPageis telling us that we're not done with the whole list of products. We can get the five following products giving the endCursor value to an after variable from the same query as before:
GraphQL
Response
1
query listProducts {
2
products(first: 5, after: "NQ") {
3
nodes {
4
name
5
slug
6
masterVariant {
7
defaultPrice {
8
amount
9
currency {
10
htmlEntity
11
}
12
}
13
images {
14
nodes {
15
smallUrl
16
}
17
}
18
}
19
}
20
pageInfo {
21
endCursor
22
hasNextPage
23
}
24
}
25
}
Copied!
1
{
2
"data": {
3
"products": {
4
"nodes": [
5
{
6
"name": "Ruby Hoodie",
7
"slug": "ruby-hoodie",
8
"masterVariant": {
9
"defaultPrice": {
10
"amount": "29.99",
11
"currency": {
12
"htmlEntity": "quot;
13
}
14
},
15
"images": {
16
"nodes": [
17
{
18
"smallUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/45/small/ruby_hoodie.jpg"
19
}
20
]
21
}
22
}
23
},
24
{
25
"name": "Ruby Hoodie Zip",
26
"slug": "ruby-hoodie-zip",
27
"masterVariant": {
28
"defaultPrice": {
29
"amount": "29.99",
30
"currency": {
31
"htmlEntity": "quot;
32
}
33
},
34
"images": {
35
"nodes": [
36
{
37
"smallUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/46/small/ruby_hoodie_zip.jpg"
38
}
39
]
40
}
41
}
42
},
43
{
44
"name": "Ruby Polo",
45
"slug": "ruby-polo",
46
"masterVariant": {
47
"defaultPrice": {
48
"amount": "26.99",
49
"currency": {
50
"htmlEntity": "quot;
51
}
52
},
53
"images": {
54
"nodes": [
55
{
56
"smallUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/47/small/ruby_polo.jpg"
57
},
58
{
59
"smallUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/48/small/ruby_polo_back.jpg"
60
}
61
]
62
}
63
}
64
},
65
{
66
"name": "Solidus Mug",
67
"slug": "solidus-mug",
68
"masterVariant": {
69
"defaultPrice": {
70
"amount": "9.99",
71
"currency": {
72
"htmlEntity": "quot;
73
}
74
},
75
"images": {
76
"nodes": [
77
{
78
"smallUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/49/small/solidus_mug.jpg"
79
}
80
]
81
}
82
}
83
},
84
{
85
"name": "Ruby Mug",
86
"slug": "ruby-mug",
87
"masterVariant": {
88
"defaultPrice": {
89
"amount": "9.99",
90
"currency": {
91
"htmlEntity": "quot;
92
}
93
},
94
"images": {
95
"nodes": [
96
{
97
"smallUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/50/small/ruby_mug.jpg"
98
}
99
]
100
}
101
}
102
}
103
],
104
"pageInfo": {
105
"endCursor": "MTA",
106
"hasNextPage": true
107
}
108
}
109
}
110
}
Copied!
We could repeat the process until hasNextPage would be false.
We can also implement backward pagination if we switch first & after variables for last & before, and endCursor & hasNextPage fields for startCursor & hasPreviousPage. Relay's spec for cursor-based pagination is mainly intended to be used in infinite-scroll UX and, for now, it doesn't support bidirectional pagination (when paginating forward hasPreviousPage is meaningless and vice-versa).

Displaying a product

Once we have rendered the list of products, users would typically click on the one they're interested in. We can use its slug to display the complete information. For instance, the amazing Solidus T-Shirt is really appreciated by customers:
GraphQL
Response
1
query getProduct {
2
productBySlug(slug: "solidus-t-shirt") {
3
name
4
description
5
variants {
6
nodes {
7
id
8
sku
9
position
10
prices {
11
nodes {
12
amount
13
currency {
14
htmlEntity
15
}
16
}
17
}
18
optionValues {
19
nodes {
20
name
21
presentation
22
optionType {
23
name
24
presentation
25
position
26
}
27
}
28
}
29
images {
30
nodes {
31
largeUrl
32
}
33
}
34
}
35
}
36
}
37
}
38
Copied!
1
{
2
"data": {
3
"productBySlug": {
4
"name": "Solidus T-Shirt",
5
"description": "Necessitatibus optio quod ullam itaque quis corporis occaecati. Saepe harum voluptates consectetur rerum dolorum. Corrupti officiis reprehenderit quo excepturi cumque. Soluta eos perspiciatis aut et ea nulla amet dolores. Dolores distinctio nesciunt libero voluptas molestiae consequatur aut veritatis.",
6
"variants": {
7
"nodes": [
8
{
9
"id": "U3ByZWU6OlZhcmlhbnQtMTM=",
10
"sku": "SOL-00003",
11
"position": 3,
12
"prices": {
13
"nodes": [
14
{
15
"amount": "19.99",
16
"currency": {
17
"htmlEntity": "quot;
18
}
19
}
20
]
21
},
22
"optionValues": {
23
"nodes": [
24
{
25
"name": "Small",
26
"presentation": "S",
27
"optionType": {
28
"name": "tshirt-size",
29
"presentation": "Size",
30
"position": 1
31
}
32
},
33
{
34
"name": "Blue",
35
"presentation": "Blue",
36
"optionType": {
37
"name": "tshirt-color",
38
"presentation": "Color",
39
"position": 2
40
}
41
}
42
]
43
},
44
"images": {
45
"nodes": [
46
{
47
"largeUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/1/large/solidus_tshirt_blue.png"
48
},
49
{
50
"largeUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/2/large/solidus_tshirt_back_blue.png"
51
}
52
]
53
}
54
},
55
{
56
"id": "U3ByZWU6OlZhcmlhbnQtMTQ=",
57
"sku": "SOL-00002",
58
"position": 5,
59
"prices": {
60
"nodes": [
61
{
62
"amount": "19.99",
63
"currency": {
64
"htmlEntity": "quot;
65
}
66
}
67
]
68
},
69
"optionValues": {
70
"nodes": [
71
{
72
"name": "Small",
73
"presentation": "S"
74
},
75
{
76
"name": "Small",
77
"presentation": "S"
78
},
79
{
80
"name": "Black",
81
"presentation": "Black"
82
},
83
{
84
"name": "Small",
85
"presentation": "S"
86
},
87
{
88
"name": "Black",
89
"presentation": "Black"
90
}
91
]
92
},
93
"images": {
94
"nodes": [
95
{
96
"largeUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/3/large/solidus_tshirt_black.png"
97
},
98
{
99
"largeUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/4/large/solidus_tshirt_back_black.png"
100
}
101
]
102
}
103
},
104
{
105
"id": "U3ByZWU6OlZhcmlhbnQtMTU=",
106
"sku": "SOL-00004",
107
"position": 7,
108
"prices": {
109
"nodes": [
110
{
111
"amount": "19.99",
112
"currency": {
113
"htmlEntity": "quot;
114
}
115
}
116
]
117
},
118
"optionValues": {
119
"nodes": [
120
{
121
"name": "Small",
122
"presentation": "S"
123
},
124
{
125
"name": "Small",
126
"presentation": "S"
127
},
128
{
129
"name": "Small",
130
"presentation": "S"
131
},
132
{
133
"name": "White",
134
"presentation": "White"
135
},
136
{
137
"name": "White",
138
"presentation": "White"
139
}
140
]
141
},
142
"images": {
143
"nodes": [
144
{
145
"largeUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/5/large/solidus_tshirt_white.png"
146
},
147
{
148
"largeUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/6/large/solidus_tshirt_back_white.png"
149
}
150
]
151
}
152
},
153
{
154
"id": "U3ByZWU6OlZhcmlhbnQtMTY=",
155
"sku": "SOL-00005",
156
"position": 9,
157
"prices": {
158
"nodes": [
159
{
160
"amount": "19.99",
161
"currency": {
162
"htmlEntity": "quot;
163
}
164
}
165
]
166
},
167
"optionValues": {
168
"nodes": [
169
{
170
"name": "Blue",
171
"presentation": "Blue"
172
},
173
{
174
"name": "Medium",
175
"presentation": "M"
176
},
177
{
178
"name": "Blue",
179
"presentation": "Blue"
180
},
181
{
182
"name": "Blue",
183
"presentation": "Blue"
184
}
185
]
186
},
187
"images": {
188
"nodes": [
189
{
190
"largeUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/7/large/solidus_tshirt_blue.png"
191
},
192
{
193
"largeUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/8/large/solidus_tshirt_back_blue.png"
194
}
195
]
196
}
197
},
198
{
199
"id": "U3ByZWU6OlZhcmlhbnQtMTc=",
200
"sku": "SOL-00006",
201
"position": 11,
202
"prices": {
203
"nodes": [
204
{
205
"amount": "19.99",
206
"currency": {
207
"htmlEntity": "quot;
208
}
209
}
210
]
211
},
212
"optionValues": {
213
"nodes": [
214
{
215
"name": "White",
216
"presentation": "White"
217
},
218
{
219
"name": "Large",
220
"presentation": "L"
221
},
222
{
223
"name": "White",
224
"presentation": "White"
225
},
226
{
227
"name": "Large",
228
"presentation": "L"
229
}
230
]
231
},
232
"images": {
233
"nodes": [
234
{
235
"largeUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/9/large/solidus_tshirt_white.png"
236
},
237
{
238
"largeUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/10/large/solidus_tshirt_back_white.png"
239
}
240
]
241
}
242
},
243
{
244
"id": "U3ByZWU6OlZhcmlhbnQtMTg=",
245
"sku": "SOL-00007",
246
"position": 13,
247
"prices": {
248
"nodes": [
249
{
250
"amount": "19.99",
251
"currency": {
252
"htmlEntity": "quot;
253
}
254
}
255
]
256
},
257
"optionValues": {
258
"nodes": [
259
{
260
"name": "Black",
261
"presentation": "Black"
262
},
263
{
264
"name": "Large",
265
"presentation": "L"
266
},
267
{
268
"name": "Large",
269
"presentation": "L"
270
},
271
{
272
"name": "Black",
273
"presentation": "Black"
274
}
275
]
276
},
277
"images": {
278
"nodes": [
279
{
280
"largeUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/11/large/solidus_tshirt_black.png"
281
},
282
{
283
"largeUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/12/large/solidus_tshirt_back_black.png"
284
}
285
]
286
}
287
},
288
{
289
"id": "U3ByZWU6OlZhcmlhbnQtMTk=",
290
"sku": "SOL-0008",
291
"position": 15,
292
"prices": {
293
"nodes": [
294
{
295
"amount": "19.99",
296
"currency": {
297
"htmlEntity": "quot;
298
}
299
}
300
]
301
},
302
"optionValues": {
303
"nodes": [
304
{
305
"name": "Blue",
306
"presentation": "Blue"
307
},
308
{
309
"name": "Blue",
310
"presentation": "Blue"
311
},
312
{
313
"name": "Extra Large",
314
"presentation": "XL"
315
},
316
{
317
"name": "Blue",
318
"presentation": "Blue"
319
}
320
]
321
},
322
"images": {
323
"nodes": [
324
{
325
"largeUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/13/large/solidus_tshirt_blue.png"
326
},
327
{
328
"largeUrl": "https://res.cloudinary.com/hl3m5fihu/image/upload/v1/spree/products/14/large/solidus_tshirt_back_blue.png"
329
}
330
]
331
}
332
}
333
]
334
}
335
}
336
}
337
}
Copied!
Notice that we're assuming there's not a crazy amount of product variants, nor its nested associations like prices and images. Otherwise, we could paginate those resources as we did before with products.

Adding a product to the cart

Say a visitor wants to buy two Solidus T-Shirt. Before adding the items to the cart, we need to create an order to attach the former to it. We need it so that we can group future additions and keep the state between requests.
Here comes our first GraphQL mutation. Mutations are similar to queries. By convention, they change the server's state. It's the equivalent to POST, PUT, PATCH and DELETEHTTP methods on traditional RESTful APIs.
We're going to use the createOrder mutation, and we need to make sure it returns the order's guestToken so that we can reference it back later. It's a good practice to always ask for errors in the mutation to detect any problem.
GraphQL
Response
1
mutation createOrder{
2
createOrder(input: {}) {
3
order {
4
guestToken
5
number
6
state
7
}
8
errors {
9
path
10
message
11
}
12
}
13
}
Copied!
1
{
2
"data": {
3
"createOrder": {
4
"order": {
5
"guestToken": "OQAFTjTtIYY1WjgCNyG3rw",
6
"number": "R901119678",
7
"state": "cart"
8
},
9
"errors": []
10
}
11
}
12
}
Copied!
Once we have the token, we need to set it as the value of a X-Spree-Order-Tokenrequest header. It's going to authenticate the request as coming from the same guest user.
We also need the id of the variant we want to add to the cart. If you look at the response for the product query, you'll see that if we chose the blue/small variant, its identifier corresponds to U3ByZWU6OlZhcmlhbnQtMTM=.
GraphQL
Response
1
mutation addToCart {
2
addToCart(input: { variantId: "U3ByZWU6OlZhcmlhbnQtMTM=", quantity: 2}) {
3
order {
4
number
5
state
6
itemTotal
7
total
8
lineItems {
9
nodes {
10
amount
11
price
12
currency
13
quantity
14
variant {
15
id
16
}
17
hasSufficientStock
18
}
19
}
20
}
21
errors {
22
path
23
message
24
}
25
}
26
}
Copied!
1
{
2
"data": {
3
"addToCart": {
4
"order": {
5
"number": "R901119678",
6
"state": "cart",
7
"itemTotal": "50.0",
8
"total": "50.0",
9
"lineItems": {
10
"nodes": [
11
{
12
"amount": 50,
13
"price": 25,
14
"currency": "USD",
15
"quantity": 2,
16
"variant": {
17
"id": "U3ByZWU6OlZhcmlhbnQtMTM="
18
},
19
"hasSufficientStock": true
20
}
21
]
22
}
23
},
24
"errors": []
25
}
26
}
27
}
Copied!
We could repeat the process for other items if needed.

Checkout 1 - Billing & shipping addresses

Once we're done adding items to the cart, we need to transition the checkout process to the next state:
GraphQL
Response
1
mutation checkoutNextFromCart {
2
nextCheckoutState(input: {}) {
3
order {
4
number
5
state
6
}
7
errors {
8
path
9
message
10
}
11
}
12
}
Copied!
1
{
2
"data": {
3
"nextCheckoutState": {
4
"order": {
5
"number": "R901119678",
6
"state": "address"
7
},
8
"errors": []
9
}
10
}
11
}
Copied!
Notice that the state changed from cart to address. That means we need to do a couple of things: associate an email to the order and set the user's shipping & billing addresses.
Let's go first with the email address:
GraphQL
Response
1
mutation checkoutEmail {
2
setOrderEmail(input: { email: "[email protected]"} ) {
3
order {
4
number
5
state
6
email
7
}
8
}
9
}
Copied!
1
{
2
"data": {
3
"setOrderEmail": {
4
"order": {
5
"number": "R901119678",
6
"state": "address",
7
"email": "[email protected]"
8
}
9
}
10
}
11
}
Copied!
All good. Before going with the addresses, we need to fetch country and state ids from our system. Here we have the list of countries:
GraphQL
Response
1
query countries {
2
countries {
3
nodes {
4
id
5
name
6
}
7
}
8
}
Copied!
1
{
2
"data": {
3
"countries": {
4
"nodes": [
5
{
6
"id": "U3ByZWU6OkNvdW50cnktMQ==",
7
"name": "Andorra"
8
},
9
{
10
"id": "U3ByZWU6OkNvdW50cnktMg==",
11
"name": "United Arab Emirates"
12
},
13
{
14
"id": "U3ByZWU6OkNvdW50cnktMw==",
15
"name": "Afghanistan"
16
},
17
{
18
"id": "U3ByZWU6OkNvdW50cnktNA==",
19
"name": "Antigua and Barbuda"
20
},
21
{
22
"id": "U3ByZWU6OkNvdW50cnktNQ==",
23
"name": "Anguilla"
24
},
25
{
26
"id": "U3ByZWU6OkNvdW50cnktNg==",
27
"name": "Albania"
28
},
29
{
30
"id": "U3ByZWU6OkNvdW50cnktNw==",
31
"name": "Armenia"
32
},
33
{
34
"id": "U3ByZWU6OkNvdW50cnktOA==",
35
"name": "Angola"
36
},
37
{
38
"id": "U3ByZWU6OkNvdW50cnktOQ==",
39
"name": "Antarctica"
40
},
41
{
42
"id": "U3ByZWU6OkNvdW50cnktMTA=",
43
"name": "Argentina"
44
},
45
{
46
"id": "U3ByZWU6OkNvdW50cnktMTE=",
47
"name": "American Samoa"
48
},
49
{
50
"id": "U3ByZWU6OkNvdW50cnktMTI=",
51
"name": "Austria"
52
},
53
{
54
"id": "U3ByZWU6OkNvdW50cnktMTM=",
55
"name": "Australia"
56
},
57
{
58
"id": "U3ByZWU6OkNvdW50cnktMTQ=",
59
"name": "Aruba"
60
},
61
{
62
"id": "U3ByZWU6OkNvdW50cnktMTU=",
63
"name": "Åland Islands"
64
},
65
{
66
"id": "U3ByZWU6OkNvdW50cnktMTY=",
67
"name": "Azerbaijan"
68
},
69
{
70
"id": "U3ByZWU6OkNvdW50cnktMTc=",
71
"name": "Bosnia and Herzegovina"
72
},
73
{
74
"id": "U3ByZWU6OkNvdW50cnktMTg=",
75
"name": "Barbados"
76
},
77
{
78
"id": "U3ByZWU6OkNvdW50cnktMTk=",
79
"name": "Bangladesh"
80
},
81
{
82
"id": "U3ByZWU6OkNvdW50cnktMjA=",
83
"name": "Belgium"
84
},
85
{
86
"id": "U3ByZWU6OkNvdW50cnktMjE=",
87
"name": "Burkina Faso"
88
},
89
{
90
"id": "U3ByZWU6OkNvdW50cnktMjI=",
91
"name": "Bulgaria"
92
},
93
{
94
"id": "U3ByZWU6OkNvdW50cnktMjM=",
95
"name": "Bahrain"
96
},
97
{
98
"id": "U3ByZWU6OkNvdW50cnktMjQ=",
99
"name": "Burundi"
100
},
101
{
102
"id": "U3ByZWU6OkNvdW50cnktMjU=",
103
"name": "Benin"
104
},
105
{
106
"id": "U3ByZWU6OkNvdW50cnktMjY=",
107
"name": "Saint Barthélemy"
108
},
109
{
110
"id": "U3ByZWU6OkNvdW50cnktMjc=",
111
"name": "Bermuda"
112
},
113
{
114
"id": "U3ByZWU6OkNvdW50cnktMjg=",
115
"name": "Brunei Darussalam"
116
},
117
{
118
"id": "U3ByZWU6OkNvdW50cnktMjk=",
119
"name": "Bolivia, Plurinational State of"
120
},
121
{
122
"id": "U3ByZWU6OkNvdW50cnktMzA=",
123
"name": "Bonaire, Sint Eustatius and Saba"
124
},
125
{
126
"id": "U3ByZWU6OkNvdW50cnktMzE=",
127
"name": "Brazil"
128
},
129
{
130
"id": "U3ByZWU6OkNvdW50cnktMzI=",
131
"name": "Bahamas"
132
},
133
{
134
"id": "U3ByZWU6OkNvdW50cnktMzM=",
135
"name": "Bhutan"
136
},
137
{
138
"id": "U3ByZWU6OkNvdW50cnktMzQ=",
139
"name": "Bouvet Island"
140
},
141
{
142
"id": "U3ByZWU6OkNvdW50cnktMzU=",
143
"name": "Botswana"
144
},
145
{
146
"id": "U3ByZWU6OkNvdW50cnktMzY=",
147
"name": "Belarus"
148
},
149
{
150
"id": "U3ByZWU6OkNvdW50cnktMzc=",
151
"name": "Belize"
152
},
153
{
154
"id": "U3ByZWU6OkNvdW50cnktMzg=",
155
"name": "Canada"
156
},
157
{
158
"id": "U3ByZWU6OkNvdW50cnktMzk=",
159
"name": "Cocos (Keeling) Islands"
160
},
161
{
162
"id": "U3ByZWU6OkNvdW50cnktNDA=",
163
"name": "Congo, The Democratic Republic of the"
164
},
165
{
166
"id": "U3ByZWU6OkNvdW50cnktNDE=",
167
"name": "Central African Republic"
168
},
169
{
170
"id":