---
title: "Read an entry for editing"
method: GET
path: "/api/editor/{vhid}"
tags: ["Proposing changes"]
---

# Read an entry for editing

`GET /api/editor/{vhid}`

## Request

- Base URL: `https://verifiedhandles.org`
- URL: `https://verifiedhandles.org/api/editor/{vhid}`
- Auth: one of:
  - none
  - HTTP bearer

What the editor opens with: the fields a change may send, as they are now, the current revision to send as `base_revision_id`, each handle with who manages it, the platforms, and what the caller may do (`capabilities`). Signed in, it carries your own unsaved draft of the entry too (`draft`). Signed out it answers too, with every capability false. Read it before proposing a change. An email address is shown only to a caller who may edit the entry live; anyone else gets it masked, and sends it back as it came to keep it.

## Path parameters

- `vhid` string, required

## Response `200`

The entry, for editing.

- EditorContext: An entry as the editor opens it, and what the caller may do to it.
  - `vhid` string, required
  - `key` string, required: The entry’s canonical key: its short name, or its VHID.
  - `signedIn` boolean, required
  - `csrf` string, nullable, required: For a browser session’s changes. A key needs none.
  - `capabilities` object, required: What the caller may do to this entry. All false signed out.
    - `canEditLive` boolean, required: May save a change live, with no review.
    - `canPropose` boolean, required: May propose a change (`POST /api/entity/{vhid}/proposals`).
    - `canUploadMedia` boolean, required
    - `canUploadFromUrl` boolean, required
    - `canUploadUnlicensed` boolean, required
    - `canLinkImages` boolean, required
  - `tools` object, nullable, required: Reviewers’ and managers’ tools for the entry. Null for anyone who neither reviews nor manages entries.
  - `proposePolicy` 'registered' | 'trusted' | 'admin' | 'closed', required: Who may propose changes to it.
  - `editPolicy` 'trusted' | 'admin', required: Who may edit it live.
  - `accountBlocked` boolean, required
  - `signInHost` string, required: The host signing in takes a visitor to (JEMEDIA Accounts), which the editor names before it does.
  - `draft` object, nullable, required: Your own unsaved draft of this entry, as `GET /api/entity/{vhid}/draft` answers it, so the editor reads it here and not in a call of its own. Null when you have none, and signed out.
    - `vhid` string, required
    - `base_revision_id` string, nullable, required: The revision the draft was edited against, or null.
    - `saved_at` string, date-time, required: Its last change.
    - `expires_at` string, date-time, required: When it is deleted unless changed again: 30 days after `saved_at`.
    - `draft` EntryDraft, required: An unsaved edit to an entry, in the editor’s own shape.
      - `vhid` string: The entry’s VHID. Optional when sending; it must be this entry’s.
      - `savedAt` number: When the draft was last changed, in milliseconds since 1970. Ignored when sending: the server keeps its own time.
      - `fields` object, required: The entry’s fields as edited. The description is HTML, kept through the same allowlist as a saved description.
        - `title` string
        - `subtitle` string
        - `description` string
        - `short` string
      - `handles` object[]
        - `platform_id` string, required
        - `value` string, required
        - `display` string, nullable
        - `kept` true: A masked email kept as stored.
        - `ref` string: Which stored email a kept one is.
      - `customOrder` boolean: The handles are in the entry’s own order.
      - `linkNames` object: VHID → name, for the entries the description links to.
      - `image` object, nullable: The lead image as picked: null when removed, absent when untouched.
        - `id` string, required: The image’s id.
        - `kind` 'commons' | 'local', required
        - `commons_filename` string, nullable, required
      - `gallery` object[]: The images after the lead, when changed.
        - `id` string, required: The image’s id.
        - `kind` 'commons' | 'local', required
        - `commons_filename` string, nullable, required
      - `imageLinks` object: Image id → link as typed, when changed.
      - `relinquish` string[]: Fields to hand to Wikidata on save.
      - `takeover` string[]: Fields to take back from Wikidata on save.
      - `dropCredit` true: Remove the Wikipedia credit on save.
      - `creditPage` string: A Wikipedia page named for the credit, as typed.
      - `creditManage` false: With `creditPage`: the description is not to go to the sync.
      - `handleTakeover` string[]
      - `handleRelinquish` string[]
      - `handleRelease` string[]
  - `baseRevisionId` string, nullable, required: The entry’s current revision. Send it as `base_revision_id` with a change, so a change made meanwhile is caught.
  - `editable` object, required: The fields a change may send, as they are now.
    - `title` string, required
    - `subtitle` string, nullable, required
    - `description` string, nullable, required
    - `short` string, nullable, required
    - `image_id` string, nullable, required
    - `image_links` object, required
    - `custom_handle_order` boolean, required
  - `handles` object[], required: Every handle, in order, as a change sends them back.
    - `platform_id` string, required
    - `value` string, nullable, required: Null for an email address when the caller may not edit the entry live.
    - `value_norm` string, nullable, required: Its key as the site stores it (letter case folded where the platform ignores it), to tell whether another value is the same handle. Null where `value` is masked.
    - `display` string, nullable, required
    - `masked` true: Present on a masked email: the address is kept but not shown.
    - `ref` string, nullable: On a masked email: which stored handle it is (null when the entry no longer has it). Send it back as `{platform_id, value: null, ref}` to keep that address; leave it out of the list to remove it.
    - `name` string, nullable, required: The platform’s display name.
    - `owner` 'wikidata' | 'site', required: `wikidata`: the sync keeps it up to date. `site`: a person owns it.
    - `wd` object, nullable, required: What the entry’s Wikidata item says about this value, or null when it says nothing.
      - `state` 'listed' | 'deprecated' | 'ended' | 'outranked' | 'gone', required
      - `since` string, nullable, required
      - `removeAfter` string, nullable, required
      - `replacedBy` string[], required
      - `reason` string, nullable
      - `qualifierOnly` boolean, required: A YouTube channel ID the item states only as a qualifier on its YouTube handle: `state` is `gone`, but the sync counts it as listed and never removes it.
    - `channel_title` string: A YouTube row’s channel title, as VH knows it without asking YouTube: for a channel ID, the title VH’s handle checker last read, else the one the item’s Wikidata statement names; for a handle, its channel’s, once the checker has read it. The editor shows it under the row. Absent when there is none.
  - `heldBack` unknown[], required: Values a person took off that Wikidata still lists, held back from the sync. An email’s are left out of both lists for a caller who may not edit the entry live, as its handle is masked.
    - unknown
  - `heldBackNotListed` unknown[], required: Values a person took off that Wikidata listed once and no longer lists as current. Still held back from the sync (never deleted by itself); the editor shows them collapsed, each with Allow again.
    - unknown
  - `linkNames` object, required: VHID → current title of each entry the description links to.
  - `provenance` object, required: For each field the sync may manage, who manages it now.
  - `qid` string, nullable, required: The entry’s Wikidata item.
  - `syncLocked` boolean, required: The sync never changes this entry (it is protected or claimed).
  - `descriptionSource` unknown, required
  - `image` object, nullable, required
    - `id` string, required
    - `kind` 'commons' | 'local', required
    - `commons_filename` string, nullable, required
    - `url` string, required: The image on this site (`/img/w/…`).
    - `width` integer, nullable, required
    - `height` integer, nullable, required
    - `commonsPage` string, nullable, required
    - `license` string, nullable
    - `license_name` string, nullable
    - `credit` string, nullable
    - `plate` unknown
  - `gallery` object[], required
    - `id` string, required
    - `kind` 'commons' | 'local', required
    - `commons_filename` string, nullable, required
    - `url` string, required: The image on this site (`/img/w/…`).
    - `width` integer, nullable, required
    - `height` integer, nullable, required
    - `commonsPage` string, nullable, required
    - `license` string, nullable
    - `license_name` string, nullable
    - `credit` string, nullable
    - `plate` unknown
  - `galleryLogo` string, nullable, required
  - `platforms` object[], required: Every platform a handle may be on, the most used first.
    - `id` string, required
    - `name` string, required
    - `category` string, required
    - `uri_prefix` string, nullable, required
    - `url_template` string, required: How a value becomes its link (doc 01 §4).
    - `is_double` boolean, required
    - `at_prefix` boolean, required
    - `wikidata_prop` string, nullable, required
    - `case_fold` boolean, required
    - `icon` string, nullable, required

## Other responses

- `400`: Or the request sent a key and a session cookie together (`bearer_with_cookie`): send one.
- `401`: No key was sent (`auth_required`), or the key was refused: unknown, revoked or expired, its holder may no longer use keys, or this instance takes none. Carries `WWW-Authenticate: Bearer`. After 60 refused keys from one IP address in a minute, every key from there is answered `429` (text, with `Retry-After`) until the minute is up.
- `403`: A read-only key tried to change something (`read_only_key`), or the account is blocked (`forbidden`).
- `404`: No public entry has that VHID.
- `503`: The site is down for maintenance. The body is the maintenance page, as HTML. Try again later: `Retry-After` gives the seconds.

---

[API](https://skmtc.dev/verifiedhandles/apis/verified-handles-api.md) · [All operations](https://skmtc.dev/verifiedhandles/apis/verified-handles-api/llms.txt) · [OpenAPI document](https://skmtc.dev/verifiedhandles/apis/verified-handles-api/revisions/40720de2e0ec?raw)
