Page MenuHomePhabricator

🟩️ Create a statement on an item via POST /entities/items/{item_id}/statements
Closed, ResolvedPublic13 Estimated Story Points


As a tool author I want to create new statements on an item so that changes created in my tool are stored in the Wikibase instance
As a Wikidata gadget author I want to create statements on an item so that changes made by gadget are stored back on Wikidata

Apart from statement data, mediawiki "metadata" can be specified:

  • "comment" to be included in the edit summary
    • use "auto summary" as the default edit summary in case no comment is provided by the user. If a comment is provided, it should be (pre- or) appended to the auto summary.
  • "comment" metadata is not in scope for this task
  • mediawiki tag(s) for the edit
    • no tags should be added, if none are provided
  • flag edit as made by a bot
    • default: false

Also, to help Wikibase solve potential edit conflict, the latest revision of an item known by a client when making the request can also be provided. No latest revision id should be expected (for now).

The response:

  • should have the HTTP status code 201,
  • should include the newly created statement in the body (including the new statement ID),
  • should provide a Location header with the URL of the newly created item specific single statement,
  • should include ETag and Last-Modified header fields for the item on which the statement was created.

Error scenarios:

  • invalid input (400)
    • this includes various scenarios with invalid values, non-existing properties, qualifiers etc in the provided statement json
    • Error messages (code - message) for invalid values in the input
      • incorrect statement data (not well formed JSON, non existing proprties, etc catch-all error for now): invalid-statement-data: "Invalid statement data provided"
      • incorrect mediawiki tag: invalid-edit-tag: "invalid MediaWiki tag: {tag}"
      • invalid value for the bot flag (if not caught by the framework - do not override the framework behaviour if already provided): invalid-bot-flag: "Invalid bot flag value: Must be "true" or "false" "
  • item does not exist (404)
  • the item is a redirect (409)
    • code: "redirected-item"
    • message: "Item {item_id} has been merged into {other_id}."
  • unexpected error (500)

Authentication (i.e. attributing the edit to an authenticated mediawiki user) is not in scope for this task. It is tracked separately in T309846.

See also

Related Objects

Event Timeline

Lucas_Werkmeister_WMDE renamed this task from Create a stement on an item via POST /entities/items/{item_id}/statements to Create a statement on an item via POST /entities/items/{item_id}/statements.Apr 22 2022, 9:10 AM
Lucas_Werkmeister_WMDE updated the task description. (Show Details)
Silvan_WMDE set the point value for this task to 13.

(To be continued) Notes from task breakdown:


  • create StatementValidator interface in Wikibase\Repo\RestApi\Validation
    • has two methods: validate( array $serializedStatement ): ?ValidationError and getValidatedStatement(): ?Statement
  • implement StatementValidator interface using SnakValidator and StatementDeserializer in new namespace similar to DataAccess (may have external dependencies)
    • deserializes the statement first and writes it to an instance property (with a getter method)
    • use SnakValidator for validation post deserialization
  • create new EditMetadataValidator validator: data type validation for metadata fields (tags: array, bot: bool)
  • use case validator has 3 dependencies: ItemIdValidator, StatementValidator, EditMetadataValidator


  • builds Location header from GUID contained in the use case response object


  • change the GetItemStatementJsonPresenter to StatementJsonPresenter for Statement presentation, change method signature to accept Statement as a param instead of response object

EditMetadata (new domain object)

  • contains comment, tags, bot, base rev id, user

ItemRevision ("new" domain object)

  • contains item, latest revision id, last modified


  • new service interface in Wikibase\Repo\RestApi\Domain\Services namespace
    • has method update( Item $item, EditMetadata $editMetadata ): ItemRevision
  • implement using MediawikiEditEntity or its factory (EntityStore is too low level)
  • new implementation in DataAccess namespace

use case life cycle:

  • route handler creates request object with metadata and serialized statement
  • use case deserializes statement
    • returns error response in case of failure
  • use case validates item id, metadata and statement (using StatementValidator)
  • item latest revision metadata lookup and redirect / not found handling
  • load item using retriever
  • generate guid using itemid and set on statement
  • add statement to item using $item->addStatement
  • save item, set revision id and last modified date
  • respond with response object with statement returned from db and revision metadata

Silvan creates:

  • spec
  • business-logic only use case (start with happy path only?): AddItemStatement
    • create the "shell" of the AddItemStatementValidator and delegate to the deserializer for getValidatedStatement
    • create ItemUpdater interface, (re) create ItemRevision class, create EditMetadata class
  • create StatementValidator
  • create EditMetadataValidator
  • add validation to use case (item id, edit metadata, statement)
    • create AddItemStatementValidator bundling the three validators

Jakob creates:

  • implement ItemUpdater using MediawikiEditEntityFactory
  • create initial AddItemStatementRouteHandler
    • unexpected error handling
    • auth header
  • item does not exist handling
  • generate location header from response
  • spec tests
Jakob_WMDE renamed this task from Create a statement on an item via POST /entities/items/{item_id}/statements to 🟩️ Create a statement on an item via POST /entities/items/{item_id}/statements.Jun 3 2022, 9:41 AM

This is now ready for verification on beta!

Some example payloads for convenience:

	"statement": {
		"type": "statement",
		"mainsnak": {
			"snaktype": "novalue",
			"property": "P92"
	"statement": {
		"type": "statement",
		"mainsnak": {
			"snaktype": "value",
			"datavalue": {
				"value": "potato",
				"type": "string"
			"property": "P92"

Verified. Some edge-case issues encountered and reported to the engineers. Tickets might surface at some point. Thanks

Verified. Handling of redirected items indeed works, Location response header documented in the autodocs. All grand, thank you