Partner Integration

JuniorForge Partner API

The JuniorForge Partner API gives approved partners read-only access to AI annotation task submissions completed by JuniorForge contributors on their behalf.

Base URL

https://juniorforge.onrender.com/api

Auth

API Key (Bearer)

Format

JSON / CSV

Scoping: Your API key automatically scopes every request to your partner account. You can only access tasks and submissions that belong to your organisation. Talent PII (names, emails, location) is never exposed.


Authentication

Authenticate all requests by passing your API key in the Authorization header.

Authentication Header
Authorization: Bearer YOUR_API_KEY

Alternatively you can use the X-API-Key header:

Alternative Header
X-API-Key: YOUR_API_KEY

Key security: Never expose your API key in client-side code or public repositories. Use environment variables or a secrets manager. Keys cannot be recovered if lost — contact JuniorForge to rotate.


Rate Limits

Rate limits are applied per API key. Default limits are shown below. Contact JuniorForge if your integration requires higher limits.

60

Requests per minute

Across all endpoints

5,000

Requests per day

Rolling 24-hour window

When rate limited, the API returns HTTP 429. Implement exponential backoff and use the ?since= parameter on submission endpoints to reduce request volume.


Endpoints

All endpoints are read-only. The base path for all partner endpoints is /partner.

GET/api/partner/me

Partner Account Info

Verify your API key is valid and inspect which permissions have been granted to your account.

Example response:

Response · JSON
{
  "success": true,
  "data": {
    "partnerName": "Outlier",
    "keyPrefix": "jf_outlier_a3f91b...",
    "label": "Outlier Production Key",
    "isActive": true,
    "permissions": {
      "readTasks": true,
      "readSubmissions": true,
      "readSubmissionResponses": true,
      "readTalentProfile": false,
      "webhookEnabled": true
    },
    "rateLimit": {
      "requestsPerMinute": 60,
      "requestsPerDay": 5000
    },
    "expiresAt": null,
    "usage": {
      "totalRequests": 142,
      "lastUsedAt": "2025-06-01T09:42:11Z"
    },
    "webhook": {
      "url": "https://your-system.com/webhooks/jf",
      "events": [
        "submission.approved"
      ]
    }
  }
}
GET/api/partner/tasks

List Partner Tasks

Returns all tasks belonging to your partner account, including submission statistics per task.

Parameters

status
querystring

Filter by task status. One of: active, paused, completed, draft.

page
queryinteger

Page number. Default: 1.

limit
queryinteger

Results per page. Max 100. Default: 50.

Example response:

Response · JSON
{
  "success": true,
  "partner": "Outlier",
  "pagination": {
    "total": 3,
    "page": 1,
    "limit": 50,
    "totalPages": 1
  },
  "data": {
    "tasks": [
      {
        "taskId": "665f1a2b3c4d5e6f7a8b9c0d",
        "externalTaskId": "outlier-codegen-batch-7",
        "externalProjectName": "Code Otter",
        "title": "Code Quality Evaluation — React Components",
        "taskType": "code_evaluation",
        "status": "active",
        "deadline": "2025-08-01T23:59:59Z",
        "estimatedDurationMinutes": 30,
        "payPerSubmissionUSD": "5.00",
        "capacity": {
          "max": 50,
          "current": 23,
          "submissionsPerContributor": 1
        },
        "reviewRequired": true,
        "submissions": {
          "total": 23,
          "approved": 18,
          "pending": 4,
          "rejected": 1
        },
        "createdAt": "2025-05-15T10:00:00Z",
        "updatedAt": "2025-06-01T08:30:00Z"
      }
    ]
  }
}
GET/api/partner/submissions

All Submissions (Bulk)

Pull submissions across all of your tasks in one request. Use the `since` parameter for incremental syncs — we strongly recommend this over full pulls.

Parameters

status
querystring

Filter by review status. One of: approved (default), pending_review, rejected, all.

since
querystring

ISO 8601 datetime. Returns only submissions submitted after this date. Highly recommended for sync jobs.

page
queryinteger

Page number. Default: 1.

limit
queryinteger

Results per page. Max 100. Default: 50.

includeResponses
queryboolean

