Operational Flows

This section details the step-by-step operational flows for the most common transactions within the Evercycle API system.

Flow 1: Authenticate and Store Tokens

Actors: HTTP client, Flask server, Evercycle backend

  1. Client sends POST /api/auth with JSON body containing username and password.

  2. api_server.py validates that both fields are present; returns 400 if not.

  3. api_server.py calls api_client.authenticate(username, password).

  4. evercycle_api.py builds the payload and POSTs to https://api.evercycle.io/v1/auth/signin.

  5. On success, the backend returns an AuthenticationResult with: * AccessToken * IdToken * RefreshToken

  6. evercycle_api.py writes these three tokens to evercycle-api/auth.properties.

  7. api_server.py updates global variables: * refresh_token ← RefreshToken * token_expiry ← now + 3600 seconds

  8. Flask session is marked authenticated.

  9. Response 200 OK with status “success” is returned to the client.

Flow 2: Call a Protected API with Valid Token

Actors: HTTP client, Flask server, Evercycle backend

  1. Client sends a request to /api/get-all with method GET.

  2. call_api('get-all') is invoked.

  3. refresh_auth_token() is called.

  4. is_token_valid() checks token_expiry against now + 60s.

  5. Token is valid → function returns True immediately.

  6. api_server.py prepares parameters: * For GET, parameters come from request.args (query string). * No special path-parameter handling needed for get-all.

  7. api_client.call_api('get-all') is executed.

  8. Config file config/get-all.json is loaded.

  9. Auth headers are injected: * access-tokenaccess_token from auth.properties * Authorizationid_token from auth.properties

  10. HTTP GET is dispatched to https://api.evercycle.io/v1/asset.

  11. Response JSON is returned to the client wrapped in: {"status": "success", "data": <response>}

Flow 3: Call an API with Expired Token (Auto-Refresh)

Actors: HTTP client, Flask server, Evercycle backend

  1. Client sends GET /api/get-all.

  2. call_api('get-all') begins.

  3. refresh_auth_token() detects that token_expiry has passed.

  4. Server attempts to POST to https://api.evercycle.io/v1/auth/refresh with the stored refresh_token.

  5. If refresh succeeds: * New tokens are extracted. * auth.properties is overwritten. * token_expiry is updated. * Flow continues as in Flow 2.

  6. If refresh fails: * Server falls back to re-authentication. * It reads config/auth-signin.json for username/password. * Calls api_client.authenticate(username, password). * On success, updates globals and proceeds. * On failure, returns 401 Unauthorized to the client.

Flow 4: Get Asset by ID (Runtime Path Patching)

Actors: HTTP client, Flask server

  1. Client sends GET /api/get-asset-id?id=12345.

  2. call_api('get-asset-id') is invoked.

  3. Authentication check passes (Flow 2/3 logic).

  4. Because api_name == 'get-asset-id', the server enters special handling: * Extracts asset_id from request.args.get('id'). * Overrides api_info['path'] to /v1/asset/{asset_id}. * Dynamically monkey-patches api_client.call_api with patched_call_api.

  5. The patched function ignores the normal config-driven URL construction and directly builds https://api.evercycle.io/v1/asset/12345.

  6. It injects headers and calls requests.get.

  7. The response is parsed and returned to the client.

  8. Note: the monkey-patch is temporary for the duration of that single call.

Flow 5: Create a New Asset

Actors: HTTP client, Flask server

  1. Client sends POST /api/create with JSON body fields.

  2. call_api('create') begins.

  3. Authentication is verified.

  4. Server loads config/create.json to obtain default body values.

  5. Request JSON body is merged on top of the defaults: merged_data = default_body.copy(); merged_data.update(request.json)

  6. The merged JSON string is passed as a parameter to api_client.call_api.

  7. api_client.call_api parses the JSON and sets user_config['body'].

  8. HTTP POST is dispatched to https://api.evercycle.io/v1/asset/create.

  9. Response is returned to the client.

Flow 6: Edit Asset (PUT with Path Parameter)

Actors: HTTP client, Flask server

  1. Client sends PUT /api/edit-asset-id with JSON body containing id and any fields to update.

  2. call_api('edit-asset-id') begins.

  3. Authentication is verified.

  4. Server extracts asset_id from body id field.

  5. It loads config/edit-asset-id.json for default body values.

  6. Request body (minus id) is merged into defaults.

  7. api_info['path'] and api_info['url'] are both overridden to /v1/asset/{asset_id}.

  8. api_client.call_api receives asset_id and the merged JSON string.

  9. The path parameter {id} is substituted in the URL.

  10. HTTP PUT is dispatched.

Flow 7: Grade Update (PUT with Multiple Path Parameters)

Actors: HTTP client, Flask server

  1. Client sends PUT /api/grade with JSON body containing id, grade, and optionally price.

  2. call_api('grade') begins.

  3. Server extracts asset_id and grade_name from the body.

  4. It loads config/grade.json for defaults.

  5. Body fields other than id and grade are merged into defaults.

  6. api_info['path'] and api_info['url'] are overridden to /v1/pricebook/{asset_id}/{grade_name}.

  7. api_client.call_api substitutes both path parameters.

  8. HTTP PUT is dispatched to the constructed URL.

Flow 8: CLI Auth and Config Generation

Actors: Terminal user, api_runner.py, filesystem

  1. User runs python3 api_runner.py generate inside evercycle-api/.

  2. ApiRunner.load_endpoints() reads all *.md files in the directory.

  3. Each markdown file is parsed by parse_markdown_file(): * First line → path * Second line → description * Regex search → method and url * Table sections → headers, parameters, body_params

  4. For each endpoint, a JSON config file is written to config/{api_name}.json with empty/default values for headers, path_params, query_params, and body.

  5. User edits the JSON config files to set desired values.

  6. User runs python3 api_runner.py run auth-signin.

  7. On success, _handle_auth_signin_response() extracts tokens and writes auth.properties.

  8. _update_config_files_with_tokens() iterates all other JSON configs and injects the new tokens into their headers objects.

Flow 9: Interactive Menu Runner

Actors: Terminal user, evercycle_api_runner.py

  1. User runs python3 evercycle_api_runner.py.

  2. EvercycleApiRunner loads all markdown specs.

  3. A numbered menu is displayed.

  4. User selects an endpoint.

  5. prepare_api_call() prompts for: * Header values * Path parameter values * Query parameter values * Body parameter values (with JSON input for objects/arrays)

  6. Types are coerced (number, boolean) based on the parameter type declared in the markdown.

  7. ApiClient.call_endpoint() is invoked with the collected data.

  8. Response status, headers, and body are printed to the terminal.