Java integration guide
Java Music API
Java developers who want to add music generation to a backend or Android backend service without hosting an audio model.
The approach
MusicAPI is a JSON REST API, so the built-in java.net.http.HttpClient (JDK 11 and newer) handles the calls and Jackson handles the JSON. Submit a job to POST /sonic/create, then poll GET /sonic/task/{task_id}. A generation takes a couple of minutes, so poll from a queued job or a scheduled executor rather than the request thread.
Install
implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.0'How it works
- 1
Use JDK 11 or newer for the built-in HttpClient. Add Jackson for JSON (or any JSON library you prefer).
- 2
Create an API key in the MusicAPI dashboard and read it from the MUSICAPI_KEY environment variable.
- 3
POST to /sonic/create with custom_mode, mv, and gpt_description_prompt, and read the returned task_id.
- 4
Poll GET /sonic/task/{task_id}. An HTTP 202, or a body with type set to not_ready, means keep waiting.
- 5
When the job finishes, iterate the data array and use each song's audio_url, a ready-to-stream MP3.
Full working example
Copy this, set the MUSICAPI_KEY environment variable, and run it. It is a real request against the live API.
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Map;
public class MusicApiExample {
static final String API = "https://api.musicapi.ai/api/v1";
static final String KEY = System.getenv("MUSICAPI_KEY");
static final HttpClient HTTP = HttpClient.newHttpClient();
static final ObjectMapper JSON = new ObjectMapper();
public static void main(String[] args) throws Exception {
// 1. Submit a generation job.
String payload = JSON.writeValueAsString(Map.of(
"custom_mode", false,
"mv", "sonic-v5",
"gpt_description_prompt", "cinematic strings for a launch video"
));
HttpRequest create = HttpRequest.newBuilder(URI.create(API + "/sonic/create"))
.header("Authorization", "Bearer " + KEY)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
String body = HTTP.send(create, HttpResponse.BodyHandlers.ofString()).body();
String taskId = JSON.readTree(body).get("task_id").asText();
// 2. Poll until the audio is ready.
while (true) {
HttpRequest poll = HttpRequest.newBuilder(URI.create(API + "/sonic/task/" + taskId))
.header("Authorization", "Bearer " + KEY)
.GET()
.build();
HttpResponse<String> res = HTTP.send(poll, HttpResponse.BodyHandlers.ofString());
if (res.statusCode() == 202) {
Thread.sleep(5000);
continue;
}
JsonNode task = JSON.readTree(res.body());
if ("not_ready".equals(task.path("type").asText())) {
Thread.sleep(5000);
continue;
}
for (JsonNode song : task.path("data")) {
System.out.println(song.path("title").asText() + " " + song.path("audio_url").asText());
}
break;
}
}
}Pricing
MusicAPI is pay-as-you-go with credit packs, plus predictable monthly subscriptions. The per-credit rate is the same across packs and subscriptions. See the pricing page for current rates, free credits, and volume options.
FAQ
Do I need Spring or a framework?
No. The example uses only the JDK 11 HttpClient plus Jackson for JSON. It drops into a plain main method, a Spring service, or an Android backend without changes to the API calls.
How do I know when the song is ready?
Poll GET /sonic/task/{task_id}. While the job runs you get an HTTP 202 or a body with type set to not_ready. When it finishes, the response carries a data array where each item has a streamable audio_url.
Can I avoid blocking a thread while polling?
Yes. A generation takes a couple of minutes, so poll from a ScheduledExecutorService or a queued job, or use HttpClient.sendAsync, instead of sleeping on a request thread.
Build it in 5 minutes
Get free credits on signup and run real generations before any payment. No credit card required to start.
API details verified 2026-06-26. The API surface evolves; the pricing page always has current rates.