Ultrahuman User Info API
Reads the authorized user's basic profile via the profile scope - user ID, time zone, and similar account metadata used to correlate metric payloads to a partner-linked user.
Reads the authorized user's basic profile via the profile scope - user ID, time zone, and similar account metadata used to correlate metric payloads to a partner-linked user.
openapi: 3.0.3
info:
title: Ultrahuman Partner (UltraSignal) API
description: >-
The Ultrahuman Partner API gives approved partners read access to
user-consented health metrics from the Ultrahuman Ring AIR / Ring Pro and,
for users with an active M1 patch, the Ultrahuman CGM. Access is secured with
OAuth 2.0 (Authorization Code Grant plus Refresh Token flow) across three
scopes: profile, ring_data, and cgm_data. Access is not self-serve - partners
apply to the developer program and are issued a Client ID, Client Secret, and
a registered redirect URI during onboarding; end users authorize data sharing
from the Ultrahuman app (Profile -> Settings -> Partner ID). Access tokens
expire in ~1 day (86400 seconds); refresh tokens rotate on each exchange.
IMPORTANT: This document is MODELED by API Evangelist from Ultrahuman's public
partner developer documentation. Endpoint paths, scopes, OAuth flows, query
parameters, and the documented metric families are drawn from the docs;
exact request/response schemas are approximations and should be verified
against the live developer portal. Ultrahuman also documents a personal-token
variant at GET /api/v1/partner/daily_metrics for a developer's own ring data.
version: '1.0'
contact:
name: Ultrahuman Partnerships
url: https://partnerships.ultrahuman.com/
x-endpointsModeled: true
servers:
- url: https://partner.ultrahuman.com
description: Ultrahuman Partner API
tags:
- name: OAuth
description: OAuth 2.0 authorization, token exchange, and revocation.
- name: Metrics
description: Ring and CGM daily metrics for consented users.
- name: User
description: Basic authorized-user profile information.
paths:
/authorize:
get:
operationId: authorize
tags:
- OAuth
summary: Authorization endpoint (Authorization Code Grant)
description: >-
Redirects the user to Ultrahuman to consent to the requested scopes.
On approval, Ultrahuman redirects back to the registered redirect_uri
with an authorization code.
parameters:
- name: response_type
in: query
required: true
schema:
type: string
enum: [code]
- name: client_id
in: query
required: true
schema:
type: string
- name: redirect_uri
in: query
required: true
schema:
type: string
format: uri
- name: scope
in: query
required: true
description: Space-delimited scopes - profile, ring_data, cgm_data.
schema:
type: string
example: profile ring_data cgm_data
- name: state
in: query
required: false
schema:
type: string
responses:
'302':
description: Redirect to redirect_uri with an authorization code (or an error).
/api/partners/oauth/token:
post:
operationId: token
tags:
- OAuth
summary: Token endpoint (code exchange and refresh)
description: >-
Exchanges an authorization code for an access token, or exchanges a
refresh token for a new access token. Perform token exchanges
server-side. Refresh tokens rotate on each exchange.
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/TokenRequest'
responses:
'200':
description: A new access token (and rotated refresh token).
content:
application/json:
schema:
$ref: '#/components/schemas/TokenResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/api/partners/oauth/revoke:
post:
operationId: revoke
tags:
- OAuth
summary: Revoke a token
description: Revokes an access or refresh token.
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
required: [token, client_id, client_secret]
properties:
token:
type: string
client_id:
type: string
client_secret:
type: string
responses:
'200':
description: Token revoked.
'400':
$ref: '#/components/responses/BadRequest'
/api/partners/v1/user_data/metrics:
get:
operationId: getUserMetrics
tags:
- Metrics
summary: Get a user's daily health metrics
description: >-
Returns consented daily metrics for the authorized user. Ring metrics
require the ring_data scope; glucose/CGM metrics require the cgm_data
scope and an active M1 patch. Query by a single date (YYYY-MM-DD) or by a
start_epoch/end_epoch window (max range 7 days). date and the epoch pair
are mutually exclusive.
security:
- bearerAuth: []
parameters:
- name: date
in: query
required: false
description: Target day in YYYY-MM-DD. Mutually exclusive with the epoch pair.
schema:
type: string
format: date
- name: start_epoch
in: query
required: false
description: Window start, epoch seconds. Use with end_epoch (max 7-day range).
schema:
type: integer
format: int64
- name: end_epoch
in: query
required: false
description: Window end, epoch seconds.
schema:
type: integer
format: int64
- name: email
in: query
required: false
description: Optional target user's email for authorized multi-user access.
schema:
type: string
format: email
responses:
'200':
description: The user's metrics for the requested period.
content:
application/json:
schema:
$ref: '#/components/schemas/MetricsResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
/api/partners/v1/user_data/user_info:
get:
operationId: getUserInfo
tags:
- User
summary: Get the authorized user's basic profile
description: >-
Returns basic profile info (user ID, time zone, etc.) for the authorized
user. Requires the profile scope.
security:
- bearerAuth: []
responses:
'200':
description: Basic user profile.
content:
application/json:
schema:
$ref: '#/components/schemas/UserInfo'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: OAuth 2.0 access token in the Authorization header.
responses:
BadRequest:
description: Invalid parameters, or the epoch window exceeded the 7-day limit.
Unauthorized:
description: Missing, invalid, or expired access token.
NotFound:
description: User not found, or the partner lacks permission for the requested data.
schemas:
TokenRequest:
type: object
required: [grant_type, client_id, client_secret]
properties:
grant_type:
type: string
enum: [authorization_code, refresh_token]
client_id:
type: string
client_secret:
type: string
code:
type: string
description: Required for grant_type=authorization_code.
redirect_uri:
type: string
format: uri
refresh_token:
type: string
description: Required for grant_type=refresh_token.
TokenResponse:
type: object
properties:
access_token:
type: string
token_type:
type: string
example: Bearer
expires_in:
type: integer
example: 86400
refresh_token:
type: string
scope:
type: string
created_at:
type: integer
format: int64
UserInfo:
type: object
properties:
id:
type: string
timezone:
type: string
example: Asia/Kolkata
MetricsResponse:
type: object
description: >-
Modeled envelope of daily metrics. The docs describe roughly 40+ metric
fields spanning cardiovascular, sleep, glucose, activity/recovery, and
temperature families; representative fields are shown here.
properties:
date:
type: string
format: date
cardiovascular:
type: object
properties:
heart_rate:
type: number
hrv_rmssd:
type: number
night_resting_heart_rate:
type: number
sleep_hrv:
type: number
spo2:
type: number
sleep:
type: object
properties:
total_duration_minutes:
type: number
efficiency:
type: number
rem_minutes:
type: number
deep_minutes:
type: number
light_minutes:
type: number
sleep_score:
type: number
temperature_deviation:
type: number
activity_recovery:
type: object
properties:
steps:
type: integer
active_minutes:
type: number
movement_index:
type: number
recovery_index:
type: number
recovery_score:
type: number
metabolic_score:
type: number
vo2_max:
type: number
temperature:
type: object
properties:
skin_temperature_celsius:
type: number
avg_body_temperature_sleep:
type: number
glucose:
type: object
description: Present only with the cgm_data scope and an active M1 patch.
properties:
readings:
type: array
items:
type: object
properties:
epoch:
type: integer
format: int64
value_mgdl:
type: number
average_mgdl:
type: number
variability:
type: number
estimated_hba1c:
type: number
time_in_target_percent:
type: number