The Rose API allows you to upload, configure, and solve optimization models programmatically. The full process consists of three main steps:
- Authentication - Secure access using your API key and secret
- Uploading the model - Send your existing model file to the Rose platform
- Solver configuration and execution - Choose solver settings and initiate the solve
Below is a complete Python example that walks through each of these steps using the Rose API. We’ll break it down section by section in the following documentation first, then show the full script at the end.
import requests import hmac import hashlib import json import os from datetime import datetime, UTC, timedelta MPS_FILE_PATH = "./path/to/bubbles_brewery.mps" PROBLEM_ID = "bubbles_brewery.mps" TOKEN_CACHE_FILE = ".token_cache.json" # End user configuration BASE_URL = "https://sapi.prod.solaas.simplerose.com/api/1.0" API_KEY_ID = os.getenv("API_KEY_ID") API_KEY_SECRET = os.getenv("API_KEY_SECRET") ACCOUNT_ID = os.getenv("ACCOUNT_ID") if not API_KEY_ID or not API_KEY_SECRET or not ACCOUNT_ID: raise EnvironmentError("Missing API_KEY_ID, API_KEY_SECRET, or ACCOUNT_ID environment variable.") # Main workflow if __name__ == "__main__": token = load_token() or authenticate() print("✅ Using token.") print("🔗 Requesting upload URL...") upload_url = request_upload_url(token) print("⬆️ Uploading MPS file...") upload_file_to_presigned_url(upload_url, MPS_FILE_PATH) print("🧮 Submitting solve...") solve_ids = submit_solve(token) print(json.dumps(solve_ids, indent=4))
Authentication
To interact with the Rose API, you must first authenticate using your API signature. This will return an access token that is valid for 24 hours. Save the token and its expiration timestamp locally—ideally in a JSON file—so that your application can reuse it until it expires. That way you do not request a new token for every API call. You only need to request a token once every 24 hours.
First-time authentication
To authenticate for the first time:
- Generate your API signature
See How to generate your API signature for detailed instructions - Send the signature to the authentication endpoint
- Receive a response containing:
- An
access_token
(used for all API requests) - An
expires_in field
(number of seconds the token is valid—typically 86,400 for 24 hours)
- An
Recommended token storage
We recommend saving the following fields to a local JSON file in a format like this:
{ "access_token": "your_token_here", "expires_at": "2038-01-01T03:14:15.926536" }
This approach avoids unnecessary token requests and streamlines your integration with the Rose API.
Sample Python code
# Authentication utilities def generate_signature(api_key_id, api_key_secret): utc_date = datetime.now(UTC).strftime("%Y-%m-%d") message = f"simplerose:{utc_date}:{api_key_id}" return hmac.new(api_key_secret.encode(), message.encode(), hashlib.sha256).hexdigest() def save_token(token): with open(TOKEN_CACHE_FILE, "w") as f: expires = (datetime.now() + timedelta(seconds=token["expires_in"])).isoformat() json.dump({ "access_token": token["access_token"], "expires": expires }, f) def load_token(): if not os.path.exists(TOKEN_CACHE_FILE): return None with open(TOKEN_CACHE_FILE, "r") as f: data = json.load(f) if datetime.now() > datetime.fromisoformat(data["expires"]): return None return data["access_token"] def authenticate(): signature = generate_signature(API_KEY_ID, API_KEY_SECRET) payload = {"api_key_id": API_KEY_ID, "signature": signature} response = requests.post(f"{BASE_URL}/authenticate", json=payload) response.raise_for_status() token = response.json() save_token(token) return token["access_token"]
Uploading the model
Before uploading your model file to the Rose API, you must request a pre-signed URL. This is a temporary, secure link that allows you to upload your model directly. You need to define a PROBLEM_ID
, the name that you want your model to appear as in the system. This should include the appropriate extension (.mps
for MPS file or .lp
for LP files). You also need to pass in a valid access token to get a pre-signed URL.
Once you receive the pre-signed URL in the response, you can upload your model file to that location using a standard HTTP PUT request. The pre-signed URL is valid for 1 hour. The file content must match the format implied by the file extension in the PROBLEM_ID
.
# File upload step def request_upload_url(token): url = f"{BASE_URL}/account/{ACCOUNT_ID}/problem/{PROBLEM_ID}" headers = {"Authorization": f"Bearer {token}"} response = requests.post(url, headers=headers, json={}) response.raise_for_status() return response.json()["upload_url"] def upload_file_to_presigned_url(upload_url, file_path): with open(file_path, "rb") as f: response = requests.put(upload_url, data=f) response.raise_for_status() print("📤 File uploaded successfully.")
Solver configuration and execution
In this step, you’ll submit a solve request that references:
- One or more solver configurations (e.g., time limits, solver strategies), and
- One or more previously uploaded problems (by
PROBLEM_ID
)
Below is an example with one solver configuration and one problem. But multiple solver configurations can be specified and multiple problems can be started at once.
# Start solving step def submit_solve(token): url = f"{BASE_URL}/account/{ACCOUNT_ID}/solve" headers = { "Authorization": f"Bearer {token}", "Content-Type": "application/json" } payload = { "solver_config": [ { "basic": { "max_time_seconds": 60, }, }, ], "problems": [ { "name": PROBLEM_ID } ], "solves": [ { "problem": 0, "solver_config": 0 } ] } response = requests.put(url, headers=headers, json=payload) if response.status_code != 200: print("❌ Solve submission failed.") print("Status code:", response.status_code) print("Response:", response.text) response.raise_for_status() solve_ids = response.json()["solve_ids"] print(f"🚀 Solve submitted. Solve IDs:") return solve_ids
Comments
0 comments
Please sign in to leave a comment.