# API Specification for Partner Integration ## Overview This document defines the REST API endpoints for the multi-partner integration system, including enhanced job assignment, partner management, and data synchronization capabilities. ## Base URL ``` Production: https://api.agmission.com/v1 Staging: https://staging-api.agmission.com/v1 Development: http://localhost:3000/api ``` ## Authentication All API endpoints require authentication using Bearer tokens: ```http Authorization: Bearer ``` ## Partner Management APIs ### List All Partners ```http GET /api/partners ``` **Response:** ```json { "partners": [ { "_id": "partner_id_1", "code": "satloc", "name": "Satloc", "description": "Satloc partner account for managing SatLoc customer accounts", "active": true, "capabilities": [ "job_upload", "data_download", "real_time_sync" ], "apiVersion": "v2.1", "status": "online", "lastHealthCheck": "2025-07-18T10:30:00Z", "createdAt": "2025-01-15T08:00:00Z", "updatedAt": "2025-07-18T10:30:00Z" } ], "total": 1 } ``` ### Get Partner Details ```http GET /api/partners/{id} ``` **Path Parameters:** - `id` (string, required): The unique identifier of the partner **Response:** ```json { "_id": "partner_id_1", "code": "satloc", "name": "Satloc", "description": "Satloc integration for precision agriculture", "active": true, "capabilities": ["job_upload", "data_download", "real_time_sync"], "apiConfig": { "baseUrl": "https://api.satloc.com", "version": "v2.1", "rateLimit": { "requestsPerSecond": 10, "burstLimit": 50 } }, "integrationSettings": { "syncInterval": 60000, "batchSize": 100, "maxRetries": 3 }, "monitoring": { "status": "online", "lastHealthCheck": "2025-07-18T10:30:00Z", "responseTime": 250, "errorRate": 0.02 } } ``` ### Create Partner ```http POST /api/partners ``` **Request Body:** ```json { "name": "New Partner", "code": "NEWPARTNER", "description": "Integration with new partner system", "capabilities": ["job_upload", "data_download"], "apiConfig": { "baseUrl": "https://api.newpartner.com", "version": "v1.0" } } ``` **Response:** ```json { "_id": "new_partner_id", "name": "New Partner", "code": "NEWPARTNER", "description": "Integration with new partner system", "active": true, "capabilities": ["job_upload", "data_download"], "createdAt": "2025-07-18T11:00:00Z", "updatedAt": "2025-07-18T11:00:00Z" } ``` ### Update Partner ```http PUT /api/partners/{id} ``` **Path Parameters:** - `id` (string, required): The unique identifier of the partner **Request Body (partial updates supported):** ```json { "name": "Updated Partner Name", "description": "Updated partner description", "capabilities": ["job_upload", "data_download", "real_time_sync"] } ``` **Response:** ```json { "_id": "partner_id_1", "name": "Updated Partner Name", "code": "SATLOC", "description": "Updated partner description", "active": true, "capabilities": ["job_upload", "data_download", "real_time_sync"], "updatedAt": "2025-07-18T11:00:00Z" } ``` ### Delete Partner (Soft Delete) ```http DELETE /api/partners/{id} ``` **Path Parameters:** - `id` (string, required): The unique identifier of the partner **Response:** ```json { "ok": true } ``` **Note:** This endpoint performs a soft delete by setting `active: false`. The partner record remains in the database for audit purposes and existing relationships are preserved. ### Get Partner Status ```http POST /api/partners/getPartnerStatus ``` **Request Body:** ```json { "partner": "partner_id_1" } ``` **Response:** ```json { "partner": "satloc", "status": "online", "lastSync": "2025-07-18T10:30:00Z", "activeJobs": 15, "pendingSyncs": 2, "metrics": { "responseTime": { "average": 250, "p95": 500, "p99": 1000 }, "errorRate": 0.02, "successRate": 0.98, "dataVolume": { "uploaded": "1.2GB", "downloaded": "850MB" } }, "recentErrors": [ { "timestamp": "2025-07-18T09:45:00Z", "operation": "data_poll", "error": "Network timeout", "retryAttempt": 2 } ] } ``` ## Partner System User Management APIs ### List All Partner System Users ```http GET /api/partners/systemUsers ``` **Query Parameters:** - `partner` (string, optional): Filter by partner ID **Response:** ```json [ { "_id": "systemuser_id_1", "username": "customer123_satloc", "name": "Customer 123 SatLoc Integration", "active": true, "partner": { "_id": "partner_id_1", "name": "SatLoc", "partnerCode": "SATLOC" }, "customer": { "_id": "customer_id_1", "name": "John's Farm", "username": "johnsfarm" }, "companyId": "36c0f342-e4e2-4fcb-b219-9cd1fad2c1ff", "apiKey": "satloc_api_key_encrypted", "createdAt": "2025-01-15T08:00:00Z", "updatedAt": "2025-07-18T10:30:00Z" } ] ``` ### Create Partner System User ```http POST /api/partners/systemUsers ``` **Request Body:** ```json { "partnerId": "partner_id_1", "customerId": "customer_id_1", "username": "customer123_satloc", "password": "secure_password", "name": "Customer 123 SatLoc Integration", "active": true, "companyId": "36c0f342-e4e2-4fcb-b219-9cd1fad2c1ff", "apiKey": "partner_api_key", "apiSecret": "partner_api_secret", "metadata": { "integrationVersion": "v2.1", "capabilities": ["job_upload", "data_sync"] } } ``` **Response:** ```json { "_id": "systemuser_id_1", "username": "customer123_satloc", "name": "Customer 123 SatLoc Integration", "active": true, "partner": "partner_id_1", "customer": "customer_id_1", "companyId": "36c0f342-e4e2-4fcb-b219-9cd1fad2c1ff", "apiKey": "satloc_api_key_encrypted", "createdAt": "2025-07-18T10:30:00Z", "updatedAt": "2025-07-18T10:30:00Z" } ``` ### Get Partner System User by ID ```http GET /api/partners/systemUsers/{id} ``` **Path Parameters:** - `id` (string, required): The unique identifier of the partner system user **Response:** ```json { "_id": "systemuser_id_1", "username": "customer123_satloc", "name": "Customer 123 SatLoc Integration", "active": true, "partner": { "_id": "partner_id_1", "name": "SatLoc", "partnerCode": "SATLOC" }, "customer": { "_id": "customer_id_1", "name": "John's Farm", "username": "johnsfarm" }, "companyId": "36c0f342-e4e2-4fcb-b219-9cd1fad2c1ff", "apiKey": "satloc_api_key_encrypted", "metadata": { "integrationVersion": "v2.1", "capabilities": ["job_upload", "data_sync"] }, "createdAt": "2025-01-15T08:00:00Z", "updatedAt": "2025-07-18T10:30:00Z" } ``` ### Update Partner System User ```http PUT /api/partners/systemUsers/{id} ``` **Path Parameters:** - `id` (string, required): The unique identifier of the partner system user **Request Body (partial updates supported):** ```json { "name": "Updated Customer Integration Name", "active": false, "apiKey": "new_encrypted_api_key", "metadata": { "integrationVersion": "v2.2", "capabilities": ["job_upload", "data_sync", "real_time_monitoring"] } } ``` **Response:** ```json { "_id": "systemuser_id_1", "username": "customer123_satloc", "name": "Updated Customer Integration Name", "active": false, "partner": "partner_id_1", "customer": "customer_id_1", "companyId": "36c0f342-e4e2-4fcb-b219-9cd1fad2c1ff", "apiKey": "new_encrypted_api_key", "metadata": { "integrationVersion": "v2.2", "capabilities": ["job_upload", "data_sync", "real_time_monitoring"] }, "updatedAt": "2025-07-18T11:00:00Z" } ``` ### Delete Partner System User (Soft Delete) ```http DELETE /api/partners/systemUsers/{id} ``` **Path Parameters:** - `id` (string, required): The unique identifier of the partner system user **Response:** ```json { "ok": true } ``` **Note:** This endpoint performs a soft delete by setting `active: false`. The record remains in the database for audit purposes. ### Get Partner Customers ```http GET /api/partners/customers ``` **Query Parameters:** - `partnerId` (string, required): The unique identifier of the partner **Description:** Retrieves all customers associated with a specific partner along with their subscription package information. **Response:** ```json [ { "_id": "customer_id_1", "name": "John Doe", "email": "john@example.com", "username": "johndoe", "contact": "+1234567890", "active": true, "country": "US", "createdAt": "2025-01-15T08:00:00Z", "updatedAt": "2025-07-18T10:30:00Z", "packageInfo": [ { "packageName": "price_1Qs3w1JxyI1MWs2Te7a45wBX", "status": "active", "startDate": "2025-01-01T00:00:00.000Z", "endDate": "2025-12-31T23:59:59.000Z", "recurring": true } ] } ] ``` ### Test Partner System User Authentication ```http POST /api/partners/systemUsers/testAuth ``` **Description:** Tests authentication credentials for a partner system user by calling the partner's authentication API. **Request Body:** ```json { "customerId": "customer_id_1", "partnerId": "partner_id_1", "username": "partner_username", "password": "partner_password" } ``` **Response:** ```json { "_id": "system_user_id", "username": "partner_username", "active": true, "partner": { "_id": "partner_id_1", "name": "Satloc", "partnerCode": "satloc" }, "customer": { "_id": "customer_id_1", "name": "John Doe", "username": "johndoe" }, "companyId": "123", "lastSyncAt": "2025-07-18T10:30:00Z", "syncStatus": "success", "authSuccess": true, "partnerApiResponse": { "authenticated": true, "userId": "partner_user_123", "companyId": "partner_company_123", "sessionToken": "abc123...", "expiresAt": "2025-07-18T14:30:00Z", "userDetails": { "userId": "partner_user_123", "permissions": ["read", "write"] } } } ``` **Error Response:** ```json { "_id": "system_user_id", "username": "partner_username", "active": true, "partner": { "_id": "partner_id_1", "name": "Satloc", "partnerCode": "satloc" }, "customer": { "_id": "customer_id_1", "name": "John Doe", "username": "johndoe" }, "authSuccess": false, "error": "Invalid credentials", "partnerApiResponse": null } ``` ## Enhanced Job Assignment APIs ### Assign Job to Aircraft/Partners ```http POST /jobs/{jobId}/assign ``` **Request Body:** ```json { "dlOp": { "type": 1, "mapOp": { "width": 1024, "height": 768, "zoom": 15 } }, "asUsers": [ { "uid": "internal_user_id_1", // Always use internal user IDs "partnerType": "internal" }, { "uid": "internal_user_id_2", // Internal user ID, not partner system user ID "partnerType": "satloc", "partnerConfig": { "aircraftId": "AC001", "priority": "high", "syncImmediate": true, "customFields": { "flightAltitude": 100, "sprayPattern": "overlap_20" } } } ], "avUsers": [ { "uid": "internal_user_id_3", // Internal user ID "partnerType": "dji" } ] } ``` **Response:** ```json { "ok": true, "assignments": [ { "assignmentId": "assign_123", "userId": "user_id_1", "partnerType": "internal", "status": "assigned", "syncStatus": "synced" }, { "assignmentId": "assign_124", "userId": "user_id_2", "partnerType": "satloc", "externalJobId": "satloc_job_456", "status": "assigned", "syncStatus": "syncing", "estimatedSyncTime": "2025-07-18T10:35:00Z" } ], "errors": [], "summary": { "totalAssignments": 2, "successfulAssignments": 2, "failedAssignments": 0, "partnerAssignments": 1, "internalAssignments": 1 } } ``` ### Get Job Assignments ```http GET /jobs/{jobId}/assignments ``` **Response:** ```json { "jobId": 123, "assignments": [ { "assignmentId": "assign_123", "user": { "_id": "user_id_1", "name": "Aircraft 001", "username": "AC001" }, "partnerType": "internal", "status": 1, "date": "2025-07-18T09:00:00Z", "syncState": { "jobUpload": { "status": "synced", "lastSuccess": "2025-07-18T09:00:00Z" }, "dataPolling": { "status": "idle" } } }, { "assignmentId": "assign_124", "user": { "_id": "user_id_2", "name": "Satloc Aircraft 002", "username": "SAT002" }, "partnerType": "satloc", "externalJobId": "satloc_job_456", "status": 0, "date": "2025-07-18T09:15:00Z", "syncState": { "jobUpload": { "status": "synced", "lastSuccess": "2025-07-18T09:16:00Z" }, "dataPolling": { "status": "polling", "lastAttempt": "2025-07-18T10:30:00Z", "nextPoll": "2025-07-18T10:31:00Z" } }, "metrics": { "syncDuration": 1250, "uploadTime": 800 } } ], "summary": { "total": 2, "pending": 1, "downloaded": 0, "completed": 1, "byPartner": { "internal": 1, "satloc": 1 } } } ``` ### Bulk Assign Jobs ```http POST /jobs/bulk-assign ``` **Request Body:** ```json { "jobs": [ { "jobId": 123, "assignments": [ { "uid": "user_id_1", "partnerType": "satloc" } ] }, { "jobId": 124, "assignments": [ { "uid": "user_id_2", "partnerType": "dji" } ] } ], "options": { "syncImmediate": false, "validateOnly": false } } ``` ### Get Available and Assigned Aircraft for Job ```http POST /jobs/assignments ``` **Description:** Retrieves available and assigned aircraft for a specific job, including aircraft details and assignment status. **Request Body:** ```json { "jobId": 123 } ``` **Response:** ```json { "avUsers": [ { "uid": "aircraft_id_1", "name": "Sprayer 001", "username": "SPR001", "active": true, "pkgActive": true, "tailNumber": "N123AB" }, { "uid": "aircraft_id_2", "name": "Helicopter 002", "username": "HELI002", "active": true, "pkgActive": true, "tailNumber": "N456CD" } ], "asUsers": [ { "uid": "aircraft_id_3", "name": "Drone 003", "username": "DRN003", "active": true, "pkgActive": true, "tailNumber": "N789EF", "assignStatus": 1 } ] } ``` **Field Descriptions:** - `avUsers`: Array of available aircraft that can be assigned to the job - `asUsers`: Array of aircraft already assigned to the job - `tailNumber`: Aircraft tail number (always present, empty string if not set) - `assignStatus`: Assignment status for assigned aircraft (0=NEW, 1=DOWNLOADED, 2=UPLOADED) ## Enhanced Job Download APIs ### Get Available Jobs (Enhanced) ```http GET /export/newJobs ``` **Query Parameters:** - `partnerType` (optional): Filter by partner type - `includeMetadata` (optional): Include sync metadata in response **Response:** ```json { "internal": [ { "assignmentId": "assign_123", "job": { "_id": 123, "name": "Field A Spraying", "startDate": "2025-07-18T08:00:00Z", "endDate": "2025-07-18T18:00:00Z" }, "date": "2025-07-18T09:00:00Z" } ], "partners": { "satloc": [ { "assignmentId": "assign_124", "job": { "_id": 124, "name": "Field B Application", "startDate": "2025-07-18T10:00:00Z", "endDate": "2025-07-18T16:00:00Z" }, "date": "2025-07-18T09:15:00Z", "externalJobId": "satloc_job_456", "syncStatus": "synced", "partnerMetadata": { "aircraftId": "SAT002", "priority": "high" } } ], "dji": [] }, "summary": { "totalAvailable": 2, "internal": 1, "partners": 1, "lastSync": "2025-07-18T10:30:00Z" } } ``` ### Download Job (Enhanced) ```http POST /export/downloadJob ``` **Request Body:** ```json { "jobId": 124, "partnerType": "satloc", "options": { "format": "native", // "native" or "converted" "includeMetadata": true, "compressionLevel": 6 } } ``` **Response:** - For internal jobs: Returns existing ZIP format - For partner jobs: Returns partner-specific format or converted format **Headers:** ``` Content-Type: application/zip Content-Disposition: attachment; filename="job_124_satloc.zip" X-Partner-Type: satloc X-External-Job-Id: satloc_job_456 X-Data-Format: native ``` ### Check Job Download Status ```http GET /export/jobs/{jobId}/download-status?partnerType={partnerType} ``` **Response:** ```json { "jobId": 124, "partnerType": "satloc", "status": "ready", // "pending", "syncing", "ready", "failed" "downloadUrl": "/export/downloadJob", "syncMetadata": { "lastSync": "2025-07-18T10:30:00Z", "dataSize": 1048576, "fileCount": 3, "format": "satloc_v2" }, "estimatedDownloadTime": 5000 // milliseconds } ``` ## Data Synchronization APIs ### Trigger Manual Sync ```http POST /sync/assignments/{assignmentId}/sync ``` **Request Body:** ```json { "operation": "job_upload", // "job_upload" or "data_poll" "priority": "high", // "low", "normal", "high" "force": false // Force sync even if recently attempted } ``` **Response:** ```json { "syncId": "sync_789", "assignmentId": "assign_124", "operation": "job_upload", "status": "queued", "estimatedCompletion": "2025-07-18T10:35:00Z", "position": 3 // Position in queue } ``` ### Get Sync Status ```http GET /sync/assignments/{assignmentId}/status ``` **Response:** ```json { "assignmentId": "assign_124", "currentOperations": [ { "operation": "data_poll", "status": "running", "startTime": "2025-07-18T10:30:00Z", "progress": 75, "metadata": { "filesChecked": 3, "filesFound": 1, "dataSize": 524288 } } ], "lastSync": { "operation": "job_upload", "status": "completed", "duration": 1250, "completedAt": "2025-07-18T09:16:00Z" }, "nextScheduled": { "operation": "data_poll", "scheduledTime": "2025-07-18T10:31:00Z" }, "syncHistory": [ { "operation": "job_upload", "status": "completed", "startTime": "2025-07-18T09:15:00Z", "endTime": "2025-07-18T09:16:00Z", "duration": 1250 } ] } ``` ### Bulk Sync Operations ```http POST /sync/bulk-sync ``` **Request Body:** ```json { "operation": "data_poll", "filters": { "partnerType": "satloc", "status": "pending", "lastSyncBefore": "2025-07-18T08:00:00Z" }, "options": { "batchSize": 10, "priority": "normal", "maxConcurrent": 3 } } ``` **Response:** ```json { "batchId": "batch_456", "totalAssignments": 25, "batches": 3, "estimatedCompletion": "2025-07-18T11:00:00Z", "status": "queued" } ``` ## Application Data APIs ### Get Application Data with Partner Info ```http GET /applications/{applicationId} ``` **Response:** ```json { "_id": "app_789", "jobId": 124, "fileName": "satloc_flight_data_001.dat", "fileSize": 1048576, "status": 3, "partnerType": "satloc", "externalJobId": "satloc_job_456", "assignmentId": "assign_124", "originalData": { "format": "satloc", "version": "2.1", "encoding": "binary", "checksum": "sha256:abc123..." }, "partnerMetadata": { "aircraftInfo": { "id": "SAT002", "model": "Satloc G4", "firmware": "v3.2.1" }, "flightInfo": { "startTime": "2025-07-18T10:00:00Z", "endTime": "2025-07-18T12:30:00Z", "duration": 9000, "altitude": {"min": 95, "max": 105, "avg": 100} }, "dataQuality": { "gpsAccuracy": 0.5, "signalStrength": 98, "dataCompleteness": 99.2 } }, "processingStage": "completed", "processingSteps": [ { "step": "upload", "status": "completed", "duration": 200 }, { "step": "validate", "status": "completed", "duration": 150 }, { "step": "convert", "status": "completed", "duration": 3000 } ], "conversionMetrics": { "recordsInput": 15000, "recordsOutput": 14987, "dataLossPercentage": 0.09, "conversionTime": 3000 }, "qualityChecks": [ { "checkType": "gps_continuity", "status": "passed", "score": 98 }, { "checkType": "spray_coverage", "status": "passed", "score": 95 } ] } ``` ### Get Processing Status ```http GET /applications/{applicationId}/processing-status ``` **Response:** ```json { "applicationId": "app_789", "currentStage": "completed", "progress": 100, "totalSteps": 6, "completedSteps": 6, "currentStep": null, "estimatedTimeRemaining": 0, "processingStarted": "2025-07-18T10:35:00Z", "processingCompleted": "2025-07-18T10:38:00Z", "totalDuration": 180000, "stepDetails": [ { "step": "upload", "status": "completed", "progress": 100, "duration": 200, "startTime": "2025-07-18T10:35:00Z", "endTime": "2025-07-18T10:35:00Z" } ] } ``` ## Error Handling All API endpoints follow consistent error response format: ```json { "error": { "code": "PARTNER_SYNC_FAILED", "message": "Failed to sync job with Satloc partner", "details": { "partnerId": "satloc", "operation": "job_upload", "cause": "Network timeout after 30s", "retryable": true, "nextRetry": "2025-07-18T10:40:00Z" }, "requestId": "req_123456789", "timestamp": "2025-07-18T10:30:00Z" } } ``` ### Error Codes | Code | Description | HTTP Status | Retryable | |------|-------------|-------------|-----------| | `PARTNER_NOT_FOUND` | Partner configuration not found | 404 | No | | `PARTNER_UNAVAILABLE` | Partner API is temporarily unavailable | 503 | Yes | | `PARTNER_SYNC_FAILED` | Failed to sync with partner | 500 | Yes | | `INVALID_PARTNER_CONFIG` | Partner configuration is invalid | 400 | No | | `RATE_LIMIT_EXCEEDED` | Partner rate limit exceeded | 429 | Yes | | `AUTHENTICATION_FAILED` | Partner authentication failed | 401 | No | | `DATA_FORMAT_ERROR` | Data format conversion failed | 422 | No | | `ASSIGNMENT_NOT_FOUND` | Assignment not found | 404 | No | | `SYNC_IN_PROGRESS` | Sync operation already in progress | 409 | No | ## Rate Limiting API endpoints are rate limited based on the operation type: - **Job Assignment**: 100 requests per minute - **Data Download**: 50 requests per minute - **Sync Operations**: 200 requests per minute - **Status Queries**: 1000 requests per minute Rate limit headers are included in all responses: ``` X-RateLimit-Limit: 100 X-RateLimit-Remaining: 95 X-RateLimit-Reset: 1642608000 X-RateLimit-Retry-After: 60 ``` ## Webhooks ### Partner Status Notifications Partners can register webhooks to receive notifications: ```http POST /webhooks/partner-events ``` **Request Body:** ```json { "url": "https://partner.example.com/webhooks/agmission", "events": ["job_assigned", "data_processed", "sync_failed"], "secret": "webhook_secret_key" } ``` ### Webhook Payload Example ```json { "event": "job_assigned", "timestamp": "2025-07-18T10:30:00Z", "data": { "assignmentId": "assign_124", "jobId": 124, "partnerType": "satloc", "externalJobId": "satloc_job_456", "userId": "user_id_2" }, "signature": "sha256=webhook_signature" } ``` This API specification provides comprehensive coverage of all partner integration functionality while maintaining backward compatibility with existing internal workflows.