Over the last couple of years, I have created a sample Campaign Manager that makes use of many of SparkPost’s RESTful API (refer to the links at the bottom of this blog). For the most part, it’s used as an example of what can be done with SparkPost as an email platform. My goal was to meet the following requirements:

  1. Store no data about the user except login credentials via cookies
  2. Directly call the SparkPost API
  3. Support the ability for any SparkPost user to leverage the Campaign Manager, including Subaccounts!
  4. Allow for campaigns to be created and deleted

In order to follow these principles, I had to come up with a way to allow an user to log into the system without creating a full blown username/password/roles system. This was easily done by having the user log into the system using a SparkPost API Key as the credential. This allowed the system to do everything on behalf of the user, including:

  • Creating, reviewing and deleting campaigns
  • Reviewing message events
  • Creating, updating and deleting templates with an embedded WYSIWYG TinyMCE html editor

Recently I decided to add some simple analytics in order to give the user an understanding of how their sending is progressing. Keeping with my philosophy of not storing data, I decided to leverage SparkPost’s metrics API. Unfortunately, there is one caveat in leveraging the metrics API; the SparkPost metrics API does not support being called using a subaccount API key! Ouch! Double ouch!

The metrics API does take a list of subaccount id(s) as an option which allows a Master API key to obtain information about a subaccount, but my problem was how to get that subaccount id from the user logging into the Campaign Manager with a subaccount API key. They were probably were never given that id in the first place and validating that user to that id would be impossible without holding data.

So in order to add Analytics that works for both the master and subaccounts to the Campaign Manager I needed to figure out which SparkPost customer id is related to the users API key. That way I can call the metrics api using the stored master key (there are parameter fields kept on the system and a master api key is one of them) along with the subaccount id as a parameter in order to obtain the proper metric data.

The biggest restrictions I found are:

  1. There is no api endpoint that can tell me what api keys are stored per subaccount.
  2. Only the following api endpoint support subaccount keys:
    1. message-events, sending-domains, suppression-list, templates, transmissions, tracking-domains, webhooks

* Notice that the metrics API is not listed

I’m not going to bore you with all the different ways that might work and their pro’s and con’s; it’s just not that interesting. But here is the approach that I am taking.

To solve this problem I took two steps:

  1. I used the stored master api key to pull the following two metrics for a 9 day interval starting the day before the current date from the metrics api for all accounts/subaccounts. This makes sure there is no new data being added while I do the following comparisons.

a. count_injected
b. count_delivered


This gave me a results that looked similar to:

    "results": [
        	"count_injected": 51,
        	"count_delivered": 40,
        	"subaccount_id": 2297
        	"count_injected": 36,
        	"count_delivered": 28,
        	"subaccount_id": 0
        	"count_injected": 10,
        	"count_delivered": 8,
        	"subaccount_id": 2294

2. I used the entered api key to pull the same two statistics from the message-events api, using the same timeframe as the call to the metrics API.


This call will return the number of results per page requested, the total_count, and link to next and last pages of results. The only item I care about though is the total_count entry. That total count should match the sum of the count_injected and count_delivered from the previous call. To get the subaccount id, I loop through the metrics call results, summing those two fields until I find a match to my message-events results.

Yes, I could find multiple systems with the exact same number as the message-events results, but the likelihood is rather small and if it does happen, I’ll throw a message saying that I can’t verify the users account at this time and to try again at another time. It’s not perfect, but except for brand new accounts, having two accounts that sum up to the same number of injections and deliveries is fairly insignificant.

One or two of you may be asking, well, how do I know I need to go through this process? How do I know that the entered API key is a subaccount API key? Figuring that out is actually fairly straight forward. All I have to do, is call the metrics API with the api key once it was entered into the Campaign Manager. If I get a http 403 I know that I have a good key, but SparkPost has refused the key, if I get a 200 I have a master key, and if I get a 401, I know I have a bad key.

So that’s how it’s done. By using the metrics API with the master key, and the message-events API with the subaccount key, I’m able to track down the subaccount ID for a final call to the metric API using the stored master key. I’m the first to admit that this is a fairly unique edge case, but I hope that if someone runs into this problem in the future that I’m able to minimize your pain.


You can view other resources on this topic here: