> For the complete documentation index, see [llms.txt](https://help.aximo.autify.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.aximo.autify.com/api-reference/uploads.md).

# Uploads

Upload and manage mobile app binaries (APK/IPA) for testing.

## List uploaded apps

> Returns previously uploaded apps that are ready to use or currently processing.\
> Automatically validates uploads against Device Farm and re-uploads expired entries.<br>

```json
{"openapi":"3.0.3","info":{"title":"Aximo API","version":"1.0.0"},"tags":[{"name":"Uploads","description":"Upload and manage mobile app binaries (APK/IPA) for testing."}],"servers":[{"url":"/","description":"Current environment"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Organization API key generated from Settings → API Keys."}},"schemas":{"Upload":{"type":"object","required":["id","fileName","fileType","status","uploadedAt","isExpired"],"properties":{"id":{"type":"string","format":"uuid"},"uploadArn":{"type":"string","nullable":true,"description":"Encrypted upload identifier token. Available once status is `succeeded`. Pass this value as `uploadArn` when creating sessions."},"fileName":{"type":"string"},"fileSize":{"type":"integer","nullable":true,"description":"File size in bytes."},"fileType":{"type":"string","enum":["ANDROID_APP","IOS_APP"]},"appName":{"type":"string","nullable":true,"description":"Human-readable app name (auto-extracted from APK/IPA)."},"appVersion":{"type":"string","nullable":true},"identifier":{"type":"string","nullable":true,"description":"Bundle ID (iOS) or package name (Android)."},"iconData":{"type":"string","nullable":true,"description":"Base64-encoded PNG app icon."},"status":{"$ref":"#/components/schemas/UploadStatus"},"message":{"type":"string","nullable":true,"description":"Status details (e.g. error message on failure)."},"uploadedAt":{"type":"string","format":"date-time"},"isExpired":{"type":"boolean","description":"Whether the upload has expired on Device Farm (auto-expires after 30 days)."}}},"UploadStatus":{"type":"string","enum":["initialized","processing","succeeded","failed"],"description":"- `initialized` — record created, waiting for file upload and submission.\n- `processing` — worker is uploading to Device Farm.\n- `succeeded` — ready to use in sessions.\n- `failed` — processing failed (see `message` for details).\n"},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}}}},"responses":{"Unauthorized":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limit exceeded — e.g. the daily session limit was reached for the\norganization, or too many API requests were sent in a short window\n(retry after the number of seconds in the `Retry-After` header).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/uploads":{"get":{"operationId":"listUploads","summary":"List uploaded apps","description":"Returns previously uploaded apps that are ready to use or currently processing.\nAutomatically validates uploads against Device Farm and re-uploads expired entries.\n","tags":["Uploads"],"parameters":[{"name":"fileType","in":"query","schema":{"type":"string","enum":["ANDROID_APP","IOS_APP"]},"description":"Filter by app type."}],"responses":{"200":{"description":"List of uploads.","content":{"application/json":{"schema":{"type":"object","required":["uploads"],"properties":{"uploads":{"type":"array","items":{"$ref":"#/components/schemas/Upload"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```

## Create an app upload

> Creates an upload record and returns a presigned URL for uploading the app binary.\
> \
> \*\*Flow:\*\*\
> 1\. Call this endpoint to get \`uploadId\` and \`presignedUrl\`.\
> 2\. \`PUT\` the binary file to \`presignedUrl\`.\
> 3\. Call \`POST /api/uploads/{uploadId}/submit\` to start processing.\
> 4\. Poll \`GET /api/uploads/{uploadId}\` until \`status\` is \`succeeded\`.\
> 5\. Use the \`uploadArn\` token in \`POST /api/sessions\` to start a mobile test.<br>

```json
{"openapi":"3.0.3","info":{"title":"Aximo API","version":"1.0.0"},"tags":[{"name":"Uploads","description":"Upload and manage mobile app binaries (APK/IPA) for testing."}],"servers":[{"url":"/","description":"Current environment"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Organization API key generated from Settings → API Keys."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}}}},"responses":{"Unauthorized":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limit exceeded — e.g. the daily session limit was reached for the\norganization, or too many API requests were sent in a short window\n(retry after the number of seconds in the `Retry-After` header).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/uploads":{"post":{"operationId":"createUpload","summary":"Create an app upload","description":"Creates an upload record and returns a presigned URL for uploading the app binary.\n\n**Flow:**\n1. Call this endpoint to get `uploadId` and `presignedUrl`.\n2. `PUT` the binary file to `presignedUrl`.\n3. Call `POST /api/uploads/{uploadId}/submit` to start processing.\n4. Poll `GET /api/uploads/{uploadId}` until `status` is `succeeded`.\n5. Use the `uploadArn` token in `POST /api/sessions` to start a mobile test.\n","tags":["Uploads"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["fileName"],"properties":{"fileName":{"type":"string","minLength":1,"description":"Original file name (must end in `.apk`, `.ipa`, or `.zip`)."},"fileSize":{"type":"integer","description":"File size in bytes (informational)."},"platform":{"type":"string","enum":["ANDROID","IOS"],"description":"Platform hint for `.zip` files."}}}}}},"responses":{"201":{"description":"Upload record created.","content":{"application/json":{"schema":{"type":"object","required":["uploadId","presignedUrl","fileType"],"properties":{"uploadId":{"type":"string","format":"uuid"},"presignedUrl":{"type":"string","description":"URL to PUT the binary file to."},"fileType":{"type":"string","enum":["ANDROID_APP","IOS_APP"]}}}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```

## Get upload status

> Returns the current processing status of an upload. Poll this endpoint\
> after calling \`POST /api/uploads/{uploadId}/submit\` until \`status\` is\
> \`succeeded\` or \`failed\`.<br>

```json
{"openapi":"3.0.3","info":{"title":"Aximo API","version":"1.0.0"},"tags":[{"name":"Uploads","description":"Upload and manage mobile app binaries (APK/IPA) for testing."}],"servers":[{"url":"/","description":"Current environment"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Organization API key generated from Settings → API Keys."}},"schemas":{"Upload":{"type":"object","required":["id","fileName","fileType","status","uploadedAt","isExpired"],"properties":{"id":{"type":"string","format":"uuid"},"uploadArn":{"type":"string","nullable":true,"description":"Encrypted upload identifier token. Available once status is `succeeded`. Pass this value as `uploadArn` when creating sessions."},"fileName":{"type":"string"},"fileSize":{"type":"integer","nullable":true,"description":"File size in bytes."},"fileType":{"type":"string","enum":["ANDROID_APP","IOS_APP"]},"appName":{"type":"string","nullable":true,"description":"Human-readable app name (auto-extracted from APK/IPA)."},"appVersion":{"type":"string","nullable":true},"identifier":{"type":"string","nullable":true,"description":"Bundle ID (iOS) or package name (Android)."},"iconData":{"type":"string","nullable":true,"description":"Base64-encoded PNG app icon."},"status":{"$ref":"#/components/schemas/UploadStatus"},"message":{"type":"string","nullable":true,"description":"Status details (e.g. error message on failure)."},"uploadedAt":{"type":"string","format":"date-time"},"isExpired":{"type":"boolean","description":"Whether the upload has expired on Device Farm (auto-expires after 30 days)."}}},"UploadStatus":{"type":"string","enum":["initialized","processing","succeeded","failed"],"description":"- `initialized` — record created, waiting for file upload and submission.\n- `processing` — worker is uploading to Device Farm.\n- `succeeded` — ready to use in sessions.\n- `failed` — processing failed (see `message` for details).\n"},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}}}},"responses":{"Unauthorized":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limit exceeded — e.g. the daily session limit was reached for the\norganization, or too many API requests were sent in a short window\n(retry after the number of seconds in the `Retry-After` header).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/uploads/{uploadId}":{"get":{"operationId":"getUploadStatus","summary":"Get upload status","description":"Returns the current processing status of an upload. Poll this endpoint\nafter calling `POST /api/uploads/{uploadId}/submit` until `status` is\n`succeeded` or `failed`.\n","tags":["Uploads"],"parameters":[{"name":"uploadId","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"UUID returned by `POST /api/uploads`."}],"responses":{"200":{"description":"Upload details.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Upload"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Upload not found or belongs to another organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```

## Upload app binary

> Upload the app binary (APK/IPA) for a previously created upload record.\
> Use this endpoint when the \`presignedUrl\` from \`POST /api/uploads\` points to\
> your Aximo instance (local development). In production, upload directly to the\
> S3 presigned URL instead.<br>

```json
{"openapi":"3.0.3","info":{"title":"Aximo API","version":"1.0.0"},"tags":[{"name":"Uploads","description":"Upload and manage mobile app binaries (APK/IPA) for testing."}],"servers":[{"url":"/","description":"Current environment"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Organization API key generated from Settings → API Keys."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}}}},"responses":{"Unauthorized":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limit exceeded — e.g. the daily session limit was reached for the\norganization, or too many API requests were sent in a short window\n(retry after the number of seconds in the `Retry-After` header).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/uploads/{uploadId}":{"put":{"operationId":"uploadFile","summary":"Upload app binary","description":"Upload the app binary (APK/IPA) for a previously created upload record.\nUse this endpoint when the `presignedUrl` from `POST /api/uploads` points to\nyour Aximo instance (local development). In production, upload directly to the\nS3 presigned URL instead.\n","tags":["Uploads"],"parameters":[{"name":"uploadId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"File uploaded successfully.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"400":{"description":"No body provided.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Upload not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```

## Submit upload for processing

> Signals that the file upload is complete and triggers background processing.\
> The worker will parse the app metadata, upload it to AWS Device Farm, and\
> update the status.\
> \
> Poll \`GET /api/uploads/{uploadId}\` until \`status\` is \`succeeded\` or \`failed\`.<br>

```json
{"openapi":"3.0.3","info":{"title":"Aximo API","version":"1.0.0"},"tags":[{"name":"Uploads","description":"Upload and manage mobile app binaries (APK/IPA) for testing."}],"servers":[{"url":"/","description":"Current environment"}],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Organization API key generated from Settings → API Keys."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}}}},"responses":{"Unauthorized":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limit exceeded — e.g. the daily session limit was reached for the\norganization, or too many API requests were sent in a short window\n(retry after the number of seconds in the `Retry-After` header).\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InternalError":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"paths":{"/api/uploads/{uploadId}/submit":{"post":{"operationId":"submitUpload","summary":"Submit upload for processing","description":"Signals that the file upload is complete and triggers background processing.\nThe worker will parse the app metadata, upload it to AWS Device Farm, and\nupdate the status.\n\nPoll `GET /api/uploads/{uploadId}` until `status` is `succeeded` or `failed`.\n","tags":["Uploads"],"parameters":[{"name":"uploadId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"202":{"description":"Upload submitted for processing.","content":{"application/json":{"schema":{"type":"object","required":["success","workflowId"],"properties":{"success":{"type":"boolean"},"workflowId":{"type":"string","description":"Background workflow ID for tracking."}}}}}},"400":{"description":"Upload not in the correct state (must be `initialized` with a file uploaded).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Upload not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}}}}
```