Set to false to retrieve metadata only (no work content). Default: true.

Example response:

Response · JSON
{
  "success": true,
  "partner": "Outlier",
  "filters": {
    "status": "approved",
    "since": "2025-06-01T00:00:00Z"
  },
  "pagination": {
    "total": 18,
    "page": 1,
    "limit": 50,
    "totalPages": 1
  },
  "meta": {
    "totalTasks": 3,
    "syncNote": "Use ?since=<ISO_DATE> for incremental syncs to reduce response size."
  },
  "data": {
    "submissions": [
      {
        "submissionId": "665f1a2b3c4d5e6f7a8b9c0e",
        "externalTaskId": "outlier-codegen-batch-7",
        "taskTitle": "Code Quality Evaluation — React Components",
        "submissionIndex": 1,
        "submittedAt": "2025-06-01T08:22:10Z",
        "reviewedAt": "2025-06-01T09:15:30Z",
        "reviewStatus": "approved",
        "qualityScore": 87,
        "timeTakenSeconds": 1842,
        "talent": {
          "talentId": "anon-id-hidden",
          "tier": 1
        },
        "responses": [
          {
            "fieldName": "overall_quality",
            "value": "The component correctly implements memoization but misses edge case handling for null props."
          },
          {
            "fieldName": "correctness_score",
            "value": 4
          },
          {
            "fieldName": "has_bugs",
            "value": false
          }
        ]
      }
    ]
  }
}
GET/api/partner/tasks/:taskId/submissions

Submissions for a Task

Pull all submissions for a single specific task. Useful when you process results per task batch.

Parameters

taskId*
pathstring

The MongoDB ID of the task. Obtain this from the List Tasks endpoint.

status
querystring

Filter by review status. Default: approved.

since
querystring

ISO 8601 datetime for incremental pulls.

page
queryinteger

Page number. Default: 1.

limit
queryinteger

Results per page. Max 100.

includeResponses
queryboolean

Include response payload. Default: true.

Example response:

Response · JSON
{
  "success": true,
  "task": {
    "taskId": "665f...",
    "externalTaskId": "outlier-codegen-batch-7",
    "title": "Code Quality Evaluation — React Components",
    "taskType": "code_evaluation"
  },
  "pagination": {
    "total": 18,
    "page": 1,
    "limit": 50,
    "totalPages": 1
  },
  "data": {
    "submissions": [
      "...same structure as /submissions..."
    ]
  }
}
GET/api/partner/submissions/:submissionId

Get Single Submission

Retrieve a single submission by its ID. Useful for spot-checking or retry logic.

Parameters

submissionId*
pathstring

The MongoDB ID of the submission.

Example response:

Response · JSON
{
  "success": true,
  "data": {
    "submission": {
      "submissionId": "665f...",
      "reviewStatus": "approved",
      "qualityScore": 87,
      "responses": [
        "..."
      ]
    }
  }
}
GET/api/partner/tasks/:taskId/export/csv

Export Submissions as CSV

Download all submissions for a task as a CSV file. Each submission response field becomes its own column — ideal for loading directly into your annotation pipelines or spreadsheet tools.

Parameters

taskId*
pathstring

The MongoDB ID of the task.

status
querystring

Filter by status. Default: approved.

since
querystring

ISO 8601 date for incremental export.

The response is a text/csv file with Content-Disposition: attachment. Each response field in the submission form becomes a separate column:

CSV Sample Output
submissionId,externalTaskId,submissionIndex,reviewStatus,qualityScore,timeTakenSeconds,submittedAt,reviewedAt,talentTier,overall_quality,correctness_score,has_bugs
665f1a2b...,outlier-codegen-batch-7,1,approved,87,1842,2025-06-01T08:22:10Z,2025-06-01T09:15:30Z,1,"The component correctly implements memoization but misses edge case handling for null props.",4,false

Webhooks

If your API key has webhook access enabled, JuniorForge will POST a signed JSON payload to your configured endpoint whenever a submission event occurs. This eliminates the need to poll the submissions endpoint.

Supported Events

submission.approved

Fired when a submission is approved by a JuniorForge reviewer. This is the primary event for pulling work product.

submission.rejected

Fired when a submission is rejected. No work product is included.

