Version 1.0.0
The open, evidence-first schema behind every registry record. Published as JSON Schema (draft 2020-12), a JSON-LD context mapped to schema.org, and the @openmoney/schema package with Zod validators.
Canonical base: https://openmoney.ai/schema/v1/
The platform or company: identity, domains, jurisdictions, verification state, published policies.
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | required | Registry id, e.g. "freelancer-com". |
| legalName | string | required | Registered legal name of the operating entity. |
| brandName | string | required | Name earners know the platform by. |
| domain | string | required | Canonical registrable domain, e.g. "freelancer.com". |
| otherDomains | string[] | required | Other domains the provider operates (regional sites, help centers). |
| hq | object | required | Where the provider is headquartered. |
| hq.country | string | null | required | Headquarters country; null when unknown. |
| hq.region | string | null | required | State, province, or city of the headquarters; null when unknown. |
| jurisdictions | string[] | required | Countries whose law governs earner terms. |
| categories | "rideshare" | "delivery" | "local_shifts" | "home_services" | "care" | "freelance" | "ai_training" | "microtask" | "research" | "selling" | "leasing" | "tutoring" | "creator" | "agent_bounty" | "open_source" | "other"[] | required | Registry categories. |
| entityVerification | object | required | Whether the operating legal entity is real and matches the brand. |
| entityVerification.status | "verified" | "unverified" | "suspicious" | required | Verification outcome. |
| entityVerification.method | string | null | required | How the legal entity was checked, e.g. "company register lookup", "WHOIS + terms page". |
| entityVerification.verifiedAt | string (date-time) | null | required | When the check was performed; null if never. |
| entityVerification.evidenceIds | string[] | required | Sources supporting the verification status. |
| paymentVerification | object | required | Whether the provider has been observed actually paying earners. |
| paymentVerification.status | "verified" | "unverified" | "suspicious" | required | Verification outcome. |
| paymentVerification.method | string | null | required | How payment was verified, e.g. "observed payout to a Passport holder", "payment processor disclosure". |
| paymentVerification.verifiedAt | string (date-time) | null | required | When payment was last verified; null if never. |
| termsUrl | string (uri) | null | required | Published terms of service for earners; null if none found. |
| payoutPolicyUrl | string (uri) | null | required | Published payout or fees policy; null if none found. |
| deactivationPolicyUrl | string (uri) | null | required | Published deactivation or account-termination policy; null if none found. |
| appealsProcess | object | required | Deactivation appeals: whether earners can appeal and whether a human reviews it. |
| appealsProcess.exists | boolean | null | required | Whether a published appeals process exists; null when unknown. |
| appealsProcess.humanReview | boolean | null | required | Whether a human reviews appeals; null when unknown. |
| appealsProcess.evidenceIds | string[] | required | Sources supporting the answers. |
| fairworkScores | object[] | required | Fairwork ratings by country and year. |
| fairworkScores[].country | string | required | ISO 3166-1 alpha-2 country code, e.g. US, IN. |
| fairworkScores[].year | integer | required | Rating year. |
| fairworkScores[].score | integer | required | Fairwork score out of 10. |
| fairworkScores[].url | string (uri) | required | Fairwork ratings page for that country and year. |
| sources | object[] | required | Every source cited by this record. |
| sources[].id | string | required | Source id, referenced by sourceId / sourceIds / evidenceIds elsewhere in the record. |
| sources[].url | string (uri) | required | Exact URL of the page or dataset. |
| sources[].publisher | string | required | Who published it (organisation name). |
| sources[].title | string | optional | Page or document title. |
| sources[].type | "platform_disclosure" | "regulatory_filing" | "third_party_dataset" | "survey" | "passport_aggregate" | "user_report" | "internal_measurement" | required | Kind of source: platform_disclosure, regulatory_filing, third_party_dataset, survey, passport_aggregate, user_report, internal_measurement. |
| sources[].retrievedAt | string (date-time) | required | When we fetched it (ISO 8601 date-time). |
| sources[].checksum | string | optional | SHA-256 hex of the retrieved body, when known. |
| sources[].reachability | "unchecked" | "ok" | "redirected" | "unreachable" | "changed" | optional | Last link-check result: unchecked, ok, redirected, unreachable, changed. |
| sources[].lastCheckedAt | string (date-time) | optional | When the link was last checked. |
| sources[].publishedAt | string (date) | optional | Publication or period date stated by the source itself. |
| sources[].notes | string | optional | Curator notes, typically the verbatim sentences the figures were read from. |
| version | "1.0.0" | required | Open Opportunity Schema version. |
| updatedAt | string (date-time) | required | When this record was last edited. |
One way to earn on a provider: eligibility, pay evidence as distributions, fee schedule, payout terms, stability, risk flags.
| Field | Type | Required | Description |
|---|---|---|---|
| id | string | required | Registry id, e.g. "freelancer-com:projects". |
| providerId | string | required | Id of the Provider offering this opportunity. |
| kind | "platform_gig" | "freelance_marketplace" | "ai_training" | "local_shift" | "selling" | "leasing" | "research_study" | "agent_bounty" | "employer_posting" | "open_source_bounty" | required | What kind of earning this is. |
| title | string | required | Short name, sentence case. |
| description | string | required | What the work is, in plain words. |
| workMode | "remote" | "onsite" | "hybrid" | required | Where the work happens. |
| geo | object | required | Geographic availability. |
| geo.countries | string[] | required | Countries where the opportunity is offered. Empty means worldwide or unknown; see eligibility. |
| geo.regions | string[] | required | States, provinces, or regions, when limited. |
| geo.cities | string[] | required | Cities or metros, when limited. |
| eligibility | object | required | Who can do this work. |
| eligibility.minAge | integer | null | required | Minimum age; null when not stated. |
| eligibility.vehicle | "none" | "bicycle" | "scooter" | "car" | "van" | "truck" | "any" | null | required | Vehicle required; null when not stated. |
| eligibility.equipment | string[] | required | Equipment the earner must supply, e.g. "smartphone", "insulated bag". |
| eligibility.credentials | string[] | required | Licenses, certifications, or degrees required. |
| eligibility.backgroundCheck | boolean | null | required | Whether a background check is required; null when not stated. |
| eligibility.countries | string[] | required | Countries of residence accepted, when they differ from geo.countries. |
| payEvidence | object[] | required | Pay distributions with sources. Empty until evidence exists; never estimated. |
| payEvidence[].metric | "net_hourly" | "gross_hourly" | "per_task" | "per_project" | required | What the pay figures measure. |
| payEvidence[].currency | string | required | ISO 4217 currency code, e.g. USD, INR. |
| payEvidence[].p25 | integer | null | required | 25th percentile in minor units; null when not reported. |
| payEvidence[].p50 | integer | null | required | Median in minor units; null when not reported. |
| payEvidence[].p90 | integer | null | required | 90th percentile in minor units; null when not reported. |
| payEvidence[].n | integer | null | required | Sample size; null when the source does not state one. |
| payEvidence[].periodStart | string (date) | required | First day of the period the figures cover. |
| payEvidence[].periodEnd | string (date) | required | Last day of the period the figures cover. |
| payEvidence[].sourceType | "passport_aggregate" | "platform_disclosure" | "third_party_dataset" | "survey" | "regulatory_filing" | required | Where a pay figure comes from. |
| payEvidence[].sourceId | string | required | Id of a source in the enclosing record's `sources[]`. Every number carries one. |
| feeSchedule | object[] | required | Published fees, each with a source. |
| feeSchedule[].name | string | required | Fee name as the provider states it. |
| feeSchedule[].type | "percent" | "fixed" | "per_application" | "subscription" | "withdrawal" | "instant_pay" | required | Fee category. |
| feeSchedule[].value | integer | required | Fee amount: basis points when unit is basis_points, minor units of `currency` when unit is minor_units. |
| feeSchedule[].unit | "basis_points" | "minor_units" | required | How `value` is expressed: basis points of the base, or minor units of `currency`. |
| feeSchedule[].currency | string | optional | Required when unit is minor_units. |
| feeSchedule[].minimum | object | optional | Floor applied to a percent fee ("10% or $5, whichever is greater"). |
| feeSchedule[].minimum.amountMinor | integer | optional | Amount in minor units (cents, paise). Integer; never a float. |
| feeSchedule[].minimum.currency | string | optional | ISO 4217 currency code, e.g. USD, INR. |
| feeSchedule[].appliesTo | string | required | What the fee applies to, e.g. "fixed-price project earnings", "each withdrawal via PayPal". |
| feeSchedule[].sourceId | string | required | Id of a source in the enclosing record's `sources[]`. Every number carries one. |
| payoutTerms | object | null | required | Payout terms; null when not yet documented. |
| onboardingCost | object | null | required | Onboarding cost; null when not yet documented. |
| stability | object | required | How dependable the work and the account are. |
| stability.taskAvailabilitySignal | "high" | "medium" | "low" | "unknown" | required | Whether there is usually work available. |
| stability.observedDeactivationRate | integer | null | required | Share of earners deactivated per year, in basis points; null when unknown. |
| stability.reportedUnpaidWorkIncidents | integer | null | required | Count of reported unpaid-work incidents in the period; null when unknown. |
| stability.sourceIds | string[] | required | Sources for the stability figures. |
| riskFlags | object[] | required | Scam and reliability signals, each with evidence. |
| riskFlags[].code | "UPFRONT_FEE" | "TASK_SCAM_PATTERN" | "CRYPTO_ONLY_PAYOUT" | "OFF_PLATFORM_ONLY_MESSAGING" | "CHECK_DEPOSIT_SCHEME" | "EQUIPMENT_PURCHASE_REQUIRED" | "DOMAIN_AGE_UNDER_90D" | "DOMAIN_MISMATCH" | "UNSUBSTANTIATED_EARNINGS_CLAIM" | "MLM_STRUCTURE" | "GHOST_POSTING" | "BRAND_IMPERSONATION" | "UNPAID_WORK_REPORTS" | "NO_APPEALS_PROCESS" | required | Scam-signature rule code. |
| riskFlags[].severity | "info" | "low" | "medium" | "high" | "critical" | required | How serious the signal is. |
| riskFlags[].evidence | object | required | The evidence a flag rests on. A flag cannot exist without it. |
| riskFlags[].evidence.sourceId | string | required | Id of a source in the enclosing record's `sources[]`. Every number carries one. |
| riskFlags[].evidence.quote | string | optional | Verbatim excerpt from the source that triggered the flag. |
| riskFlags[].evidence.observedAt | string (date-time) | required | When the evidence was observed. |
| riskFlags[].detectedBy | "rule" | "curator" | "report" | required | Who or what raised the flag. |
| riskFlags[].ruleVersion | string | required | Version of the rule set or curator guideline that raised the flag, e.g. "scam-rules@1.0.0". |
| agentPostable | boolean | required | Whether AI agents may post or apply on behalf of a principal. |
| postedBy | object | required | Who posted this and, for agents, whose Proof backs them. |
| postedBy.type | "provider" | "agent" | "employer" | required | Who posted the opportunity. |
| postedBy.agentId | string | optional | Agent id when posted by an agent. |
| postedBy.principalProofId | string | optional | Proof id of the agent's human principal when posted by an agent. |
| lastVerifiedAt | string (date-time) | required | When a curator last confirmed the record against its sources. |
| scorecard | object | null | required | Scorecard; null before the first computation. |
| sources | object[] | required | Every source cited by this record. |
| sources[].id | string | required | Source id, referenced by sourceId / sourceIds / evidenceIds elsewhere in the record. |
| sources[].url | string (uri) | required | Exact URL of the page or dataset. |
| sources[].publisher | string | required | Who published it (organisation name). |
| sources[].title | string | optional | Page or document title. |
| sources[].type | "platform_disclosure" | "regulatory_filing" | "third_party_dataset" | "survey" | "passport_aggregate" | "user_report" | "internal_measurement" | required | Kind of source: platform_disclosure, regulatory_filing, third_party_dataset, survey, passport_aggregate, user_report, internal_measurement. |
| sources[].retrievedAt | string (date-time) | required | When we fetched it (ISO 8601 date-time). |
| sources[].checksum | string | optional | SHA-256 hex of the retrieved body, when known. |
| sources[].reachability | "unchecked" | "ok" | "redirected" | "unreachable" | "changed" | optional | Last link-check result: unchecked, ok, redirected, unreachable, changed. |
| sources[].lastCheckedAt | string (date-time) | optional | When the link was last checked. |
| sources[].publishedAt | string (date) | optional | Publication or period date stated by the source itself. |
| sources[].notes | string | optional | Curator notes, typically the verbatim sentences the figures were read from. |
| version | "1.0.0" | required | Open Opportunity Schema version. |
A scam-signature code with severity and the evidence it fired on. A flag cannot exist without evidence.
| Field | Type | Required | Description |
|---|---|---|---|
| code | "UPFRONT_FEE" | "TASK_SCAM_PATTERN" | "CRYPTO_ONLY_PAYOUT" | "OFF_PLATFORM_ONLY_MESSAGING" | "CHECK_DEPOSIT_SCHEME" | "EQUIPMENT_PURCHASE_REQUIRED" | "DOMAIN_AGE_UNDER_90D" | "DOMAIN_MISMATCH" | "UNSUBSTANTIATED_EARNINGS_CLAIM" | "MLM_STRUCTURE" | "GHOST_POSTING" | "BRAND_IMPERSONATION" | "UNPAID_WORK_REPORTS" | "NO_APPEALS_PROCESS" | required | Scam-signature rule code. |
| severity | "info" | "low" | "medium" | "high" | "critical" | required | How serious the signal is. |
| evidence | object | required | The evidence a flag rests on. A flag cannot exist without it. |
| evidence.sourceId | string | required | Id of a source in the enclosing record's `sources[]`. Every number carries one. |
| evidence.quote | string | optional | Verbatim excerpt from the source that triggered the flag. |
| evidence.observedAt | string (date-time) | required | When the evidence was observed. |
| detectedBy | "rule" | "curator" | "report" | required | Who or what raised the flag. |
| ruleVersion | string | required | Version of the rule set or curator guideline that raised the flag, e.g. "scam-rules@1.0.0". |
Six dimensions with confidence, a composite that is marked partial when evidence is missing, and the methodology version.
| Field | Type | Required | Description |
|---|---|---|---|
| pay | object | required | Pay: median net hourly vs. local minimum wage and category median. |
| pay.score | integer | null | required | 0–100, or null when there is insufficient evidence. |
| pay.confidence | "high" | "medium" | "low" | "insufficient" | required | Confidence in the score: high, medium, low, or insufficient. |
| pay.evidenceIds | string[] | required | Sources the score was computed from. |
| fees | object | required | Fees: total extraction rate including unpaid onboarding. |
| fees.score | integer | null | required | 0–100, or null when there is insufficient evidence. |
| fees.confidence | "high" | "medium" | "low" | "insufficient" | required | Confidence in the score: high, medium, low, or insufficient. |
| fees.evidenceIds | string[] | required | Sources the score was computed from. |
| payout | object | required | Payout: frequency, delay, minimum, reliability incidents. |
| payout.score | integer | null | required | 0–100, or null when there is insufficient evidence. |
| payout.confidence | "high" | "medium" | "low" | "insufficient" | required | Confidence in the score: high, medium, low, or insufficient. |
| payout.evidenceIds | string[] | required | Sources the score was computed from. |
| stability | object | required | Stability: task availability, deactivation rate, unpaid-work incidents, appeals. |
| stability.score | integer | null | required | 0–100, or null when there is insufficient evidence. |
| stability.confidence | "high" | "medium" | "low" | "insufficient" | required | Confidence in the score: high, medium, low, or insufficient. |
| stability.evidenceIds | string[] | required | Sources the score was computed from. |
| transparency | object | required | Transparency: published terms, fees, deactivation policy, pay disclosures. |
| transparency.score | integer | null | required | 0–100, or null when there is insufficient evidence. |
| transparency.confidence | "high" | "medium" | "low" | "insufficient" | required | Confidence in the score: high, medium, low, or insufficient. |
| transparency.evidenceIds | string[] | required | Sources the score was computed from. |
| scamRisk | object | required | Scam risk (inverted: 100 = no signals): risk flags, verification, domain age, complaints. |
| scamRisk.score | integer | null | required | 0–100, or null when there is insufficient evidence. |
| scamRisk.confidence | "high" | "medium" | "low" | "insufficient" | required | Confidence in the score: high, medium, low, or insufficient. |
| scamRisk.evidenceIds | string[] | required | Sources the score was computed from. |
| composite | object | required | The weighted composite and how it was computed. |
| composite.score | integer | null | required | Weighted composite 0–100, or null when no dimension has evidence. |
| composite.partial | boolean | required | True when at least one dimension was excluded for insufficient evidence. |
| composite.weights | object | required | Composite weights per dimension in basis points; they sum to 10000. |
| composite.weights.pay | integer | required | Percentage in basis points (10000 = 100%). |
| composite.weights.fees | integer | required | Percentage in basis points (10000 = 100%). |
| composite.weights.payout | integer | required | Percentage in basis points (10000 = 100%). |
| composite.weights.stability | integer | required | Percentage in basis points (10000 = 100%). |
| composite.weights.transparency | integer | required | Percentage in basis points (10000 = 100%). |
| composite.weights.scamRisk | integer | required | Percentage in basis points (10000 = 100%). |
| composite.methodologyVersion | string | required | Version of the scoring methodology that produced this composite, e.g. "scoring@1.0.0". |
| computedAt | string (date-time) | required | When the scorecard was computed. |