AWS Builder Center
Tap Into the Rift ๐ŸŽฏ - Building Your First Riot Games API Integration

Tap Into the Rift ๐ŸŽฏ - Building Your First Riot Games API Integration

Connect Your Project to Real League Data Like a Pro

Sr. Solutions Architect, Games
Welcome to Day 6 of the Riot Games Rift Rewind Developer Challenge! Today you'll learn how to build a feature that connects to the Riot Games API to fetch and display real League of Legends data. This is where your project gets truly interactive and showcases real technical skills.
In about 60 minutes, you will learn why API integrations need more than just JavaScript, how to run code securely in the cloud, and how to connect your frontend to external services. We're not just adding a feature, we're learning how modern applications fetch and display live data.
By the end of today, you'll have a working Riot API integration that follows professional practices. Time to connect to the Rift!

What You Will Accomplish Today

โœ… Understand how API calls work and why they need backend services
โœ… Learn how to run code securely in the cloud with API keys
โœ… Set up your Riot Developer account and API key
โœ… Configure secure permissions for API calls
โœ… Add a live League data feature to your project

What You Will Need

  • Your AWS account from Day 1 ๐Ÿ’ป
  • Your Amplify project from Day 5 ๐ŸŒ
  • About 60 minutes of your time โฐ
  • Riot Developer account for API access ๐Ÿ”‘

Step 1: What Happens When You Call an API? ๐Ÿคทโ€โ™€๏ธ

Picture this: someone visits your project, enters a Riot ID, clicks "Look Up Stats" and... then what? If you're thinking "champion mastery data magically appears," there's actually a whole technical journey happening behind the scenes.
JavaScript running in the browser can make API calls, but it can't securely store API keys or handle sensitive operations. Those need to happen on a server. Think of browser JavaScript as the messenger that asks servers to do the secure tasks.

Client-Server API Flow

Here's what actually happens when someone requests League data:
  1. JavaScript packages the request and sends it to your backend function
  2. Server receives the request and makes the secure API call to Riot Games using your private API key
  3. Riot API responds with the requested data (or an error)
  4. Server processes and returns the data to your JavaScript
  5. JavaScript updates the page with the League data
This isn't just League lookups, it's a fundamental pattern behind every API integration. Weather apps, stock tickers, social media feeds: they all follow this same secure client-server process.

