Authentication

All requests to the Udacity Public API must be authenticated using an API token. Use client credentials to generate short-lived tokens programmatically.

Endpoints
POSThttps://api.udacity.com/api/public/api/v1/tokens/graphql
POSThttps://api.udacity.com/api/public/api/v1/catalog/graphql
POSThttps://api.udacity.com/api/public/api/v1/program-progress/graphql
POSThttps://api.udacity.com/api/public/api/v1/assessment-progress/graphql
POSThttps://api.udacity.com/api/public/api/v1/learning-plan-progress/graphql
Recommended

Client credentials

For backend services, data pipelines, and LMS integrations, use a client credential pair to programmatically generate short-lived tokens.

  1. A company admin creates a client credential in the Management Portal, yielding a clientId and clientSecret.
  2. Your service calls generateToken on the Tokens API to exchange the credential pair for a short-lived token.
  3. Use the returned token in the Authorization header for all data API requests. Tokens expire after 1 hour.

If your credential covers multiple companies, include "companyId" in the input to scope the token.

See Generate API Credentials for instructions.

Request
curl -X POST https://api.udacity.com/api/public/api/v1/tokens/graphql \
  -H "Content-Type: application/json" \
  -d '{
    "query": "mutation($input: GenerateTokenInput!) { generateToken(input: $input) { unredactedToken expiresIn } }",
    "variables": {
      "input": {
        "clientId": "udcl_YOUR_CLIENT_ID",
        "clientSecret": "udcs_YOUR_CLIENT_SECRET"
      }
    }
  }'
Usage

Using a token

Include your token in the Authorization header using the Token scheme (not Bearer).

unredactedTokenstring

Your bearer token. Store it securely — it grants full API access.

expiresIninteger (seconds)

Token lifetime — 3600 by default (1 hour).

Header
Authorization: Token YOUR_TOKEN
curl Example
curl -X POST https://api.udacity.com/api/public/api/v1/catalog/graphql \
  -H "Content-Type: application/json" \
  -H "Authorization: Token YOUR_TOKEN" \
  -d '{"query": "{ catalog { companyId programs { key title } } }"}'
JavaScript Example
const response = await fetch(
  'https://api.udacity.com/api/public/api/v1/catalog/graphql',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'Token YOUR_TOKEN',
    },
    body: JSON.stringify({
      query: `{
        catalog {
          companyId
          programs { key title type }
          assessments { id title }
          learningPlans { id title }
        }
      }`,
    }),
  }
);

const data = await response.json();
console.log(data);
Authorization

Token scopes

A token must carry scopes that grant access to specific API domains. If your token lacks the required scope, the API returns a 403 Forbidden error.

Tokens generated via client credentials automatically include a COMPANY scope for the target company. No manual scope configuration is needed.

Errors

Error responses

401 Unauthorized

Missing, invalid, or expired token.

403 Forbidden

Token is valid but lacks the required scope.

429 Too Many Requests

Rate limit exceeded — see Rate Limits. The generateToken endpoint has an additional per-credential limit of 50 requests/minute.

Error Response
{
  "errors": [{
    "message": "not authorized",
    "extensions": { "code": "UNAUTHORIZED" }
  }]
}
Best Practices

Security recommendations

  • Never hardcode credentials or tokens in source code. Use environment variables or a secrets manager.
  • Prefer client credentials for production. Tokens are short-lived, credentials are company-owned, and rotation is programmatic.
  • Refresh tokens proactively. Check expiresIn and schedule a refresh before expiry.
  • Use revokeExisting: true when rotating. This atomically revokes overlapping credentials.
  • Revoke credentials you no longer use. Tokens from a revoked credential continue working until they expire.

See Best Practices for more.