Skip to content
UGP v1.0 is a public comment draft. Comments close November 23, 2026. The A–D defect counts are provisional.Public comment draft · until November 23, 2026Comment on this draftComment →
UGPUniversal Grading Protocol
Build

JSON schema

PDF

The UGP v1.0 record schema, JSON Schema 2020-12, at /schema/v1.0/record.json: identity, the eight axes, the derived result and the audit fields.

Schema: /schema/v1.0/record.json, JSON Schema 2020-12.

The shape of a record

text
ugp_version, profile, profile_status, record_scope
identity    { make, model, …, blacklist { status, basis, source, checked_at } }
axes
  cosmetic   { value, basis, zones { AA, A, B, C, … } [defects], mapped_from? { scale, value, crosswalk } }
  functional { status, faults[] }
  battery    { health_pct, basis, cells[], replaced }
  locks      { value, types[] }
  operator   { value, carrier }
  data       { value, method, technique, tool, certificate_id, standard_rev }
  parts      { value, manifest[] }
  kit        { value, components[] }
result      { status, reasons[], grade, premium, core_code, ctia_derived? }
audit       { grader_id, graded_at, method, verification_tier, conformance, tolerance_table }

Annex B · §4.1

Three rules that matter in code

  1. result is derived. The grade, status and core code in result match the derivation of §11 and §12; never accept them from user input. Recompute them from axes and compare. §4.4
  2. Store raw observations. Keep the per-zone defect lists, fault codes, battery readings and part states, not only the roll-up values, so a record can be regraded when a tolerance changes. §4.3
  3. Every value has a basis. Measured, evidenced, declared or unknown. A declared battery and a measured one derive differently (only a measured 90% or more can be Premium). §4.2

Versions and profiles

  • ugp_version pins the version the record was graded under; disputes are judged against it. §14.6
  • profile_status is provisional for device classes whose profile pack is not published yet. §1.2
  • audit.tolerance_table is phone-1.0-provisional while the A–D counts are provisional. §5.5
  • record_scope is unit or lot. §14.5
  • identity.blacklist.status is clear, reported or unchecked; basis says how clear was reached: measured or evidenced (a check) or declared. unchecked derives NOT GRADED with reason lost_stolen_unchecked; a declared clear adds the disclosure lost_stolen_declared. §9.3
  • axes.cosmetic.mapped_from (scale, value, crosswalk) is set only on a supplier-mapped grade, with cosmetic basis declared. It adds the disclosure supplier_mapped and the core-code extension ~src:supplier. §13.6

Testing your implementation

Validate every record against the schema, then check that your derivation reproduces every golden example. The examples are published beside the schema at /schema/v1.0/golden/. Annex E