I thought I'd shift gears a bit and start working on some tooling for Buttondown, which delivers this newsletter. While I've been happy with the service, there are a few gaps in features that I'd like to have. Fortunately, they offer a free API for customers and I've been using it to build tooling to fill in those gaps. I thought you might like to see how I'm doing it and get a peek into my thought process. This won't be code that you can follow along on your own, but you should be able to apply the same principles to your projects.
## Archive Searching
I love that all of my previous newsletters are available in an online [archive](https://buttondown.email/behind-the-powershell-pipeline/archive/). However, the site doesn't have a direct search feature. If you wanted to find what I have written about eventing, you can't easily do that from the web site. Fortunately, the content is crawled by search engines, so you could use Google.
In the Google search box, you can type `site:buttondown.email/behind-the-powershell-pipeline eventing` and you'll get a list of results from my newsletter.
If you are a premium subscriber, you can read the full archived article. What I don't know is if Google is searching the limited preview that is available to non-premium subscribers or the full article.
Regardless, I'd like to build something that I can publish or post somewhere that you can use to search the archive. To be honest, I have no idea what I want to build yet. I have some ideas on what I want to do, but nothing definitive on a deliverable.
## Exploring the Buttondown API
In any event, the first step is to use the Buttondown API to get the data I need. I'm going to use PowerShell to do this, of course, using the `Invoke-RestMethod` cmdlet. Buttondown publishers, like me, can get an API key to access newsletter-related data. The API is documented, although, like much API documentation, it is aimed at developers and not scripters like myself.
I thought I'd shift gears and start working on tooling for Buttondown, which delivers this newsletter. While I've been happy with the service, there are a few gaps in features that I'd like to have. Fortunately, they offer a free API for customers, and I've been using it to build tooling to fill in those gaps. I thought you might like to see how I'm doing it and get a peek into my thought process. This won't be code that you can follow along on your own, but you should be able to apply the same principles to your projects.
Archive Searching
I love that my previous newsletters are available in an online archive. However, the site doesn't have a direct search feature. If you want to find what I have written about eventing, you can't easily do that from the website. Fortunately, the content is crawled by search engines, so you could use Google.
In the Google search box, you can type site:buttondown.email/behind-the-powershell-pipeline eventing and you'll get a list of results from my newsletter.
figure 1
You can read the complete archived article if you are a premium subscriber. I don't know if Google is searching the limited preview available to non-premium subscribers or the full article.
Regardless, I'd like to build something I can publish or post somewhere you can use to search the archive. Honestly, I have no idea what I want to develop yet. I have some ideas on what I want to do, but nothing definitive on a deliverable.
Exploring the Buttondown API
The first step is to use the Buttondown API to get the data I need. I will use PowerShell to do this, of course, using the Invoke-RestMethod cmdlet. Buttondown publishers, like me, can get an API key to access newsletter-related data. The API is documented, although, like much API documentation, it is aimed at developers and not scripters like myself.
Once I had my API key, the first thing I did was put it in my secrets management vault. I will need to use the API key to authenticate, so I'll need to pass it in my code. I hope it goes without saying that I don't want to hardcode this value into my code. I should pass it as a parameter.
In my development code, I'll get the API key and save it to a variable.
I am storing the variable as a plain text string. I could store it as a secure string, but then I'd have to convert it to a plain text string to use it in the API call. I trust the physical security of my computer, so I'm fine with this approach.
Many API requests will require some sort of authentication. When using Invoke-RestMethod, I can pass the API key in the request header.
$head=@{Authorization="token $bdAPI"}
You need to look at your documentation to determine what value is required for authorization. In my case, Buttondown is expecting a string like token abc123def456.
Next, I need to know the endpoint. The endpoint is the URL that I will be calling. In my case, I want to get a list of all my emails. The documentation tells me that the base URI is https://api.buttondown.email/v1/. There are different endpoints for different features. For emails, I need to call https://api.buttondown.email/v1/emails/.
In my code, I like to separate the elements of the URI into variables. This makes it easier to build the URI and troubleshoot if needed.
Be careful combining elements to build your path. You don't want to end up with double slashes. The value of $uri is `https://api.buttondown.email/v1/emails
I can use Invoke-RestMethod to make the call, passing the authentication header.
$r=Invoke-RestMethod-Uri$uri-Headers$head
I've only been published on the site for a few weeks, so I only get the items I've sent.
PSD:\OneDrive...\behind-archive\>$r.count
8
This is where you need to use PowerShell to help you explore the data.
The API documentation tells me what kind of data I can expect but not necessarily where it is. In this case, the results property holds the data I need. This is where I see the properties defined in the API documentation.
The data includes the full text of the article. I'll probably want to cut that down to a preview. However, I also have an idea of building an index of PowerShell commands and concepts I've written about. I could use the body property to create that index. But that's not for today.
Using API Parameters
The default behavior of the emails endpoint is to return emails I have sent. When I migrated from Substack, that content was imported into Buttondown as emails with an imported status. The API documentation tells me that I can use parameters to filter the results by using parameters. The documentation says I can use the status parameter to filter by status. Fortunately, the documentation also tells me possible values to use. Use the ? character to add parameters to the URI.
I can't tell you how much time I spent spinning my wheels trying to use a URI like $base/emails/?status=imported only to encounter errors. See that extra slash in front of the ? character? That's what was causing the problem. I had to remove the slash to get it to work.
But I need to get emails where the status is sent or imported. I can use the status parameter to get both. This trick is in concatenating the parameters, even if they are the same.
It is not uncommon for APIs to return data in pages or groups. In this case, it looks like Buttondown returns 100 items at a time. Typically, the next page is defined with a query parameter like ?page=2. Once again, either look to the documentation or your object for help.
$all|Get-Member-MemberTypeProperties
figure 4
The next property is a URI that I can use to get the next page of results. I can use a do loop to get the results.
I'm using the common parameter OutVariable to store the Invoke-RestMethod result. That is so I can get the next URI and use it in the loop. The Results property gets added to the array, $all.
Now, I can work with the results in $all to build my archive search.
When I'm ready to work on this further, I can import the data and continue. I hope this gives you an idea of using an API to get data for your projects. I'll continue to work on this and share my progress with you. If you have any questions or suggestions, please let me know.
(c) 2022-2025 JDH Information Technology Solutions, Inc. - all rights reserved
Don't miss what's next. Subscribe to Behind the PowerShell Pipeline: