This isn't new, but was something I discovered a few weeks ago and I'm finally making the time to blog about it. I've used the Meetup API in the past with ColdFusion and for the most part, it just works, but like many APIs today it requires authenticated calls to get data. Unfortunately, even a simple search against public data also required an authenticated call. This means using the API in a purely client-side application won't be secure because your code will contain your secret keys.

Or so you would think. It isn't obvious at first (or wasn't to me), but the API actually supports "Key signatures". What this means is that you can design an API call, like, find me the meetups around area X that use the word "kitten" in the description and Meetup will give you a "signed" version of the URL to use in your application. Now here's the killer part. That URL is 100% safe to use because it will only do precisely what you told it to: Search for groups around area X with kitten in the name. Even better, this "lock" on the URL does not apply to anything related to paging or JSON/P callbacks. So outside of not being terribly obvious (at least in my opinion), this is a killer feature of the API and one worth considering for your next application.

In order to test this, you will need to have an account with Meetup and be logged in. Then simply go to the API Console and begin testing. Here is a screen shot of that in action:

shot1

You'll want to use the console to get your API calls down exactly as you want them and once you're satisfied, just copy and paste that URL into your code. I went ahead and whipped up a quick demo that performs a search for Ionic meetups around the world. Here's the code - and to be clear - this was quick and dirty, not nice.

function fetchGroups(url, cb, data) {
	if(!data) data = [];
	
	$.ajax({
		
		dataType:'jsonp',
		method:'get',
		url:url,
		success:function(result) {
			console.log('back with ' + result.data.length +' results');
			console.dir(result);
			//add to data
			data.push.apply(data, result.data);
			if(result.meta.next_link) {
				var nextUrl = result.meta.next_link;
				fetchGroups(nextUrl, cb, data);
			} else {
				cb(data);	
			}
		}
	});	
	
}

$(document).ready(function() {
	
	var $results = $("#results");

	$results.html("<p>Finding meetups with Ionic in the description.</p>");

	fetchGroups("https://api.meetup.com/find/groups?&photo-host=public&page=50&text=ionic&sig_id=2109318&radius=global&order=newest&sig=ad335a79ccce2b1bb65b27fe10ea6836305e5533&callback=?", function(res) {
		console.log("totally done");
		console.dir(res);	

		var s = "";
		for(var i=0;i<res.length; i++) {
			var group = res[i];
			s += "<h2>"+(i+1)+" <a href='"+group.link+"'>"+group.name+"</a></h2>";
			if(group.group_photo && group.group_photo.thumb_link) {
				s += "<img src=\"" + group.group_photo.thumb_link + "\" align=\"left\">";
			}
			s += "<p>Location: "+group.city + ", " + group.state + " " + group.country + "</p><br clear=\"left\">";
		}
		$results.html(s);
		
		
	});
		
});

I created a simple recursive function, fetchGroups, that lets me pass the initial signed URL in and deal with aggregating multiple pages of results. When finished, it then calls a callback function with the results. I should have used Promises perhaps, but, I was being lazy. The results are rendered out somewhat simply, but that could be improved of course.

You can view a live demo of this here: https://static.raymondcamden.com/demos/2015/nov/20/. Let me know what you think!