Why Not Call Riot API Directly from JavaScript?

  • Security: API keys should never be exposed in browser code where anyone can see them
  • CORS: Most APIs (including Riot's) don't allow direct browser calls for security reasons
  • Rate Limiting: Server-side calls can implement proper rate limiting and caching
  • Error Handling: Servers can handle API failures gracefully and provide fallbacks
Understanding this pattern is crucial for modern web development. The skills you learn building this Riot API integration apply to every external service integration you'll ever build.

Step 2: Get Your Riot Developer API Key ๐Ÿ”‘

To access League data, you need to register as a Riot Developer and get an API key. This key authenticates your requests and lets you access live game data.

Register for Riot Developer Portal

  1. Go to Riot Developer Portal - Visit developer.riotgames.com
  2. Sign in with your Riot Account - Use your existing Riot Games account (or create one)
  3. Accept Developer Terms - Read and accept the Riot Games API Terms of Service
  4. Get your API key:
    • Navigate to your dashboard
    • You'll see "Development API Key" with a "REGENERATE API KEY" button
    • Copy this key and save it securely (it expires every 24 hours for personal keys)
For production apps, you'd apply for a production key, but the personal key works great for learning.
Important: Never commit your API key to GitHub or expose it in client-side code. We'll store it securely in AWS.

Understanding Rate Limits

Riot APIs have rate limits to ensure fair usage:
  • Personal API Key: 20 requests per second, 100 requests every 2 minutes
  • Production Keys: Higher limits based on your application
Our serverless function will respect these limits and handle errors gracefully.

About Riot IDs

Riot Games now uses Riot IDs in the format GameName#TAG (like "Hide on bush#KR1"). This replaced the old summoner name system. Your integration will need to handle this format.

Step 3: Configure Secure API Key Storage ๐Ÿ”

Now we need to store your Riot API key securely in AWS. Never hardcode API keys in your Lambda function code - instead, we'll use AWS Systems Manager Parameter Store for secure storage.

Store Your API Key Securely

  1. Navigate to Systems Manager - In the AWS Console, search for "Systems Manager" and click on it
  2. Go to Parameter Store:
    • In the left sidebar, click "Parameter Store"
    • Click "Create parameter"
  3. Configure the parameter:
    • Name: /rift-rewind/riot-api-key
    • Description: "Riot Games API key for League data integration"
    • Tier: Standard
    • Type: SecureString (this encrypts your API key)
    • Value: Paste your Riot API key here
  4. Click "Create parameter"
You'll know you're done when you see "Create parameter request succeeded" at the top.

Create Permissions Policy

We need to give our Lambda function permission to read the encrypted API key.
  1. Go to IAM - Search for "IAM" in the AWS Console
  2. Create policy - Click "Policies" โ†’ "Create policy"
  3. Configure permissions:
    • Service: Systems Manager
    • Actions: Search for and select GetParameter
    • Resources: Click "Specific" โ†’ "Add ARN"
    • ARN: Enter arn:aws:ssm:*:*:parameter/rift-rewind/riot-api-key
    • Click "Add ARNs" then "Next"
  4. Policy details:
    • Name: RiotAPIKeyAccess
    • Click "Create policy"

Create Lambda Execution Role

  1. Create role - In IAM, click "Roles" โ†’ "Create role"
  2. Set it up:
    • Trusted entity type: "AWS service"
    • Use case: "Lambda"
    • Click "Next"
  3. Add permissions - Select these policies:
    • AWSLambdaBasicExecutionRole (for logging)
    • RiotAPIKeyAccess (the policy we just created)
  4. Finish:
    • Role name: riot-api-lambda-role
    • Description: "Allows Lambda to access Riot API key and write logs"
    • Click "Create role"

Step 4: Write the Riot API Integration Code โšก

Now let's create the Lambda function that will securely call the Riot API and return League data to your frontend.

Create Your Lambda Function

  1. Navigate to Lambda - Search for "Lambda" in the AWS Console
  2. Create function:
    • Click "Create a function"
    • Choose "Author from scratch"
    • Function name: riot-api-function
    • Runtime: "Python 3.13"
    • Execution role: Use existing role โ†’ riot-api-lambda-role
    • Click "Create function"

Add the Riot API Code

Replace the default code with this updated Riot API integration that uses the current Riot ID system:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import json
import boto3
import urllib3
from urllib.parse import quote

def lambda_handler(event, context):
"""
Fetches champion mastery data for a summoner using Riot ID.
Expected input: {"summonerName": "GameName#TAG", "region": "na1"}
"""

try:
# Parse the request
body = json.loads(event['body'])
summoner_name = body.get('summonerName', '').strip()
region = body.get('region', 'na1')

# Validate input
if not summoner_name:
return {
'statusCode': 400,
'body': json.dumps({'error': 'Summoner name is required'})
}

# Validate Riot ID format
if '#' not in summoner_name:
return {
'statusCode': 400,
'body': json.dumps({'error': 'Please use Riot ID format: GameName#TAG (e.g., Hide on bush#KR1)'})
}

# Get API key from Parameter Store
ssm = boto3.client('ssm')
parameter = ssm.get_parameter(
Name='/rift-rewind/riot-api-key',
WithDecryption=True
)
api_key = parameter['Parameter']['Value']

# Initialize HTTP client
http = urllib3.PoolManager()
headers = {'X-Riot-Token': api_key}

# Step 1: Get account PUUID using Riot ID
game_name, tag_line = summoner_name.split('#', 1)
game_name = quote(game_name)
tag_line = quote(tag_line)

routing_value = get_routing_value(region)
account_url = f"https://{routing_value}.api.riotgames.com/riot/account/v1/accounts/by-riot-id/{game_name}/{tag_line}"

account_response = http.request('GET', account_url, headers=headers)

if account_response.status == 404:
return {
'statusCode': 404,
'body': json.dumps({'error': 'Riot ID not found. Check spelling and region.'})
}
elif account_response.status != 200:
return {
'statusCode': account_response.status,
'body': json.dumps({'error': f'Failed to fetch account: {account_response.status}'})
}

account_data = json.loads(account_response.data.decode('utf-8'))
puuid = account_data['puuid']

# Step 2: Get summoner data by PUUID
summoner_url = f"https://{region}.api.riotgames.com/lol/summoner/v4/summoners/by-puuid/{puuid}"
summoner_response = http.request('GET', summoner_url, headers=headers)

if summoner_response.status != 200:
return {
'statusCode': 500,
'body': json.dumps({'error': 'Failed to fetch summoner data'})
}

summoner_data = json.loads(summoner_response.data.decode('utf-8'))

# Step 3: Get champion mastery data
mastery_url = f"https://{region}.api.riotgames.com/lol/champion-mastery/v4/champion-masteries/by-puuid/{puuid}/top?count=3"
mastery_response = http.request('GET', mastery_url, headers=headers)

mastery_data = []
if mastery_response.status == 200:
mastery_data = json.loads(mastery_response.data.decode('utf-8'))

# Format response
response_data = {
'summoner': {
'name': account_data['gameName'] + '#' + account_data['tagLine'],
'level': summoner_data['summonerLevel'],
'puuid': puuid
},
'topChampions': mastery_data[:3]
}

return {
'statusCode': 200,
'body': json.dumps(response_data)
}

except Exception as e:
print(f"Error: {str(e)}")
import traceback
traceback.print_exc()
return {
'statusCode': 500,
'body': json.dumps({'error': 'Internal server error'})
}

def get_routing_value(region):
"""Map platform region to routing value for Riot ID API"""
routing_map = {
'na1': 'americas',
'br1': 'americas',
'la1': 'americas',
'la2': 'americas',
'euw1': 'europe',
'eun1': 'europe',
'tr1': 'europe',
'ru': 'europe',
'kr': 'asia',
'jp1': 'asia',
'oc1': 'sea',
'ph2': 'sea',
'sg2': 'sea',
'th2': 'sea',
'tw2': 'sea',
'vn2': 'sea'
}
return routing_map.get(region, 'americas')
Key changes from the original code:
  • Uses Riot ID format (GameName#TAG) instead of deprecated summoner name
  • Calls the account API first to get PUUID
  • Then uses PUUID to get summoner and mastery data
  • Removed CORS headers (handled by Function URL configuration)
  • Added URL encoding for special characters in Riot IDs
  • Added better error handling and validation

Deploy the Function

  1. After pasting the code, click the Deploy button near the top of the code editor
  2. Wait for the "Changes deployed" message to appear
You'll know you're done when you see a green success message saying "Changes deployed" and your code is visible in the editor.

Step 5: Create a Function URL ๐ŸŒ

Your Riot API function exists, but how does your webpage call it? We need to create a public endpoint.

Creating the Function URL

  1. Create:
    • In your Lambda function, go to "Configuration" โ†’ "Function URL"
    • Click "Create function URL"
  2. Auth type: NONE (allows public access)
  3. Configure CORS:
    • Additional settings: Expand this section
    • Configure CORS: Check this option
    • Allow origin: Your Amplify website's domain (see instructions below)
    • Allow headers: Content-Type
    • Allow methods: POST
  4. Save
  5. Copy the Function URL - This is your API endpoint (looks like https://abc123.lambda-url.us-east-1.on.aws)

Finding Your Amplify Domain

This is critical - the CORS origin must match your Amplify domain exactly:
  1. Go to AWS Amplify Console
  2. Click on your app (rift-rewind-project or whatever you named it)
  3. Your domain is shown near the top of the page (looks like https://main.d1a2b3c4d5e6f7.amplifyapp.com)
  4. Copy the ENTIRE URL including https:// - do not add a trailing slash
  5. Paste it into the "Allow origin" field in the CORS configuration above
Example: If your Amplify domain is https://main.d1a2b3c4d5e6f7.amplifyapp.com, that's exactly what you enter - not d1a2b3c4d5e6f7.amplifyapp.com or https://main.d1a2b3c4d5e6f7.amplifyapp.com/
Important: The CORS configuration here is what allows your website to call this function. We don't need CORS headers in the Lambda response because the Function URL handles it. This prevents the 403 Forbidden errors that occurred in the original version.

Step 6: Add League Data Lookup to Your Project ๐Ÿ“

Now let's add the League data lookup feature to your project. Since your project is connected to GitHub, you can edit directly in your browser.

Edit Your Project Files

Go to your GitHub repository and press the . (period) key, OR change github.com to github.dev in your URL to open the web-based VS Code editor.

Add the League Lookup Section

Add this League data lookup section to your index.html file before the closing </main> tag:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<!-- LEAGUE DATA LOOKUP SECTION -->
<section class="league-lookup">
<h3>League Data Lookup</h3>
<p>Enter a Riot ID to see their level and top champions!</p>

<!-- Lookup message container for success/error messages -->
<div id="lookup-message" class="lookup-message" style="display: none;"></div>

<div class="lookup-form-container">
<!-- Riot ID lookup form -->
<div class="form-group">
<label for="summoner-name">Riot ID</label>
<input type="text" id="summoner-name" name="summoner-name" placeholder="GameName#TAG (e.g., Hide on bush#KR1)" required>
<small style="color: #687078; display: block; margin-top: 4px;">Format: GameName#TAG</small>
</div>
<div class="form-group">
<label for="region">Region</label>
<select id="region" name="region">
<option value="na1">North America</option>
<option value="euw1">Europe West</option>
<option value="eun1">Europe Nordic & East</option>
<option value="kr">Korea</option>
<option value="br1">Brazil</option>
<option value="la1">Latin America North</option>
<option value="la2">Latin America South</option>
<option value="oc1">Oceania</option>
<option value="tr1">Turkey</option>
<option value="ru">Russia</option>
<option value="jp1">Japan</option>
</select>
</div>
<!-- Lookup submit button -->
<button type="button" id="lookup-btn" class="lookup-submit-btn">Look Up Summoner</button>
</div>

<!-- Results display area -->
<div id="summoner-results" class="summoner-results" style="display: none;">
<h4>Summoner Info</h4>
<div id="summoner-info"></div>
<div id="champion-mastery"></div>
</div>
</section>
<!-- END LEAGUE DATA LOOKUP SECTION -->

Add the JavaScript

Add this script before the closing </body> tag:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<script>
// League Data Lookup - Calls Riot API via Lambda
const RIOT_API_URL = 'YOUR_LAMBDA_FUNCTION_URL_HERE'; // Replace with your Function URL

document.addEventListener('DOMContentLoaded', function() {
const lookupBtn = document.getElementById('lookup-btn');
const summonerNameInput = document.getElementById('summoner-name');
const regionSelect = document.getElementById('region');

lookupBtn.addEventListener('click', async function() {
const summonerName = summonerNameInput.value.trim();
const region = regionSelect.value;
const messageDiv = document.getElementById('lookup-message');
const resultsDiv = document.getElementById('summoner-results');

if (!summonerName) {
showMessage('Please enter a Riot ID', 'error');
return;
}

if (!summonerName.includes('#')) {
showMessage('Please use Riot ID format: GameName#TAG', 'error');
return;
}

// Show loading state
lookupBtn.textContent = 'Looking up...';
lookupBtn.disabled = true;
messageDiv.style.display = 'none';
resultsDiv.style.display = 'none';

try {
const response = await fetch(RIOT_API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
summonerName: summonerName,
region: region
})
});

const data = await response.json();

if (response.ok) {
displaySummonerData(data);
showMessage('Summoner found!', 'success');
} else {
showMessage(data.error || 'Failed to fetch summoner data', 'error');
}
} catch (error) {
console.error('Error:', error);
showMessage('Network error. Please try again.', 'error');
}

// Reset button
lookupBtn.textContent = 'Look Up Summoner';
lookupBtn.disabled = false;
});

// Enter key support
summonerNameInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
lookupBtn.click();
}
});
});

