Making Your First API Call ========================== This guide walks you through making your first authenticated API call to the ops-db-api. .. contents:: Table of Contents :local: :depth: 2 Prerequisites ------------- Before proceeding, ensure you have: * Completed the :doc:`installation` steps * The API server running locally * ``curl`` or a similar HTTP client installed Starting the API Server ----------------------- If the server isn't already running, start it: .. code-block:: bash cd ops-db-api source venv/bin/activate uvicorn ccat_ops_db_api.main:app --reload --port 8000 The server will start on ``http://localhost:8000``. Accessing the API Documentation -------------------------------- FastAPI provides interactive API documentation out of the box: **Swagger UI** (Recommended for exploration) Visit: http://localhost:8000/docs **ReDoc** (Alternative documentation view) Visit: http://localhost:8000/redoc The Swagger UI allows you to: * Browse all available endpoints * View request/response schemas * Test endpoints directly from your browser * See authentication requirements Making an Unauthenticated Request ---------------------------------- Start with a simple health check that doesn't require authentication: .. code-block:: bash curl http://localhost:8000/health Expected response: .. code-block:: json { "status": "healthy", "database": "connected", "redis": "connected", "transaction_buffer": { "size": 0, "failed": 0 }, "background_processor": "running" } This confirms that: * The API is running * Database connection is working * Redis connection is working * Transaction buffering system is operational Getting an API Token -------------------- For authenticated requests, you need an API token. There are several ways to obtain one: Method 1: Demo Token (Development Only) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For local development, you can use a demo token endpoint: .. code-block:: bash curl -X POST http://localhost:8000/api/demo/create-demo-token Expected response: .. code-block:: json { "token": "demo_token_abc123xyz789...", "user_id": 1, "role": "admin" } .. warning:: Demo tokens should **never** be used in production. They are only for local testing. Method 2: Admin Script (Recommended) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use the admin script to create a proper API token: .. code-block:: bash # Create an admin user if not exists ./create_admin_user.sh # Then use the UI or CLI to generate a token Method 3: GitHub OAuth (For UI Users) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you have GitHub OAuth configured, you can log in through the web UI and generate a token from your profile. Making an Authenticated Request -------------------------------- Once you have a token, include it in the ``Authorization`` header: Format ~~~~~~ .. code-block:: bash curl -H "Authorization: Bearer YOUR_TOKEN" \ http://localhost:8000/ENDPOINT Example: Get Current User ~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash TOKEN="your_actual_token_here" curl -H "Authorization: Bearer $TOKEN" \ http://localhost:8000/auth/me Expected response: .. code-block:: json { "id": 1, "username": "admin", "email": "admin@example.com", "full_name": "Admin User", "roles": ["admin"], "is_active": true, "created_at": "2025-01-01T00:00:00Z" } Example: List Instruments ~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash curl -H "Authorization: Bearer $TOKEN" \ http://localhost:8000/instruments/ Expected response: .. code-block:: json [ { "id": 1, "name": "CCAT-prime", "description": "Prime-Cam instrument", "is_active": true } ] Example: Get Transfer Overview ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash curl -H "Authorization: Bearer $TOKEN" \ http://localhost:8000/api/transfer/overview Expected response: .. code-block:: json { "total_packages": 42, "pending_transfers": 3, "active_transfers": 2, "completed_transfers": 37, "failed_transfers": 0, "total_data_size_gb": 1250.5 } Making a POST Request --------------------- To create or modify data, use POST requests with JSON payloads: Example: Create User Preference ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash curl -X POST http://localhost:8000/api/demo/update-user-preferences \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "user_id": 1, "preferences": { "theme": "dark", "language": "en", "notifications": true } }' Expected response: .. code-block:: json { "status": "success", "message": "User preferences updated", "transaction_id": "abc123" } Using the Interactive Documentation ------------------------------------ The easiest way to explore the API is through Swagger UI at http://localhost:8000/docs: Step 1: Authorize ~~~~~~~~~~~~~~~~~~ 1. Click the **Authorize** button (green lock icon) 2. Enter your token in the format: ``Bearer YOUR_TOKEN`` 3. Click **Authorize**, then **Close** Step 2: Test an Endpoint ~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Expand any endpoint (e.g., ``GET /instruments/``) 2. Click **Try it out** 3. Fill in any required parameters 4. Click **Execute** 5. View the response below Step 3: View Request/Response Schemas ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Scroll down to see the **Schemas** section * Each data model is documented with field types and constraints * Click on schemas to expand and explore Common Response Codes --------------------- Understanding HTTP status codes: **200 OK** Request succeeded, data returned **201 Created** Resource created successfully **400 Bad Request** Invalid request format or missing required fields **401 Unauthorized** Missing or invalid authentication token **403 Forbidden** Valid token but insufficient permissions **404 Not Found** Requested resource doesn't exist **500 Internal Server Error** Server error (check logs) Testing Transaction Buffering ------------------------------ If you're running with ``SITE_TYPE=secondary``, you can test the transaction buffering system: Create a Buffered Observation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash curl -X POST http://localhost:8000/api/demo/create-observation \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "obs_data": { "obs_unit_id": 1, "start_time": "2025-01-01T00:00:00Z", "end_time": "2025-01-01T01:00:00Z", "mean_pwv": 2.5, "mean_elevation": 45.0, "package_name": "test_package_001", "instrument_module_configuration_id": 1 }, "raw_files": [ { "name": "test_file_001.fits", "path": "/data/test_file_001.fits", "size": 1024000, "checksum": "abc123", "file_type": "fits" } ] }' Check Buffer Status ~~~~~~~~~~~~~~~~~~~ .. code-block:: bash curl http://localhost:8000/buffer-stats Expected response: .. code-block:: json { "pending_transactions": 1, "failed_transactions": 0, "processing_rate": 1.0 } Troubleshooting --------------- 401 Unauthorized Error ~~~~~~~~~~~~~~~~~~~~~~ If you receive a 401 error: 1. Verify your token is correct and not expired 2. Ensure you're using the correct header format: ``Authorization: Bearer TOKEN`` 3. Check that the token exists in the database Connection Refused ~~~~~~~~~~~~~~~~~~ If curl can't connect: 1. Verify the API server is running 2. Check the correct port (default: 8000) 3. Try ``http://127.0.0.1:8000`` instead of ``localhost`` Empty Response or Error ~~~~~~~~~~~~~~~~~~~~~~~ If you get unexpected responses: 1. Check the API logs in the terminal where uvicorn is running 2. Verify your database has data (some endpoints return empty arrays for empty tables) 3. Try the same request in Swagger UI for better error messages Next Steps ---------- Now that you can make API calls, explore: * :doc:`running-locally` - Set up the full stack with Docker Compose * :doc:`../tutorials/simple-endpoints/simple-read-endpoint` - Build your own endpoints * :doc:`../architecture/system-overview` - Understand how the API works * :doc:`../deep-dive/transaction-buffering/overview` - Learn about the buffering system Using Python to Make API Calls ------------------------------- For programmatic access, use the ``requests`` library: .. code-block:: python import requests BASE_URL = "http://localhost:8000" TOKEN = "your_token_here" headers = { "Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json" } # Health check response = requests.get(f"{BASE_URL}/health") print(response.json()) # Authenticated request response = requests.get(f"{BASE_URL}/auth/me", headers=headers) print(response.json()) # POST request data = { "user_id": 1, "preferences": {"theme": "dark"} } response = requests.post( f"{BASE_URL}/api/demo/update-user-preferences", headers=headers, json=data ) print(response.json()) See :doc:`../tutorials/observatory-integration/service-scripts` for production-ready examples.