How to build a new workspace using C# and Miro REST API

Getting unauthorized error when calling Miro API

I’m working on a WPF project with .NET Core 6.0 and trying to integrate with Miro’s REST API to create workspaces programmatically. I have my API credentials set up but running into authentication issues.

The first part of my code handles the OAuth flow correctly, but when I try to make the actual API call to create a board, I get an Unauthorized response. I’m using HttpClient for the requests.

public string AppId = "myappid";
public string AppSecret = "myappsecret";

internal async Task GenerateMiroWorkspace()
{
    try
    {
        var authClient = new HttpClient();
        var authEndpoint = $"https://miro.com/app-install/?response_type=code&client_id={AppId}";
        var authRequest = new HttpRequestMessage(HttpMethod.Post, authEndpoint);
        authRequest.Headers.Add("Authorization", $"Bearer {AppSecret}");
        var authResponse = await authClient.SendAsync(authRequest);
        var authResult = await authResponse.Content.ReadAsStringAsync();
        
        // This part works fine
        
        var apiClient = new HttpClient();
        var createRequest = new HttpRequestMessage(HttpMethod.Post, "https://api.miro.com/v1/boards");
        createRequest.Headers.Add("Accept", "application/json");
        
        var payload = new
        {
            title = "New Workspace",
            policy = new
            {
                visibility = "private",
                permissions = "private"
            }
        };
        
        createRequest.Content = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
        var createResponse = await apiClient.SendAsync(createRequest);
        var createResult = await createResponse.Content.ReadAsStringAsync();
        
        // Getting 401 Unauthorized here
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}

What am I missing in the authentication process? Do I need to include additional headers or use a different token format?

you’re missing the bearer token in your create request. add createRequest.Headers.Add("Authorization", $"Bearer {your_access_token}"); before sending the API call. also, the app secret isn’t the same as the access token.

You’re mixing up the OAuth flow with direct API calls. That app-install endpoint is for manual browser authorization, not programmatic access. You need to complete the full OAuth2 flow first to get an access token. After the user authorizes your app, Miro redirects back with an authorization code. Then you exchange that code for an access token using the /oauth/token endpoint. Once you have the token, include it in your board creation request headers as Authorization: Bearer {access_token}. Also, the v1 API is deprecated - use v2 endpoints instead. I made this same mistake when I started with Miro’s API six months ago.