Skip to Content
Getting Started

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"] }
FieldConstraint
displayName1–128 characters
redirectUris1–10 URIs
requestedScopesthe 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.

  1. Start the authorization-code flow at POST /oauth/authorize.
  2. The user reviews and approves the requested scopes in the DPerspective app.
  3. You receive a single-use authorization code at your redirect URI.
  4. Exchange the code at POST /oauth/token for an access token (and refresh token).

See Authentication and Consent & Approval for the full flow.

Make your first call

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.