- Docs
- Connect your users
Poll the sign-in status
Core + Managed TransfersGuide · 1 min
Start a sign-in with your own uniqueId and poll its state, for desktop apps, TVs and other clients that cannot receive a redirect.
Some clients cannot catch a redirect: a desktop app that opens the system browser, a TV app that shows a QR code, a CLI. Give the sign-in your own id and ask for its state until it ends.
- Make a UUID v4
Make it on the client, for example with
crypto.randomUUID(). Use a new one for every sign-in. - Open the sign-in with it
Add it as
uniqueIdto the sign-in URL, and open the URL in the browser. - Poll
Call
GET /app/integrations/byUniqueId/{uniqueId}every 2 seconds untilauthModel.statusissuccessorerror.
https://app.musicapi.com/{slug}?returnUrl={returnUrl}&uniqueId=7f1d2b9a-3c4e-4f5a-8b6c-9d0e1f2a3b4c
const uniqueId = crypto.randomUUID();
openBrowser(`https://app.musicapi.com/{slug}?returnUrl=${encodeURIComponent("{returnUrl}")}&uniqueId=${uniqueId}`);
async function waitForSignIn() {
for (let i = 0; i < 150; i += 1) {
const response = await fetch(`https://api.musicapi.com/app/integrations/byUniqueId/${uniqueId}?tokenOnly=1`);
if (response.ok) {
const { authModel, integrationUser } = await response.json();
if (authModel.status === "success") return integrationUser.uuid;
if (authModel.status === "error") throw new Error(authModel.errorType ?? "Sign-in failed");
}
await new Promise((resolve) => setTimeout(resolve, 2000));
}
throw new Error("Timed out");
}
The answer
404until the user picks a service: the attempt does not exist yet. Keep polling.200withauthModel.status: "initialised"while the user signs in.200withsuccessorerrorat the end.
{
"authModel": {
"uuid": "a1869581-38b2-4268-aee2-a4c2355efeb0",
"status": "success",
"error": null,
"errorType": null
},
"oneTimeToken": null,
"integrationUser": {
"uuid": "3f0b8c1e-6a4d-4c7a-9a55-2f1e7d9b0c11",
"integrationUserId": "mica.nowak",
"name": "Mica Nowak",
"email": "[email protected]",
"imageUrl": "https://images.example.com/mica.jpg",
"country": "PL"
}
}
Security
The call needs no credential: the uniqueId you chose is the secret. Treat it like a password for the length of the sign-in.
- Always make the
uniqueIdwith a secure random generator, never from a user id. - Send
tokenOnly=1from a browser or any client you do not control. The answer then never holds music-service credentials. - Without
tokenOnly, a sign-in started withrequestOneTimeToken=truewhosereturnUrlis not anhttp(s)URL (a native app scheme) also returnsauthData, the raw service tokens. A sign-in that returns to anhttp(s)URL never does. - With
requestOneTimeToken=true,oneTimeTokencarries a token that lives 30 seconds.