{
  "info": {
    "_postman_id": "aifitnessapi-oura",
    "name": "Oura (aifitnessapi.com)",
    "description": "Oura: OAuth 2.0 and Webhook samples requests built from the vendor documentation aifitnessapi.com quotes. Generated by scripts/build-collections.mjs; no secrets included. https://aifitnessapi.com/collections",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "item": [
    {
      "name": "OAuth 2.0",
      "description": "Oura's authorization-code flow as its documentation describes it, read 2026-11-05. Fill client_id, redirect_uri and scope in an environment of your own and keep client_secret there, never in a shared collection.\n\nThe same facts, with each source sentence, at https://aifitnessapi.com/integrate/oura-api and https://aifitnessapi.com/tools/oauth-playground.",
      "item": [
        {
          "name": "1. Authorization URL (open in a browser)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "https://cloud.ouraring.com/oauth/authorize?response_type=code&client_id={{client_id}}&redirect_uri={{redirect_uri}}&scope={{scope}}&state={{state}}&code_challenge={{code_challenge}}&code_challenge_method=S256",
              "protocol": "https",
              "host": [
                "cloud",
                "ouraring",
                "com"
              ],
              "path": [
                "oauth",
                "authorize"
              ],
              "query": [
                {
                  "key": "response_type",
                  "value": "code"
                },
                {
                  "key": "client_id",
                  "value": "{{client_id}}"
                },
                {
                  "key": "redirect_uri",
                  "value": "{{redirect_uri}}"
                },
                {
                  "key": "scope",
                  "value": "{{scope}}"
                },
                {
                  "key": "state",
                  "value": "{{state}}"
                },
                {
                  "key": "code_challenge",
                  "value": "{{code_challenge}}"
                },
                {
                  "key": "code_challenge_method",
                  "value": "S256"
                }
              ]
            },
            "description": "https://cloud.ouraring.com/oauth/authorize. Authorization URL. Open this URL in a browser (in Postman: copy it from the request bar); the user signs in and Oura redirects to {{redirect_uri}} with ?code=… Put that value in the auth_code variable.\n\nSource: Oura API documentation, “Authentication”, https://cloud.ouraring.com/docs/authentication\n\nScope: Space-separated. Left blank, the app requests every scope; the user can switch scopes off at consent. Source: Oura API documentation, “Authentication”, https://cloud.ouraring.com/docs/authentication\n\nDocumented scopes (joined with spaces):\n- email: Email address of the user\n- personal: Personal information (gender, age, height, weight)\n- daily: Daily summaries of sleep, activity and readiness\n- heartrate: Time series heart rate for Gen 3 users\n- workout: Summaries for auto-detected and user entered workouts\n- tag: User entered tags\n- session: Guided and unguided sessions in the Oura app\n- spo2: Daily SpO2 Average recorded during sleep\n- heart_health: Heart health data (listed in the OpenAPI document, not on the Authentication page)\n\nPKCE: Recommended. code_challenge_method must be S256; the verifier is 43 to 128 characters, hashed with SHA-256 and base64url-encoded without padding. Generate a verifier and challenge in your browser at https://aifitnessapi.com/tools/oauth-playground and put them in code_verifier and code_challenge. Source: Oura API documentation, “Authentication”, https://cloud.ouraring.com/docs/authentication\n\nAlso documented: https://developer.ouraring.com/authorize. Universal-link authorization URL for new OAuth clients; on a phone with the Oura app it can open the consent page in the app. Source: Oura API documentation, “Authentication”, https://cloud.ouraring.com/docs/authentication"
          },
          "response": []
        },
        {
          "name": "2. Exchange the code for tokens",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/x-www-form-urlencoded",
                "type": "text"
              },
              {
                "key": "User-Agent",
                "value": "YourApp/1.0",
                "type": "text"
              }
            ],
            "url": {
              "raw": "https://api.ouraring.com/oauth/token",
              "protocol": "https",
              "host": [
                "api",
                "ouraring",
                "com"
              ],
              "path": [
                "oauth",
                "token"
              ]
            },
            "description": "https://api.ouraring.com/oauth/token. Token URL.\n\nSource: Oura API documentation, “Authentication”, https://cloud.ouraring.com/docs/authentication\n\nClient credentials go in the form body here; the vendor also accepts HTTP Basic.\n\nToken lifetime: Returned in expires_in. The page states no fixed number for the server-side flow; the client-side flow's token is currently 30 days and has no refresh token. Source: Oura API documentation, “Authentication”, https://cloud.ouraring.com/docs/authentication\n\nNote: Client credentials go in the form body or as HTTP Basic (client_id as user name, client_secret as password). Source: Oura API documentation, “Authentication”, https://cloud.ouraring.com/docs/authentication\n\nNote: Every request to the Oura API needs a non-empty User-Agent header, so the commands below send one. Source: Oura API documentation, “Authentication”, https://cloud.ouraring.com/docs/authentication\n\nNote: Revoke a token with GET https://api.ouraring.com/oauth/revoke?access_token=…. Source: Oura API documentation, “Authentication”, https://cloud.ouraring.com/docs/authentication",
            "body": {
              "mode": "urlencoded",
              "urlencoded": [
                {
                  "key": "grant_type",
                  "value": "authorization_code",
                  "type": "text"
                },
                {
                  "key": "code",
                  "value": "{{auth_code}}",
                  "type": "text"
                },
                {
                  "key": "redirect_uri",
                  "value": "{{redirect_uri}}",
                  "type": "text"
                },
                {
                  "key": "client_id",
                  "value": "{{client_id}}",
                  "type": "text"
                },
                {
                  "key": "client_secret",
                  "value": "{{client_secret}}",
                  "type": "text"
                },
                {
                  "key": "code_verifier",
                  "value": "{{code_verifier}}",
                  "type": "text",
                  "disabled": true,
                  "description": "Enable when the authorization request carried a code_challenge."
                }
              ]
            }
          },
          "response": []
        },
        {
          "name": "3. Refresh the access token",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/x-www-form-urlencoded",
                "type": "text"
              },
              {
                "key": "User-Agent",
                "value": "YourApp/1.0",
                "type": "text"
              }
            ],
            "url": {
              "raw": "https://api.ouraring.com/oauth/token",
              "protocol": "https",
              "host": [
                "api",
                "ouraring",
                "com"
              ],
              "path": [
                "oauth",
                "token"
              ]
            },
            "description": "Refresh: grant_type=refresh_token at the token URL returns a new access token and a new refresh token; each refresh token works once.\n\nSource: Oura API documentation, “Authentication”, https://cloud.ouraring.com/docs/authentication",
            "body": {
              "mode": "urlencoded",
              "urlencoded": [
                {
                  "key": "grant_type",
                  "value": "refresh_token",
                  "type": "text"
                },
                {
                  "key": "refresh_token",
                  "value": "{{refresh_token}}",
                  "type": "text"
                },
                {
                  "key": "client_id",
                  "value": "{{client_id}}",
                  "type": "text"
                },
                {
                  "key": "client_secret",
                  "value": "{{client_secret}}",
                  "type": "text"
                }
              ]
            }
          },
          "response": []
        }
      ]
    },
    {
      "name": "Webhook samples",
      "description": "Oura's documented example notifications, sent to {{local_url}} (your local handler) unchanged. Signature: HMAC-SHA256 keyed by your client secret over the x-oura-timestamp value followed by JSON.stringify(body), hex, upper-case, in x-oura-signature. Source: Oura API v2 OpenAPI document (1.43), “Webhooks for Real-Time Data Updates”, https://cloud.ouraring.com/v2/static/json/openapi-1.43.json\n\nHeaders that carry a signature hold the placeholder Oura prints, so a handler that verifies signatures will reject these: to send correctly signed requests, use https://aifitnessapi.com/webhooks/send-sample.mjs. Respond: Respond with a 2xx in under 10 seconds and process the event asynchronously. Before events flow, Oura verifies the callback with a GET carrying verification_token and challenge; echo the challenge as JSON.\n\nPayload library with JSON Schemas: https://aifitnessapi.com/webhooks#oura.",
      "item": [
        {
          "name": "Data event",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "x-oura-signature",
                "value": "HMAC_SIGNATURE",
                "type": "text",
                "description": "As in Oura's example."
              },
              {
                "key": "x-oura-timestamp",
                "value": "1234567890",
                "type": "text",
                "description": "As in Oura's example."
              }
            ],
            "url": {
              "raw": "{{local_url}}",
              "host": [
                "{{local_url}}"
              ]
            },
            "description": "Oura sends a POST to your callback URL when subscribed data changes (the example: a user syncs new sleep data).\n\nOura's example event is a POST with x-oura-signature and x-oura-timestamp headers. Source: Oura API v2 OpenAPI document (1.43), “Webhooks for Real-Time Data Updates”, https://cloud.ouraring.com/v2/static/json/openapi-1.43.json",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"event_type\": \"update\",\n  \"data_type\": \"sleep\",\n  \"object_id\": \"12345abc\",\n  \"event_time\": \"2023-01-01T08:00:00+00:00\",\n  \"user_id\": \"user123\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "response": []
        }
      ]
    }
  ],
  "variable": [
    {
      "key": "client_id",
      "value": "",
      "type": "string",
      "description": "Your app's client ID, from the vendor's developer console."
    },
    {
      "key": "client_secret",
      "value": "",
      "type": "string",
      "description": "Keep it in a Postman or Bruno environment marked secret. This collection ships it empty."
    },
    {
      "key": "redirect_uri",
      "value": "",
      "type": "string",
      "description": "The redirect URI registered with the vendor."
    },
    {
      "key": "scope",
      "value": "",
      "type": "string",
      "description": "Scopes to request, joined as the vendor documents (see the authorization request)."
    },
    {
      "key": "state",
      "value": "",
      "type": "string",
      "description": "A random value you check on the redirect."
    },
    {
      "key": "code_verifier",
      "value": "",
      "type": "string",
      "description": "PKCE verifier (generate one at /tools/oauth-playground)."
    },
    {
      "key": "code_challenge",
      "value": "",
      "type": "string",
      "description": "PKCE challenge for that verifier."
    },
    {
      "key": "auth_code",
      "value": "",
      "type": "string",
      "description": "The ?code= value from the redirect."
    },
    {
      "key": "refresh_token",
      "value": "",
      "type": "string",
      "description": "The refresh_token from the token response."
    },
    {
      "key": "local_url",
      "value": "http://localhost:3000/webhooks/oura",
      "type": "string",
      "description": "Where your webhook handler listens."
    }
  ]
}