function displaySummonerData(data) {
const resultsDiv = document.getElementById('summoner-results');
const summonerInfo = document.getElementById('summoner-info');
const championMastery = document.getElementById('champion-mastery');

// Display summoner info
summonerInfo.innerHTML = `
<div class="summoner-card">
<h5>${data.summoner.name}</h5>
<p>Level: ${data.summoner.level}</p>
</div>
`
;

// Display top champions
if (data.topChampions && data.topChampions.length > 0) {
const championsHtml = data.topChampions.map(champ => `
<div class="champion-card">
<p><strong>Champion ID:</strong> ${champ.championId}</p>
<p><strong>Mastery Level:</strong> ${champ.championLevel}</p>
<p><strong>Mastery Points:</strong> ${champ.championPoints.toLocaleString()}</p>
</div>
`
).join('');

championMastery.innerHTML = `
<h5>Top Champions</h5>
<div class="champions-grid">
${championsHtml}
</div>
`
;
} else {
championMastery.innerHTML = '<p>No champion mastery data found.</p>';
}

resultsDiv.style.display = 'block';
}

function showMessage(text, type) {
const messageDiv = document.getElementById('lookup-message');
messageDiv.textContent = text;
messageDiv.className = `lookup-message ${type}`;
messageDiv.style.display = 'block';

// Auto-hide after 10 seconds
setTimeout(() => {
messageDiv.style.display = 'none';
}, 10000);
}
</script>

