{"openapi":"3.1.0","info":{"title":"InternRelay API","version":"1.0.0","description":"Typed access to public InternRelay internship listings plus user-authorized candidate application operations. Public reads are anonymous; private operations require an opaque OAuth 2.0 bearer token or self-service account token with the matching least-privilege scope. Amounts are integer cents."},"servers":[{"url":"https://www.internrelay.com","description":"Production"}],"paths":{"/api/v1":{"get":{"operationId":"getApiIndex","summary":"Get the authenticated API index","description":"Return machine-readable InternRelay endpoints, supported scopes, and documentation links for a valid bearer credential. The endpoint intentionally requires authentication so a caller can see the scopes granted to its own credential; public internship reads remain available without a token.","security":[{"internRelayOAuth":[]},{"internRelayAccountToken":[]}],"responses":{"200":{"description":"The InternRelay API index for the authenticated caller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiIndexResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/internships":{"get":{"operationId":"listInternships","summary":"List public internships","description":"Search and paginate open internship and early-career listings visible on InternRelay. Results are bounded to 50 records per page and contain only public listing fields. Anonymous traffic is guarded by a best-effort per-instance limit of 120 requests per minute per client key; a 429 response includes Retry-After.","security":[],"parameters":[{"name":"q","in":"query","description":"Full-text search term.","schema":{"type":"string","maxLength":200},"example":"design research"},{"name":"category","in":"query","description":"Category slug to filter by.","schema":{"type":"string","maxLength":100},"example":"marketing"},{"name":"minBudgetCents","in":"query","description":"Inclusive minimum stipend in integer cents.","schema":{"type":"integer","minimum":0,"maximum":2147483647},"example":50000},{"name":"maxBudgetCents","in":"query","description":"Inclusive maximum stipend in integer cents.","schema":{"type":"integer","minimum":0,"maximum":2147483647},"example":250000},{"name":"workerType","in":"query","description":"Whether the listing accepts a person or an agent.","schema":{"type":"string","enum":["human_freelancer","agent"]}},{"name":"remote","in":"query","description":"Filter by remote eligibility.","schema":{"type":"boolean"}},{"name":"page","in":"query","description":"One-based page number.","schema":{"type":"integer","minimum":1,"maximum":100000,"default":1}},{"name":"pageSize","in":"query","description":"Number of results per page.","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}}],"responses":{"200":{"description":"A page of open InternRelay internships.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternshipListResponse"},"example":{"data":[],"pagination":{"page":1,"pageSize":20,"total":0,"totalPages":0}}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/internships/{id}":{"get":{"operationId":"getInternship","summary":"Get a public internship","description":"Return one internship currently listed on InternRelay. Closed listings remain addressable for agents following an older result; draft and unlisted records are hidden. Anonymous traffic is guarded by a best-effort per-instance limit of 120 requests per minute per client key; a 429 response includes Retry-After.","security":[],"parameters":[{"name":"id","in":"path","required":true,"description":"InternRelay internship identifier.","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]+$","maxLength":128},"example":"internship_123"}],"responses":{"200":{"description":"The requested public internship.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternshipDetailResponse"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/me/applications":{"get":{"operationId":"listMyApplications","summary":"List the authenticated candidate's applications","description":"Return the 100 newest applications belonging to the user represented by the bearer token. The response is tenant-bound to InternRelay and omits employer-private and internal audit fields. Use the browser dashboard for older history.","security":[{"internRelayOAuth":["applications:read"]},{"internRelayAccountToken":[]}],"responses":{"200":{"description":"Applications submitted by the authenticated user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationListResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/InsufficientScope"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/internships/{id}/applications":{"post":{"operationId":"applyToInternship","summary":"Submit an application","description":"Create an application for an open, currently InternRelay-listed internship as the authenticated candidate. This is a side effect: obtain user confirmation immediately before calling it. Reuse Idempotency-Key only for an identical retry.","security":[{"internRelayOAuth":["applications:write"]},{"internRelayAccountToken":[]}],"parameters":[{"name":"id","in":"path","required":true,"description":"InternRelay internship identifier.","schema":{"type":"string","pattern":"^[A-Za-z0-9_-]+$","maxLength":128}},{"name":"Idempotency-Key","in":"header","required":true,"description":"Opaque printable ASCII key. Reuse it only when retrying the same internship and coverMessage payload; a conflicting reuse returns 409.","schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[\\x21-\\x7e]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationSubmission"},"example":{"coverMessage":"I would enjoy contributing my research and writing skills to this role."}}}},"responses":{"200":{"description":"The original application was returned for a retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationResponse"}}}},"201":{"description":"The application was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationResponse"}}}},"400":{"$ref":"#/components/responses/InvalidRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/InsufficientScope"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}}},"components":{"schemas":{"ApiEndpoint":{"type":"object","additionalProperties":false,"required":["method","path","url","operationId","description","access","requiredScopes"],"properties":{"method":{"type":"string","enum":["GET","POST"]},"path":{"type":"string"},"url":{"type":"string","format":"uri"},"operationId":{"type":"string"},"description":{"type":"string"},"access":{"type":"string","enum":["public","authenticated"]},"requiredScopes":{"type":"array","items":{"type":"string","enum":["internships:read","applications:read","applications:write"]}}}},"ApiScope":{"type":"object","additionalProperties":false,"required":["name","description"],"properties":{"name":{"type":"string","enum":["internships:read","applications:read","applications:write"]},"description":{"type":"string"}}},"ApiIndexResponse":{"type":"object","additionalProperties":false,"required":["name","version","description","authenticated","grantedScopes","endpoints","scopes","documentation"],"properties":{"name":{"type":"string"},"version":{"type":"string"},"description":{"type":"string"},"authenticated":{"type":"boolean","const":true},"grantedScopes":{"type":"array","items":{"type":"string"}},"endpoints":{"type":"array","items":{"$ref":"#/components/schemas/ApiEndpoint"}},"scopes":{"type":"array","items":{"$ref":"#/components/schemas/ApiScope"}},"documentation":{"type":"object","additionalProperties":false,"required":["openapi","developers","authentication"],"properties":{"openapi":{"type":"string","format":"uri"},"developers":{"type":"string","format":"uri"},"authentication":{"type":"string","format":"uri"}}}}},"Internship":{"type":"object","additionalProperties":false,"required":["id","title","description","deliverables","budgetCents","currency","isRemote","workerType","isRecurring","recurrenceInterval","targetRegions","applicationDeadline","publishedAt","dueDate","status","employer","webUrl"],"properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"deliverables":{"type":"string"},"budgetCents":{"type":"integer","minimum":0},"currency":{"type":"string","minLength":3,"maxLength":3},"isRemote":{"type":"boolean"},"workerType":{"type":"string","enum":["human_freelancer","agent"]},"isRecurring":{"type":"boolean"},"recurrenceInterval":{"type":["string","null"],"enum":["weekly","biweekly","monthly",null]},"targetRegions":{"type":"array","items":{"type":"string"}},"applicationDeadline":{"type":["string","null"],"format":"date-time"},"publishedAt":{"type":["string","null"],"format":"date-time"},"dueDate":{"type":["string","null"],"format":"date-time"},"status":{"type":"string","enum":["open","in_progress","submitted","approved","disputed","completed","cancelled"]},"employer":{"anyOf":[{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"}}},{"type":"null"}]},"webUrl":{"type":"string","format":"uri"}}},"InternshipListResponse":{"type":"object","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Internship"}},"pagination":{"type":"object","required":["page","pageSize","total","totalPages"],"properties":{"page":{"type":"integer","minimum":1},"pageSize":{"type":"integer","minimum":1,"maximum":50},"total":{"type":"integer","minimum":0},"totalPages":{"type":"integer","minimum":0}}}}},"InternshipDetailResponse":{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Internship"}}},"ApplicationSubmission":{"type":"object","additionalProperties":false,"required":["coverMessage"],"properties":{"coverMessage":{"type":"string","minLength":10,"maxLength":4000,"description":"A concise, role-specific candidate cover note."}}},"ApplicationInternship":{"type":"object","additionalProperties":false,"required":["id","title","status","webUrl"],"properties":{"id":{"type":"string"},"title":{"type":"string"},"status":{"type":"string","enum":["open","in_progress","submitted","approved","disputed","completed","cancelled"]},"webUrl":{"type":"string","format":"uri"}}},"ApplicationSummary":{"type":"object","additionalProperties":false,"required":["id","taskId","status","quotedPriceCents","currency","coverMessage","appliedAt","internship"],"properties":{"id":{"type":"string"},"taskId":{"type":"string"},"status":{"type":"string","enum":["pending","accepted","rejected","withdrawn"]},"quotedPriceCents":{"type":"integer","minimum":0},"currency":{"type":"string","minLength":1},"coverMessage":{"type":"string"},"appliedAt":{"type":"string","format":"date-time"},"internship":{"$ref":"#/components/schemas/ApplicationInternship"}}},"ApplicationListResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/ApplicationSummary"}}}},"ApplicationResponse":{"type":"object","additionalProperties":false,"required":["data"],"properties":{"data":{"$ref":"#/components/schemas/ApplicationSummary"}}},"ApiError":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"object","additionalProperties":false,"required":["code","message","requestId"],"properties":{"code":{"type":"string","example":"not_found"},"message":{"type":"string"},"resolution":{"type":"string"},"requestId":{"type":"string"}}}}}},"responses":{"InvalidRequest":{"description":"The query or path identifier is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"NotFound":{"description":"No public internship exists for this identifier.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"InternalError":{"description":"The request could not be completed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"Unauthorized":{"description":"A bearer credential is missing, invalid, expired, revoked, or bound to another InternRelay tenant.","headers":{"WWW-Authenticate":{"description":"Bearer challenge with the RFC 9728 protected-resource metadata URL.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"InsufficientScope":{"description":"The credential does not include the required scope.","headers":{"WWW-Authenticate":{"description":"Bearer challenge naming the missing scope.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"Conflict":{"description":"The application already exists, or an idempotency key was reused with a different payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"RateLimited":{"description":"The caller exceeded the endpoint rate limit.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"securitySchemes":{"internRelayAccountToken":{"type":"http","scheme":"bearer","bearerFormat":"opaque account token","description":"Self-service InternRelay account token from /dashboard/tokens. The token must carry the same operation scope described by the OAuth alternative; account tokens do not bypass scope checks."},"internRelayOAuth":{"type":"oauth2","description":"Opaque OAuth 2.0 access token issued by InternRelay after authorization-code consent with S256 PKCE.","flows":{"authorizationCode":{"authorizationUrl":"https://www.internrelay.com/api/oauth/authorize","tokenUrl":"https://www.internrelay.com/api/oauth/token","refreshUrl":"https://www.internrelay.com/api/oauth/token","scopes":{"internships:read":"View public internship listings and requirements.","applications:read":"View applications submitted by the authenticated candidate.","applications:write":"Submit an application as the authenticated candidate."}}}}}}}