Management API
Your app's dashboard configuration is also readable and writable over HTTPS, which is useful for deployment automation — pointing your callback URL at a new host as part of a release, for instance.
Locations are no longer managed here. Voshi asks your app for its destinations at placement time, so the location endpoints below are legacy — they configure locations stored inside Voshi, which only applies to Voshi-hosted apps. Build a locations endpoint instead.
Base URL: https://api.link.voshi.com/ltiaas/v1
All management endpoints authenticate with your API key:
Authorization: Bearer ltiaas_<app-id>_<secret>
The app object
Endpoints that return your app use this shape:
{
"id": "I4ppXy",
"name": "My Study Tool",
"description": "Practice and quizzes for CS courses.",
"logo_url": "https://myapp.example.com/logo.png",
"callback_url": "https://myapp.example.com/launch_receiver",
"provision_url": "https://myapp.example.com/voshi/provision",
"locations_url": "https://myapp.example.com/voshi/locations",
"grades_released": true,
"status": "active",
"api_key_hint": "ltiaas_…cr3t",
"locations": [
{
"id": "Il0c8n",
"extid": "home",
"type": "content",
"label": "Home"
}
],
"created": "2026-05-01T12:00:00+00:00"
}
grades_released controls whether grades your app submits are immediately visible to students in the LMS gradebook (default true). status is read-only here — see app status.
Get your app
GET /ltiaas/v1/apps/me
Returns the app object above. The API key itself is never included — only api_key_hint.
curl "https://api.link.voshi.com/ltiaas/v1/apps/me" \
-H "Authorization: Bearer ltiaas_myappid_mysecret"
Update your app
PATCH /ltiaas/v1/apps/me
Content-Type: application/json
A partial update — send only the fields you want to change. Returns the updated app object.
namestringCannot be blank.
descriptionstringlogo_urlstringcallback_urlstringValidated on write — see endpoint URL rules.
provision_urlstringYour provisioning receiver. Same URL rules; send "" to clear it if your app needs no setup.
locations_urlstringYour locations endpoint. Same URL rules; send "" to clear it, which leaves only Voshi-stored locations on offer.
grades_releasedbooleancurl -X PATCH "https://api.link.voshi.com/ltiaas/v1/apps/me" \
-H "Authorization: Bearer ltiaas_myappid_mysecret" \
-H "Content-Type: application/json" \
-d '{"callback_url": "https://myapp.example.com/v2/launch_receiver"}'
Legacy: locations stored in Voshi
The four endpoints below manage location records inside Voshi. They predate app-served locations and don't affect what an instructor sees in the picker unless your app is hosted by Voshi. See Locations.
List locations
GET /ltiaas/v1/apps/me/locations
{
"locations": [
{
"id": "Il0c8n",
"extid": "home",
"type": "content",
"label": "Home"
},
{
"id": "Il0c8m",
"extid": "chapter3_quiz",
"type": "assessment",
"label": "Chapter 3 Quiz"
}
]
}
Create a location
POST /ltiaas/v1/apps/me/locations
Content-Type: application/json
Returns the created location object.
extidstringrequiredYour own ID for the location — letters, digits, dashes, and underscores. Unique within your app, and permanent once it has been placed.
typestringdefault: contentOne of assessment, practice, content, setup. An unrecognized value is rejected with a 422 (not silently coerced).
labelstringdefault: The name shown to instructors in the content picker.
curl -X POST "https://api.link.voshi.com/ltiaas/v1/apps/me/locations" \
-H "Authorization: Bearer ltiaas_myappid_mysecret" \
-H "Content-Type: application/json" \
-d '{"extid": "chapter3_quiz", "type": "assessment", "label": "Chapter 3 Quiz"}'
Update a location
PATCH /ltiaas/v1/apps/me/locations/{location_id}
Content-Type: application/json
A partial update — only the fields you send are touched. Accepts the same fields as create, all optional. Returns the updated location object.
Changing an extid that has already been linked into a course breaks every placement of it — see What makes a good extid.
Delete a location
DELETE /ltiaas/v1/apps/me/locations/{location_id}
Returns {"deleted": "<location_id>"}. The location registered with your app at creation time (extid home) cannot be deleted — 422 the home location cannot be deleted. Deleting a location that instructors have already placed breaks those placements.
Rotate your API key
POST /ltiaas/v1/apps/me/rotate-key
Issues a new API key for your app and invalidates the current one immediately — including the key you authenticated this call with. The response is the only time the new key is shown:
{
"app_id": "I4ppXy",
"api_key": "ltiaas_I4ppXy_n3ws3cr3t",
"api_key_hint": "ltiaas_…cr3t",
"message": "Save this API key now — it is shown only once. The previous key is no longer valid."
}
curl -X POST "https://api.link.voshi.com/ltiaas/v1/apps/me/rotate-key" \
-H "Authorization: Bearer ltiaas_myappid_myoldsecret"
There is no overlap window. Every deployed instance of your app still using the old key starts getting 401 the moment this returns — roll the new key out before you call it, or accept a gap in grade submission.
Errors
| Status | Cause |
|---|---|
401 | Missing, malformed, or invalid API key; or the app is suspended. |
404 | Location not found — unknown location ID (or one belonging to another app). |
422 | Validation failure — blank name, an invalid callback_url / provision_url / locations_url, a missing extid, an unknown location type, or deleting the home location. |
Error responses use the standard error envelope.