Add the CSS Styles

Add these styles to your styles.css file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/* LEAGUE LOOKUP STYLES */
.league-lookup {
background: white;
border-radius: 8px;
padding: 40px;
margin-top: 40px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.league-lookup h3 {
color: #232f3e;
font-size: 32px;
font-weight: 700;
margin-bottom: 16px;
text-align: center;
}

.league-lookup > p {
font-size: 16px;
color: #687078;
margin-bottom: 32px;
text-align: center;
}

.lookup-form-container {
max-width: 500px;
margin: 0 auto 32px;
}

.lookup-message {
padding: 12px 16px;
border-radius: 6px;
margin-bottom: 24px;
font-weight: 500;
text-align: center;
}

.lookup-message.success {
background: #dcfce7;
color: #166534;
border: 1px solid #bbf7d0;
}

.lookup-message.error {
background: #fef2f2;
color: #dc2626;
border: 1px solid #fecaca;
}

.form-group {
margin-bottom: 20px;
}

.form-group label {
display: block;
font-weight: 600;
color: #232f3e;
margin-bottom: 8px;
}

.form-group input,
.form-group select {
width: 100%;
padding: 12px 16px;
border: 1px solid #e5e7eb;
border-radius: 6px;
font-size: 16px;
background: #f8fafc;
}

.form-group input:focus,
.form-group select:focus {
outline: none;
border-color: #c89b3c;
background: white;
box-shadow: 0 0 0 3px rgba(200, 155, 60, 0.1);
}

.lookup-submit-btn {
background: #c89b3c;
color: white;
padding: 12px 32px;
border: none;
border-radius: 6px;
font-weight: 500;
font-size: 16px;
cursor: pointer;
transition: all 0.2s ease;
display: block;
margin: 0 auto;
}

.lookup-submit-btn:hover {
background: #b8862e;
transform: translateY(-1px);
}

.lookup-submit-btn:disabled {
background: #9ca3af;
cursor: not-allowed;
transform: none;
}

/* Results display */
.summoner-results {
max-width: 600px;
margin: 0 auto;
background: #f8fafc;
border-radius: 8px;
padding: 24px;
}

.summoner-card {
background: white;
border-radius: 6px;
padding: 20px;
margin-bottom: 20px;
text-align: center;
}

.summoner-card h5 {
color: #c89b3c;
font-size: 24px;
margin-bottom: 8px;
}

.champions-grid {
display: grid;
gap: 16px;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

.champion-card {
background: white;
border-radius: 6px;
padding: 16px;
border-left: 4px solid #c89b3c;
}

.champion-card p {
margin: 4px 0;
font-size: 14px;
}

@media (max-width: 768px) {
.league-lookup {
padding: 24px;
}

.champions-grid {
grid-template-columns: 1fr;
}
}
/* END LEAGUE LOOKUP STYLES */

Deploy Your Changes

  1. Replace YOUR_LAMBDA_FUNCTION_URL_HERE with your actual Lambda Function URL from Step 5
  2. Commit your changes:
    • Add a commit message like "Add Riot API integration with Riot ID support"
    • Click "Commit changes"
  3. Amplify automatically deploys your updates in 2-3 minutes

Step 7: Test Your Riot API Integration ๐Ÿงช

Let's make sure everything works end-to-end with real League data.

Test the Integration

  1. Visit your project - Go to your Amplify website and scroll down to the League Data Lookup section
  2. Try a lookup:
    • Enter your own Riot ID (find it in your League of Legends client: Profile โ†’ Riot ID)
    • Or try a test Riot ID in the format GameName#TAG
    • Select the correct region
    • Click "Look Up Summoner"
  3. Check it worked:
    • You should see summoner level and top champions displayed
    • The data should be current and accurate
    • Try different Riot IDs and regions
Note about test accounts: Professional player Riot IDs and tags may change over time. If example Riot IDs from guides don't work, use your own Riot ID from your League of Legends client (Profile โ†’ Riot ID shows it in the format GameName#TAG).

Troubleshooting Common Issues

"Please use Riot ID format" error:
  • Make sure you're using the GameName#TAG format (with the # symbol)
  • Example: PlayerName#NA1, not just PlayerName
  • The format is case-sensitive
"Riot ID not found" error:
  • Double-check the Riot ID spelling (case-sensitive)
  • Verify the TAG matches the account (NA1, EUW, KR1, etc.)
  • Make sure the region selector matches where the account is located
  • Try looking up your own Riot ID from your League client to verify the format
403 Forbidden error:
  • Check that your Function URL CORS configuration includes your Amplify domain
  • Verify the Amplify domain is copied exactly including https:// with no trailing slash
  • Make sure your API key hasn't expired (regenerate if needed)
  • Confirm the Function URL is correctly copied into your JavaScript
Network errors or CORS issues:
  • Verify your Lambda Function URL is correct in the JavaScript
  • Check that the Function URL CORS "Allow origin" matches your Amplify domain exactly
  • Open browser developer console (F12) to see detailed error messages
  • Look for CORS-related errors in the console
No data displaying:
  • Check CloudWatch logs in your Lambda function's Monitor tab
  • Look for errors in the browser console (F12)
  • Ensure your Riot API key is valid and not expired
  • Verify the Parameter Store parameter name is exactly /rift-rewind/riot-api-key
Rate limit errors (429 status):
  • Personal API keys have low rate limits (20/sec, 100/2min)
  • Wait a minute between requests
  • Consider adding caching for production applications
  • Don't repeatedly test with the same Riot ID
"Internal server error" message:
  • Check CloudWatch logs for detailed error information
  • Verify all three API calls in the Lambda function are working
  • Make sure the routing value function is correctly mapping your region

Checklist โœ…

Check the items below to make sure you have completed today's challenge:
  • [ ] Created Riot Developer account and obtained API key
  • [ ] Stored API key securely in AWS Parameter Store
  • [ ] Created IAM execution role with proper permissions
  • [ ] Created Lambda function with updated Riot ID API integration code
  • [ ] Deployed the Lambda function successfully
  • [ ] Configured Function URL with correct CORS settings (matching Amplify domain)
  • [ ] Added League data lookup feature to your project with Riot ID support
  • [ ] Added JavaScript to handle API calls and display results
  • [ ] Added CSS styling for the lookup feature
  • [ ] Tested complete flow from frontend to Riot API with Riot ID format
  • [ ] Verified data displays correctly for summoner level and top champions

Next Steps ๐Ÿš€

Congratulations! You've built a working Riot API integration that runs securely in the cloud! Here's what you've accomplished:
โœ… Secure API integration with proper key management
โœ… Serverless architecture that scales automatically and costs almost nothing
โœ… Real-time League data fetching and display using current Riot ID system
โœ… Professional error handling and user experience
โœ… CORS-enabled API that works with modern web security
Your project now connects to live Riot Games data and demonstrates real API integration skills. This is the same pattern used by professional applications to integrate with external services.
What's next? Tomorrow on Day 7, you'll document your journey and share your success! You'll write about your experience, take screenshots of what you built, and share your project with the community. Time to show off those API integration skills!
GG on building your first cloud-based API integration! ๐ŸŽฎโ˜๏ธ
Pro tip: The skills you learned today - secure API key management, serverless functions, and external API integration - are fundamental to modern web development. You've just implemented the same patterns used by major applications and services.
***## Update Notes (Oct 3, 2025)This article has been updated to fix two critical issues reported by the community:1. Updated to Riot ID API: The original code used the deprecated /summoners/by-name/ endpoint. The updated version uses the current Riot ID system (GameName#TAG format) with the /riot/account/v1/accounts/by-riot-id/ endpoint.
2. Removed conflicting CORS headers: The Lambda function no longer returns CORS headers since they're configured in the Function URL settings. This prevents the 403 Forbidden errors some users experienced.
3. Added detailed CORS configuration instructions: Step 5 now includes explicit instructions on finding and correctly entering the Amplify domain for CORS configuration.
4. Enhanced error handling: Added URL encoding for special characters in Riot IDs and improved error messages throughout the Lambda function.Special thanks to Vir Patel, Tahmid H, and others in the community for identifying and helping debug these issues!
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article