Getting Started
From zero to your first authenticated API call.
Prerequisites
- A DPerspective end-user account. The developer who owns the app registers it while logged in to DPerspective.
- A DPerspective user who will approve your app’s access to their data. During development this can be the same person.
Register your application
Registration is performed by a logged-in DPerspective user (the app owner), authenticated by their end-user session — not by a partner token.
POST /developer/apps
Authorization: Bearer <end-user session token>
Content-Type: application/json
{
"displayName": "My Health Dashboard",
"redirectUris": ["https://myapp.example.com/oauth/callback"],
"requestedScopes": ["read:health-data", "read:medications"]
}| Field | Constraint |
|---|---|
displayName | 1–128 characters |
redirectUris | 1–10 URIs |
requestedScopes | the scopes your app may later request from users |
The response returns your clientId and a plaintext clientSecret shown
exactly once:
{
"clientId": "abc123…",
"clientSecret": "shown-once-store-it-now",
"displayName": "My Health Dashboard",
"status": "active"
}Store the clientSecret securely — it is never retrievable again. Only
its last 4 characters are shown afterward. You can rotate it later, which
immediately invalidates the old one.
Send the user through consent
- Start the authorization-code flow at
POST /oauth/authorize. - The user reviews and approves the requested scopes in the DPerspective app.
- You receive a single-use authorization code at your redirect URI.
- Exchange the code at
POST /oauth/tokenfor an access token (and refresh token).
See Authentication and Consent & Approval for the full flow.
Make your first call
cURL
curl https://dperspective.galacticgeeks.com/api/v1/health-data \
-H "Authorization: Bearer <access_token>"A successful response is scope-limited and paginated:
{
"data": [
{
"id": "…",
"type": "heart_rate",
"value": 72,
"unit": "bpm",
"timestamp": "2025-01-01T10:00:00Z",
"source": "wearable"
}
],
"pagination": { "page": 1, "pageSize": 20, "total": 1, "totalPages": 1 }
}Handle errors
All errors use a consistent envelope. Always branch on error.code, not the
message text.
{
"error": {
"code": "CONSENT_REQUIRED",
"message": "No active consent grant covers the requested scope."
}
}Request only the minimum scopes you need — see the Scopes reference — and review the Rate Limits before going to production.