Processing API
Run server-side analytics on satellite imagery. Submit processing jobs for NDVI computation, change detection, and more. Jobs run asynchronously and results are delivered as COG files with a download URL.
Async Job Architecture
Processing jobs follow a submit-then-poll pattern. You submit a job definition, receive a job ID, and poll for status until the job completes.
POST /api/v1/process with the operation type, scene IDs, and parameters. Returns a job_id immediately.GET /api/v1/process/{jobId} to check job status. Status progresses: queuedprocessingcompletedcompleted, the response includes a result object with a pre-signed download URL for the output file.Submit a Job
/api/v1/processRequires authentication. Send a JSON body with the operation type and input scenes.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| operation | string | Required | The processing operation. One of: ndvi, change_detection |
| scene_ids | string[] | Required | Array of scene IDs to process. NDVI requires 1 scene; change detection requires exactly 2 (before and after). |
| params | object | Optional | Operation-specific parameters. See individual operation docs below. |
| webhook_url | string | Optional | URL to receive a POST callback when the job completes. The callback body includes the full job status response. |
Operations
Normalized Difference Vegetation Index
Computes NDVI from the red and NIR bands of a single scene. Output is a single-band COG with values ranging from -1.0 to 1.0. Bands are automatically resolved from the scene metadata.
{ "operation": "ndvi", "scene_ids": ["sentinel-2:S2B_MSIL2A_20250115T184929"], "params": { "colormap": "rdylgn" }}| Param | Default | Description |
|---|---|---|
| colormap | none | Optional colormap to apply. Options: rdylgn, viridis, greens. If omitted, output is raw float values. |
Change Detection
Compares two scenes of the same area at different times to detect changes. Requires exactly 2 scene IDs (before and after). Output is a classified change map with categories: no change, vegetation gain, vegetation loss, built-up gain, water change.
{ "operation": "change_detection", "scene_ids": [ "sentinel-2:S2B_MSIL2A_20240715T184929", "sentinel-2:S2B_MSIL2A_20250115T184929" ], "params": { "threshold": 0.15, "bands": ["red", "nir", "swir16"] }}| Param | Default | Description |
|---|---|---|
| threshold | 0.1 | Minimum spectral difference to classify as a change (0.0 - 1.0). Lower values detect more subtle changes. |
| bands | ["red","nir"] | Bands to use for the comparison. More bands improve classification accuracy but increase processing time. |
Complete Example: NDVI
Submit an NDVI job, poll for completion, and download the result.
cURL
"color: #6b7280"># Step 1: Submit the jobcurl -X POST "https://astraos.cloud/api/v1/process" \ -H "Authorization: Bearer astra_sk_live_your_key_here" \ -H "Content-Type: application/json" \ -d &"color: #6b7280">#39;{ "operation": "ndvi", "scene_ids": ["sentinel-2:S2B_MSIL2A_20250115T184929"], "params": { "colormap": "rdylgn" } }&"color: #6b7280">#39;"color: #6b7280"># Response: { "job_id": "job_abc123", "status": "queued", ... }"color: #6b7280"># Step 2: Poll for statuscurl "https://astraos.cloud/api/v1/process/job_abc123" \ -H "Authorization: Bearer astra_sk_live_your_key_here""color: #6b7280"># Response when complete:"color: #6b7280"># { "job_id": "job_abc123", "status": "completed", "result": { "href": "https://..." } }Python
import requestsimport timeAPI_KEY = "astra_sk_live_your_key_here"BASE = "https://astraos.cloud/api/v1"headers = {"Authorization": f"Bearer {API_KEY}"}"color: #6b7280"># Step 1: Submit the jobjob = requests.post( f"{BASE}/process", headers={**headers, "Content-Type": "application/json"}, json={ "operation": "ndvi", "scene_ids": ["sentinel-2:S2B_MSIL2A_20250115T184929"], "params": {"colormap": "rdylgn"}, },).json()print(f"Job submitted: {job[&"color: #6b7280">#39;job_id39;]} (status: {job[39;status39;]})")"color: #6b7280"># Step 2: Poll until completewhile job["status"] in ("queued", "processing"): time.sleep(3) job = requests.get( f"{BASE}/process/{job[&"color: #6b7280">#39;job_id39;]}", headers=headers, ).json() print(f" Status: {job[&"color: #6b7280">#39;status39;]}")"color: #6b7280"># Step 3: Download resultif job["status"] == "completed": url = job["result"]["href"] print(f"Downloading NDVI result from: {url}") import urllib.request urllib.request.urlretrieve(url, "ndvi_output.tif") print("Saved to ndvi_output.tif")else: print(f"Job failed: {job.get(&"color: #6b7280">#39;error39;, {}).get(39;message39;, 39;Unknown error39;)}")JavaScript
const API_KEY = "astra_sk_live_your_key_here";const BASE = "https://astraos.cloud/api/v1";const headers = { Authorization: `Bearer ${API_KEY}` };"color: #6b7280">// Step 1: Submit the jobconst submitRes = await fetch(`${BASE}/process`, { method: "POST", headers: { ...headers, "Content-Type": "application/json" }, body: JSON.stringify({ operation: "ndvi", scene_ids: ["sentinel-2:S2B_MSIL2A_20250115T184929"], params: { colormap: "rdylgn" }, }),});let job = await submitRes.json();console.log(`Job submitted: ${job.job_id} (status: ${job.status})`);"color: #6b7280">// Step 2: Poll until completewhile (job.status === "queued" || job.status === "processing") { await new Promise((r) => setTimeout(r, 3000)); const pollRes = await fetch(`${BASE}/process/${job.job_id}`, { headers }); job = await pollRes.json(); console.log(` Status: ${job.status}`);}"color: #6b7280">// Step 3: Use the resultif (job.status === "completed") { console.log(`Result URL: ${job.result.href}`);} else { console.error(`Job failed: ${job.error?.message}`);}Poll Job Status
/api/v1/process/{jobId}Returns the current status and metadata for a processing job.
1{2 "job_id": "job_abc123",3 "status": "completed",4 "operation": "ndvi",5 "scene_ids": ["sentinel-2:S2B_MSIL2A_20250115T184929"],6 "created_at": "2025-01-15T19:00:00Z",7 "completed_at": "2025-01-15T19:00:12Z",8 "duration_ms": 12340,9 "result": {10 "href": "https://storage.astraos.cloud/jobs/job_abc123/ndvi_output.tif?sig=...",11 "type": "image/tiff; application=geotiff; profile=cloud-optimized",12 "file:size": 8388608,13 "expires_at": "2025-01-16T19:00:00Z"14 }15}Job Statuses
| Status | Description |
|---|---|
| queued | Job is in the queue waiting to be picked up by a worker. |
| processing | Job is currently being executed. Input data has been fetched and computation is running. |
| completed | Job finished successfully. The result field contains the output download URL. |
| failed | Job encountered an error. The error field contains a code and message describing the failure. |