task.completed

Fired when all submission slots for a task have been filled and reviewed.

Payload Shape

Response · JSON
{
  "event": "submission.approved",
  "partnerName": "Outlier",
  "externalTaskId": "outlier-codegen-batch-7",
  "taskId": "665f1a2b3c4d5e6f7a8b9c0d",
  "taskTitle": "Code Quality Evaluation — React Components",
  "submission": {
    "submissionId": "665f1a2b3c4d5e6f7a8b9c0e",
    "submissionIndex": 1,
    "reviewStatus": "approved",
    "qualityScore": 87,
    "timeTakenSeconds": 1842,
    "submittedAt": "2025-06-01T08:22:10Z",
    "reviewedAt": "2025-06-01T09:15:30Z",
    "responses": [
      {
        "fieldName": "overall_quality",
        "value": "The component correctly implements memoization but misses edge case handling for null props."
      },
      {
        "fieldName": "correctness_score",
        "value": 4
      }
    ],
    "talent": {
      "tier": 1
    }
  },
  "deliveredAt": "2025-06-01T09:15:35Z"
}

Signature Verification

Every webhook request includes an X-JuniorForge-Signature header containing sha256=<HMAC>. Always verify this before processing the payload.

Python · Flask

Reliability: JuniorForge makes one delivery attempt per event with a 10-second timeout. If delivery fails, the submission remains accessible via the REST API. We recommend implementing a fallback polling job alongside webhook consumption.


Data Schemas

Submission Object

submissionIdstring

MongoDB ObjectId. Unique identifier for this submission.

externalTaskIdstring?

Your own task reference ID, set when the task was created in JuniorForge admin.

taskTitlestring

Human-readable name of the task.

submissionIndexinteger

Which submission this is for this talent on this task (starts at 1).

submittedAtISO 8601

When the talent submitted their work.

reviewedAtISO 8601

When a JuniorForge reviewer approved or rejected it.

reviewStatusenum

approved | pending_review | rejected | flagged

qualityScoreinteger?

0–100 quality score assigned by the reviewer.

timeTakenSecondsinteger?

Time the talent spent on the submission (measured client-side).

talent.tierinteger

JuniorForge talent tier. 1 = top tier, 2 = mid tier.

talent.preferredRolestring?

Only present if readTalentProfile permission is granted.

responsesarray?

Array of { fieldName, value } objects. Each entry is one form field. Only present if readSubmissionResponses is granted.


Error Codes

401 INVALID_KEY

The API key is missing, malformed, or has been revoked.

401 KEY_EXPIRED

The API key has passed its expiry date. Contact JuniorForge to renew.

403 PERMISSION_DENIED

Your key doesn't have the required permission for this endpoint.

403 TASK_NOT_YOURS

The requested task does not belong to your partner account.

403 SUBMISSION_NOT_YOURS

The requested submission is not for one of your tasks.

404

The requested resource was not found.

429

Rate limit exceeded. Back off and retry with exponential delay.

500

Internal server error. Retry after a short delay. Contact support if persistent.

Error Response Shape

Response · JSON
{
  "success": false,
  "code": "PERMISSION_DENIED",
  "message": "Your API key does not have 'readSubmissionResponses' access. Contact JuniorForge to upgrade your key permissions."
}

Code Examples

Verify Access

curl
curl "https://juniorforge.onrender.com/api/partner/me" \
  -H "Authorization: Bearer YOUR_API_KEY"

Incremental Sync (Recommended)

curl
curl "https://juniorforge.onrender.com/api/partner/submissions?status=approved&since=2025-06-01T00:00:00Z" \
  -H "Authorization: Bearer YOUR_API_KEY"

Submissions for a Specific Task

curl
curl "https://juniorforge.onrender.com/api/partner/tasks/TASK_ID/submissions?status=approved" \
  -H "Authorization: Bearer YOUR_API_KEY"

Download CSV Export

curl
curl "https://juniorforge.onrender.com/api/partner/tasks/TASK_ID/export/csv?status=approved" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  --output submissions.csv

Questions about the API? Contact your JuniorForge account manager or email contact@juniorforge.com

JuniorForge Partner API · v1 · 2026