The Soundcloud API documentation is incredibly misleading if you are not using one of their official languages (PHP, Ruby, Python, and Javascript). This guide will not cover every function of the Soundcloud API, but it will give you an excellent foundation to begin using Soundcloud with your Go application.

In order to speed up development, you may want to download some of the following tools:

1. Wireshark - Monitoring TCP connections so that you can see requests and responses. Instead of sending to https:// @ Soundcloud, send to your own domain or localhost and monitor that.

2. Curl - For rapid testing with the Soundcloud API to make sure you're sending the right parameters.

3. LiteIDE - Not necessary, but a very nice IDE for developing in Go.

If you haven't already done so, register your application here. We'll get back to the redirect URI later, but use any html page. Here is the information I inputted for it:

1. Website of your app: http://simpletune.me/

2. Redirect URI for Authentication: http://localhost:8080/platform/soundcloudCallback.html


The first goal was to connect to their API using OAuth. You need to prompt the user to allow your app to access their account, to do this, they click on a url which brings them to a Soundcloud authentication page. Once they allow your app, they are brought to your redirect URI.

<a href="https://soundcloud.com/connect?client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&response_type=code&scope=non-expiring">Connect to CloudSound</a>

This section uses github.com/gorilla/mux.

In order to handle this on our Go server, we must have a handler:

r := mux.NewRouter()
r.HandleFunc("/platform/soundcloudCallback.html", platformHandler)
http.Handle("/", r)

This handler goes to the function, platformHandler() which generates the [empty] HTML page:

func platformHandler(w http.ResponseWriter, r *http.Request) {
	Auth(r.URL.String()[len("/platform/soundcloudCallback.html?code="):])
}

What happens here is Soundcloud redirects to the REDIRECT_URI along with a code that you can extract through the url (via slicing). Now we have to actually request an access token using that code.

// Create a struct to organize our Soundcloud credentials
type Client struct {
	ID          string
	Secret      string
	RedirectURI string
	Token       Token
	Client      *http.Client
}
// Create a "constructor" for the struct with our personal credentials. 
// Take these credentials from [http://soundcloud.com/you/apps](http://soundcloud.com/you/apps).
func NewClient() (Client, error) {
	c := Client{
		ID:          "YOUR_CLIENT_ID",
		Secret:      "YOUR_CLIENT_SECRET",
		RedirectURI: "YOUR_REDIRECT_URI",
		Client:      &http.Client{},
	}
	return c, nil
}

Now that we have a client struct, we will actually authenticate:

// Be sure to import the necessary packages.
import (
	"encoding/json"
	"net/http"
	"net/url"
	"strings"
)
func Auth(code string) (Client, error) {
	c, err := NewClient()
	if err != nil {
		return c, err
	}
       // Refer to: https://developers.soundcloud.com/docs/api/reference#token for information about parameters you must send.
	v := url.Values{}
	v.Set("client_id", c.ID)
	v.Set("client_secret", c.Secret)
	v.Set("redirect_uri", c.RedirectURI)
	v.Set("grant_type", "authorization_code")
	v.Set("code", code)
        // Ensure we are receiving JSON in the response from Soundcloud
	requestHeader := http.Header{}
	requestHeader.Add("Accept", "application/json")
       // Create the request
        req, err := http.NewRequest("POST", "https://api.soundcloud.com/oauth2/token", strings.NewReader(v.Encode()))
	if err != nil {
		return nil, err
	}
	req.Header = requestHeader
       // Send the request
	resp, err := c.Client.Do(req)
	if err != nil {
		return nil, err
	}
	// If there was no error, you should have received an access_token and the scope/ longetivity of the token in the resp.Body in JSON.
	return c, nil
}

Now that we are authenticated and have access to our user's account, it's time to do cool stuff like uploading tracks and getting more information about their current tracks. I'll cover that in my next blog post.