C2PA Soft Binding API

1. Soft Binding Resolution API for C2PA Manifest Recovery

C2PA specifies a mechanism for recovering a C2PA Manifest for an asset, for example when the metadata containing the C2PA Manifest has been stripped. This mechanism is a soft binding (for example an invisible watermark or content fingerprint). The soft binding is used to look-up the C2PA Manifest within a Manifest Repository. The soft binding is described by the soft binding assertion.

This document describes a series of use cases for why it is necessary to recover C2PA Manifests that have become decoupled from the asset to which they belong. It then goes into detail on how to use soft bindings to solve for these use cases. This process of recovering C2PA Manifests using soft bindings is composed of 2 key components:

1.1. Use Cases

The following use cases illustrate common situations in which C2PA Manifest recovery is performed. In these use cases: Alice is a content producer; Bob is content consumer; Mallory is a malicious `man in the middle' actor.

1.1.1. UC1: Recovery from stripping of C2PA metadata

Alice is a photojournalist and captures a photo of an event, editing it to enhance visibility of some content. The camera and editing tool implement C2PA and each embed a manifest within the image. Alice knows that some distribution platforms will strip C2PA metadata and so decides to add an imperceptible watermark to the photo prior to submitting it for publication. The watermark may be added via Alice’s image editing tool, modifying the image pixels prior to signing the manifest. Or, Alice may utilize a watermark vendor’s tool to retroactively embed the watermark in the image pixels, signing the asset with a further manifest.

Bob later encounters Alice’s photo on social media but the C2PA Manifest has been stripped. Bob’s software (web browser or news client) detects that a watermark is present within the photo. Bob has configured his software to automatically interrogate well-known manifest repositories (e.g., from major news organizations, vendors of watermarking/tools) to obtain the manifest using the watermark. Bob recovers and views the manifest of the photo.

Bob is therefore aware of the provenance information for the asset, enabling him to make an informed trust decision on the asset.

1.1.2. UC2: Recovery from malicious substitution of provenance (manifest replaced, watermark unchanged)

Alice is a photojournalist who embeds C2PA metadata within her assets to protect their integrity and gain attribution. Mallory wishes to manipulate the provenance of Alice’s photo to fake its creation story or to steal attribution. Mallory substitutes the manifest in the asset creating a new provenance chain signed by himself. Fortunately, Alice has included a watermark in her digital content.

When Bob encounters Alice’s photo online, he performs a lookup from a manifest store to obtain the manifest associated with the watermark. Bob can then compare the recovered manifest to the manifest embedded within the asset to see if the story matches up and make an appropriate trust decision e.g., potentially deciding to believe the manifest recovered from the trusted manifest store.

1.1.3. UC3: Recovery from malicious substitution of provenance (manifest stripped, watermark substituted)

Alice is a journalist who embeds C2PA metadata within her assets to protect their integrity and gain attribution. Mallory wishes to manipulate the provenance of Alice’s audio recording to fake its creation story or to steal attribution. Mallory strips the metadata from Alice’s audio recording and modifies the recording to render the watermark unreadable. She then embeds a new watermark. Mallory registers a new manifest within a watermarking vendor’s manifest store, using his new soft binding. Mallory publishes this modified audio recording on social media.

Bob encounters Mallory’s audio recording on social media and detects the presence of a watermark. Bob resolves the watermark via lookup and obtains a false attribution / back story to the audio recording. However, Bob notices that the manifest was signed by Mallory not Alice so can make an appropriate trust decision.

1.1.4. UC4: Watermark lookup in federated manifest store

Alice is a photojournalist who embeds C2PA metadata within her assets to protect their integrity and gain attribution. She also embeds a watermark e.g., per UC1 and chooses any of several manifest repositories to store her manifest.

In addition to storing her manifest, she registers her watermark within a service that maps her watermark (soft binding) to the location of her manifest in one or many manifest stores.

Bob detects a watermark in Alice’s image online on social media but its manifest has been stripped by the social platform. Bob queries the service to figure out which manifest repository to resolve the watermarked soft binding against. Bob then queries the appropriate repository.

1.1.5. UC5: Preserving provenance through non-C2PA capable toolchains

Acme Corp maintains a content production pipeline where some stages are non-C2PA capable. Bob receives an asset from freelance journalist Alice, containing a valid C2PA Manifest. Bob’s software inserts into the digital content of the assets a watermark containing a unique identifier and records the unique identifier as a soft binding assertion in the manifest. The manifest is placed within a manifest repository maintained internally by Acme Corp. The content passes through legacy content production processes that strip the C2PA Manifest. The final stages of production are C2PA compliant. The watermark is read from the asset and submitted as a query to the manifest repository run internally by Acme Corp. After passing through the non-C2PA tools, the manifest is automatically matched using the embedded watermark, and is included as an ingredient in a new manifest, which documents that actions have been performed on the content prior to entering the C2PA capable final stage of the pipeline. The manifest is embedded into the asset in the usual way. The content is published and provenance of the asset may be traced back to Alice by end consumers of the content.

1.1.6. UC6: Indicating Content Generated by AI

Alice is a graphic designer working on illustrating a novel. She is working on a picture of a well-known monument being destroyed by a flood. To design this image she uses a C2PA capable generative AI tool. After several prompts and manual edits she is happy with the results and renders it into a JPEG image. Because of the regulations on GenAI in force in Alice’s country, the GenAI tool adds a manifest to the image indicating the role of GenAI in creation of the image. Alice also applies a watermark to the image per UC1.

Mallory is a malicious user wanting to create fake-news from Alice’s image. He takes a screenshot of the image and publishes it on different social media platforms. Mallory’s malicious intention is to use the image of the damaged monument as clickbait in a fake-news campaign. Unfortunately, some social media platforms are not C2PA capable and strip the manifest off. However, the watermark persists through the screenshot and social media rendition processes.

Bob views Mallory’s image on social media and is running web browser software that can detect the watermark. The browser recognizes that the watermark algorithm is listed in the C2PA soft binding algorithm list and displays the Content Credentials pin on the image. Bob clicks on the pin and the browser retrieves the manifest associated with the image. It displays the manifest and flags the image as generated by AI. Bob realizes he does not have to worry as the image is fictitious and was generated by AI.

1.2. Usage Flows

1.2.1. Decoupled manifests

While an increasing number of tools and platforms retain and add to C2PA Manifests, a number of workflows remove C2PA Manifests, leading to decoupled provenance information from assets. Consequently, the asset may lack the correct active manifest or contain no C2PA Manifest store at all. The soft binding algorithm list and resolution API may be used to recover the active manifest.

This covers the following use cases: UC1, UC2, UC5, UC6

1.2.1.1. Watermarking algorithms

[watermark-recovery] provides an example flow leveraging the soft binding algorithm list and resolution API to recover C2PA Manifests using an invisible watermark embedded in an asset.

Diagram
1.2.1.2. Fingerprinting algorithms

[fingerprint-recovery] provides an example flow leveraging the soft binding algorithm list and resolution API to recover C2PA Manifests using an asset’s fingerprint.

Diagram

1.2.2. Recovering manifests

The primary use of soft binding algorithms is the recovery of detached C2PA Manifests. However, they can also be used for other use cases such as providing information about the potential substitutions of manifests. This is done by comparing a local active C2PA Manifest (i.e., attached to the asset) with a C2PA Manifest recovered via the soft binding algorithm list and resolution API.

This covers the following use case: UC3, UC2

1.2.2.1. Watermarking algorithms

[watermark-golden] provides an example flow leveraging the soft binding algorithm list and resolution API to retrieve a C2PA Manifest using an invisible watermark embedded in an asset and cross-check it with the local active C2PA manifest.

Diagram
1.2.2.2. Fingerprinting Algorithms

[fingerprint-golden] provides an example flow leveraging the soft binding algorithm list and resolution API to retrieve a C2PA Manifest using an asset’s fingerprint and cross-check it with the local C2PA active manifest.

Diagram
1.2.2.3. Combining Watermarking and Fingerprinting

A check may performed to verify that the recovered manifest matches the query asset bearing the watermark. This mitigates the possibility of attacking the watermarking system to spoof (e.g., transfer) a watermark from one asset to another.

One way to automate this check is to store a fingerprint of the asset within the recovered manifest, and compare the fingerprint against a similarly computed fingerprint from the query asset. This is shown in [watermark-and-fingerprint].

Diagram

1.3. Soft Binding Algorithm List

The soft binding algorithm list is an authoritative list of C2PA supported soft binding algorithms. It lists the fingerprinting and watermarking technologies that C2PA clients may use to recover manifests. Entries in the list also contain additional information on the algorithms to facilitate interoperability.

Developers wanting their soft binding algorithms to be referenced in soft binding assertions or in soft binding resolution API transactions shall request they be added as a new entries in the soft binding algorithm list.

1.4. Soft Binding Resolution API specification

The soft binding resolution API is a Web API providing a standard way of retrieving C2PA Manifest stores from a soft binding resolution API endpoint given a soft binding value, a manifest identifier, or an asset.

The API specification and documentation is available below in the OpenAPI format as a JSON or YAML document.

{
  "openapi": "3.0.3",
  "info": {
    "title": "C2PA Soft Binding Resolution API",
    "description": "This is the OpenAPI specification of the C2PA Soft Binding Resolution API. This document specifies a web service API endpoint for matching soft bindings (e.g., watermarks or fingerprints) to C2PA Manifests.",
    "version": "1.0.0"
  },
  "externalDocs": {
    "description": "C2PA Specification",
    "url": "https://c2pa.org/specifications"
  },
  "servers": [
    {
      "url": "https://c2pa.example.org/v1"
    }
  ],
  "paths": {
    "/matches/byBinding": {
      "get": {
        "tags": [
          "query"
        ],
        "summary": "Returns C2PA Manifest identifiers corresponding to a soft binding.",
        "description": "Given one soft binding, find zero or more manifests identifiers within the manifest store matching the soft binding.",
        "operationId": "queryByBinding",
        "parameters": [
          {
            "name": "value",
            "in": "query",
            "description": "A base64-encoded string describing, in algorithm specific format, the value of the soft binding to be used as the query. Note: if the value is expected to be too large to fit in a URL then the POST method may be used.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "alg",
            "in": "query",
            "description": "A string identifying the soft binding algorithm and version of that algorithm used as per the authoritative list of C2PA soft binding algorithm names available at: https://github.com/c2pa-org/softbinding-algorithm-list",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "maxResults",
            "in": "query",
            "description": "The maximum number of manifest identifiers to return for each query.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/c2pa.softBindingQueryResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid query value",
            "content": {}
          },
          "414": {
            "description": "Query too long, consider using POST instead",
            "content": {}
          },
          "500": {
            "description": "Service failure",
            "content": {}
          }
        },
        "security": [
          {
            "auth": [
              "fetch:manifests"
            ]
          }
        ]
      },
      "post": {
        "tags": [
          "query"
        ],
        "summary": "Returns C2PA Manifest identifiers corresponding to a large soft binding value.",
        "description": "Given a large soft binding value, find zero or more matching manifest identifiers. Use this method if the size of the soft binding value is expected to be large too large to fit in a URL, otherwise favor the use of GET.",
        "operationId": "queryByLargeBinding",
        "parameters": [
          {
            "name": "maxResults",
            "in": "query",
            "description": "The maximum number of manifests to return for each query.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 10
            }
          }
        ],
        "requestBody": {
          "description": "Soft binding query JSON document.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/c2pa.softBindingQuery"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/c2pa.softBindingQueryResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid query value",
            "content": {}
          },
          "500": {
            "description": "Service failure",
            "content": {}
          }
        },
        "security": [
          {
            "auth": [
              "fetch:manifests"
            ]
          }
        ]
      }
    },
    "/matches/byContent": {
      "post": {
        "tags": [
          "query"
        ],
        "summary": "Finds C2PA Manifest identifiers using a digital asset.",
        "description": "Find zero or more C2PA Manifest identifiers within the manifest store using an uploaded file containing a digital asset.",
        "operationId": "uploadFile",
        "parameters": [
          {
            "name": "alg",
            "in": "query",
            "description": "A string identifying the soft binding algorithm and version of that algorithm used as per the authoritative list of C2PA soft binding algorithm names available at: https://github.com/c2pa-org/softbinding-algorithm-list",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "maxResults",
            "in": "query",
            "description": "The maximum number of manifests identifiers return for the query.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 10
            }
          },
          {
            "name": "hintAlg",
            "in": "query",
            "description": "An optional parameter specifying an additional soft binding algorithm name and version (as per the authoritative list of C2PA soft binding algorithm names available at: https://github.com/c2pa-org/softbinding-algorithm-list) to aid in resolution of the query.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "hintValue",
            "in": "query",
            "description": "An optional parameter specifying an additional soft binding algorithm value for the corresponding hintAlg to aid in resolution of the query.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "description": "Asset to match to manifests.",
          "content": {
            "image/*": {
              "schema": {
                "type": "string",
                "format": "binary",
                "description": "Asset of type image."
              }
            },
            "audio/*": {
              "schema": {
                "type": "string",
                "format": "binary",
                "description": "Asset of type audio."
              }
            },
            "video/*": {
              "schema": {
                "type": "string",
                "format": "binary",
                "description": "Asset of type video."
              }
            },
            "application/*": {
              "schema": {
                "type": "string",
                "format": "binary",
                "description": "Asset of type application, such as `application/pdf`."
              }
            },
            "model/*": {
              "schema": {
                "type": "string",
                "format": "binary",
                "description": "Asset of type model."
              }
            },
            "text/*": {
              "schema": {
                "type": "string",
                "format": "string",
                "description": "Asset of type text."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/c2pa.softBindingQueryResult"
                }
              }
            }
          },
          "415": {
            "description": "Invalid asset type",
            "content": {}
          },
          "500": {
            "description": "Service failure",
            "content": {}
          }
        },
        "security": [
          {
            "auth": [
              "fetch:manifests"
            ]
          }
        ]
      }
    },
    "/manifests/{manifestId}": {
      "get": {
        "tags": [
          "fetch"
        ],
        "summary": "Returns a full C2PA Manifest Store or an active C2PA Manifest.",
        "description": "Retrieve a C2PA Manifest by manifest identifier. This either returns the active manifest or the entire C2PA Manifest Store that the active manifest identifier is part of. C2PA Manifest identifiers should follow the format described in the C2PA Technical specification at xref:specs:C2PA_Specification.adoc[_unique_identifiers]",
        "operationId": "getManifestById",
        "parameters": [
          {
            "name": "returnActiveManifest",
            "in": "query",
            "description": "Specifies if only the active manifest should be returned. By default the entire C2PA Manifest Store is returned.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "manifestId",
            "in": "path",
            "description": "Identifier of the C2PA Manifest to return",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/c2pa": {}
            }
          },
          "400": {
            "description": "Invalid C2PA Manifest Id supplied",
            "content": {}
          },
          "404": {
            "description": "C2PA Manifest Id not found",
            "content": {}
          },
          "500": {
            "description": "Service failure",
            "content": {}
          }
        },
        "security": [
          {
            "auth": [
              "fetch:manifests"
            ]
          }
        ]
      }
    },
    "/services/supportedAlgorithms": {
      "get": {
        "tags": [
          "service"
        ],
        "summary": "Returns a list of the soft binding algorithms supported by the service.",
        "description": "Enumerate the names of soft binding algorithms supported as queries by the service. See https://github.com/c2pa-org/softbinding-algorithm-list for an authoritative list of C2PA soft binding algorithm names.",
        "operationId": "getSupportedBindings",
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/c2pa.softBindingAlgList"
                }
              }
            }
          },
          "500": {
            "description": "Service failure",
            "content": {}
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "c2pa.softBindingAlgList": {
        "description": "list of the names of soft binding algorithms supported by this service. The authoritative list of name is available here: https://github.com/c2pa-org/softbinding-algorithm-list",
        "properties": {
          "watermarks": {
            "type": "array",
            "items": {
              "type": "object",
              "oneOf": [
                {
                  "required": [
                    "watermarks"
                  ]
                },
                {
                  "required": [
                    "fingerprints"
                  ]
                }
              ],
              "properties": {
                "alg": {
                  "type": "string",
                  "example": "foo.bar.watermark.1",
                  "description": "Unique identifier of a fingerprint algorithm."
                }
              },
              "required": [
                "alg"
              ]
            }
          },
          "fingerprints": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "alg": {
                  "type": "string",
                  "example": "foo.bar.fingerprint.1",
                  "description": "Unique identifier of a watermark algorithm."
                }
              },
              "required": [
                "alg"
              ]
            }
          }
        }
      },
      "c2pa.softBindingQuery": {
        "required": [
          "value",
          "alg"
        ],
        "type": "object",
        "properties": {
          "alg": {
            "type": "string",
            "description": "A string identifying the soft binding algorithm and version of that algorithm used."
          },
          "value": {
            "type": "string",
            "description": "A base64-encoded string describing, in algorithm specific format, the value of the soft binding to be used as the query."
          }
        }
      },
      "c2pa.softBindingQueryResult": {
        "type": "object",
        "properties": {
          "matches": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "manifestId": {
                  "type": "string",
                  "description": "Unique identifier of a matched C2PA Manifest"
                },
                "endpoint": {
                  "type": "string",
                  "description": "Endpoint of a Soft Binding Resolution API from which the C2PA Manifest may be obtained. If the endpoint is absent then the C2PA Manifest is available from same endpoint the query was sent to using the /manifests endpoint."
                },
                "similarityScore": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 100,
                  "description": "An integer score in the range (0-100) representing the strength of match, if appropriate, where 0 is the weakest possible match and 100 is the strongest possible match."
                }
              },
              "required": [
                "manifestId"
              ]
            }
          }
        }
      }
    },
    "securitySchemes": {
      "auth": {
        "type": "oauth2",
        "flows": {
          "implicit": {
            "authorizationUrl": "http://example.c2pa.org/oauth/dialog",
            "scopes": {
              "fetch:manifests": "search and read manifests within the manifest store."
            }
          }
        }
      }
    }
  }
}
openapi: 3.0.3
info:
  title: C2PA Soft Binding Resolution API
  description: >-
    This is the OpenAPI specification of the C2PA Soft Binding Resolution API.
    This document specifies a web service API endpoint for matching soft
    bindings (e.g., watermarks or fingerprints) to C2PA Manifests.
  version: 1.0.0
externalDocs:
  description: C2PA Specification
  url: https://c2pa.org/specifications
servers:
  - url: https://c2pa.example.org/v1
paths:
  /matches/byBinding:
    get:
      tags:
        - query
      summary: Returns C2PA Manifest identifiers corresponding to a soft binding.
      description: >-
        Given one soft binding, find zero or more manifests identifiers within
        the manifest store matching the soft binding.
      operationId: queryByBinding
      parameters:
        - name: value
          in: query
          description: >-
            A base64-encoded string describing, in algorithm specific format,
            the value of the soft binding to be used as the query. Note: if the
            value is expected to be too large to fit in a URL then the POST
            method may be used.
          required: true
          schema:
            type: string
        - name: alg
          in: query
          description: >-
            A string identifying the soft binding algorithm and version of that
            algorithm used as per the authoritative list of C2PA soft binding
            algorithm names available at:
            https://github.com/c2pa-org/softbinding-algorithm-list
          required: true
          schema:
            type: string
        - name: maxResults
          in: query
          description: The maximum number of manifest identifiers to return for each query.
          schema:
            type: integer
            minimum: 1
            default: 10
      responses:
        "200":
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/c2pa.softBindingQueryResult"
        "400":
          description: Invalid query value
          content: {}
        "414":
          description: Query too long, consider using POST instead
          content: {}
        "500":
          description: Service failure
          content: {}
      security:
        - auth:
            - fetch:manifests
    post:
      tags:
        - query
      summary: >-
        Returns C2PA Manifest identifiers corresponding to a large soft binding
        value.
      description: >-
        Given a large soft binding value, find zero or more matching manifest
        identifiers. Use this method if the size of the soft binding value is
        expected to be large too large to fit in a URL, otherwise favor the use
        of GET.
      operationId: queryByLargeBinding
      parameters:
        - name: maxResults
          in: query
          description: The maximum number of manifests to return for each query.
          schema:
            type: integer
            minimum: 1
            default: 10
      requestBody:
        description: Soft binding query JSON document.
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/c2pa.softBindingQuery"
        required: true
      responses:
        "200":
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/c2pa.softBindingQueryResult"
        "400":
          description: Invalid query value
          content: {}
        "500":
          description: Service failure
          content: {}
      security:
        - auth:
            - fetch:manifests
  /matches/byContent:
    post:
      tags:
        - query
      summary: Finds C2PA Manifest identifiers using a digital asset.
      description: >-
        Find zero or more C2PA Manifest identifiers within the manifest store
        using an uploaded file containing a digital asset.
      operationId: uploadFile
      parameters:
        - name: alg
          in: query
          description: >-
            A string identifying the soft binding algorithm and version of that
            algorithm used as per the authoritative list of C2PA soft binding
            algorithm names available at:
            https://github.com/c2pa-org/softbinding-algorithm-list
          schema:
            type: string
        - name: maxResults
          in: query
          description: The maximum number of manifests identifiers return for the query.
          schema:
            type: integer
            minimum: 1
            default: 10
        - name: hintAlg
          in: query
          description: >-
            An optional parameter specifying an additional soft binding
            algorithm name and version (as per the authoritative list of C2PA
            soft binding algorithm names available at:
            https://github.com/c2pa-org/softbinding-algorithm-list) to aid in
            resolution of the query.
          schema:
            type: string
        - name: hintValue
          in: query
          description: >-
            An optional parameter specifying an additional soft binding
            algorithm value for the corresponding hintAlg to aid in resolution
            of the query.
          schema:
            type: string
      requestBody:
        description: Asset to match to manifests.
        content:
          image/*:
            schema:
              type: string
              format: binary
              description: Asset of type image.
          audio/*:
            schema:
              type: string
              format: binary
              description: Asset of type audio.
          video/*:
            schema:
              type: string
              format: binary
              description: Asset of type video.
          application/*:
            schema:
              type: string
              format: binary
              description: Asset of type application, such as `application/pdf`.
          model/*:
            schema:
              type: string
              format: binary
              description: Asset of type model.
          text/*:
            schema:
              type: string
              format: string
              description: Asset of type text.
      responses:
        "200":
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/c2pa.softBindingQueryResult"
        "415":
          description: Invalid asset type
          content: {}
        "500":
          description: Service failure
          content: {}
      security:
        - auth:
            - fetch:manifests
  /manifests/{manifestId}:
    get:
      tags:
        - fetch
      summary: Returns a full C2PA Manifest Store or an active C2PA Manifest.
      description: >-
        Retrieve a C2PA Manifest by manifest identifier. This either returns the
        active manifest or the entire C2PA Manifest Store that the active
        manifest identifier is part of. C2PA Manifest identifiers should follow
        the format described in the C2PA Technical specification at
        xref:specs:C2PA_Specification.adoc[_unique_identifiers]
      operationId: getManifestById
      parameters:
        - name: returnActiveManifest
          in: query
          description: >-
            Specifies if only the active manifest should be returned. By default
            the entire C2PA Manifest Store is returned.
          schema:
            type: boolean
            default: false
        - name: manifestId
          in: path
          description: Identifier of the C2PA Manifest to return
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Successful operation
          content:
            application/c2pa: {}
        "400":
          description: Invalid C2PA Manifest Id supplied
          content: {}
        "404":
          description: C2PA Manifest Id not found
          content: {}
        "500":
          description: Service failure
          content: {}
      security:
        - auth:
            - fetch:manifests
  /services/supportedAlgorithms:
    get:
      tags:
        - service
      summary: Returns a list of the soft binding algorithms supported by the service.
      description: >-
        Enumerate the names of soft binding algorithms supported as queries by
        the service. See https://github.com/c2pa-org/softbinding-algorithm-list
        for an authoritative list of C2PA soft binding algorithm names.
      operationId: getSupportedBindings
      responses:
        "200":
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/c2pa.softBindingAlgList"
        "500":
          description: Service failure
          content: {}
components:
  schemas:
    c2pa.softBindingAlgList:
      description: >-
        list of the names of soft binding algorithms supported by this service.
        The authoritative list of name is available here:
        https://github.com/c2pa-org/softbinding-algorithm-list
      properties:
        watermarks:
          type: array
          items:
            type: object
            oneOf:
              - required:
                  - watermarks
              - required:
                  - fingerprints
            properties:
              alg:
                type: string
                example: foo.bar.watermark.1
                description: Unique identifier of a fingerprint algorithm.
            required:
              - alg
        fingerprints:
          type: array
          items:
            type: object
            properties:
              alg:
                type: string
                example: foo.bar.fingerprint.1
                description: Unique identifier of a watermark algorithm.
            required:
              - alg
    c2pa.softBindingQuery:
      required:
        - value
        - alg
      type: object
      properties:
        alg:
          type: string
          description: >-
            A string identifying the soft binding algorithm and version of that
            algorithm used.
        value:
          type: string
          description: >-
            A base64-encoded string describing, in algorithm specific format,
            the value of the soft binding to be used as the query.
    c2pa.softBindingQueryResult:
      type: object
      properties:
        matches:
          type: array
          items:
            type: object
            properties:
              manifestId:
                type: string
                description: Unique identifier of a matched C2PA Manifest
              endpoint:
                type: string
                description: >-
                  Endpoint of a Soft Binding Resolution API from which the C2PA
                  Manifest may be obtained. If the endpoint is absent then the
                  C2PA Manifest is available from same endpoint the query was
                  sent to using the /manifests endpoint.
              similarityScore:
                type: integer
                minimum: 0
                maximum: 100
                description: >-
                  An integer score in the range (0-100) representing the
                  strength of match, if appropriate, where 0 is the weakest
                  possible match and 100 is the strongest possible match.
            required:
              - manifestId
  securitySchemes:
    auth:
      type: oauth2
      flows:
        implicit:
          authorizationUrl: http://example.c2pa.org/oauth/dialog
          scopes:
            fetch:manifests: search and read manifests within the manifest store.

2. Federated Lookup

A mechanism is required to orchestrate search across multiple independent C2PA Manifest Repositories, as in some cases it may not be practical to discover or query a complete set of C2PA Manifest Repositories.

The Decentralized Soft Binding Resolution process enables query across multiple C2PA Manifest Repositories.

2.1. Overview of the Decentralized Soft Binding Resolution Process

Distributed Ledger Technology (DLT) is used to create a decentralized Key-Value (K-V) store. The key is the soft binding value, such as may be incorporated in an asset via a watermark. The value is a URI of an endpoint implementing the soft binding resolution API. Optionally, the value may also contain the unique identifier of the C2PA Manifest.

2.1.1. Querying the K-V Store

The process to retrieve a C2PA Manifest from a C2PA Manifest Repository using these APIs is illustrated via the sequence diagram below and is as follows:

  1. The C2PA Manifest consumer first computes the soft binding from the asset, for example by detecting a watermark.

  2. The decentralized K-V store is queried using the soft binding to obtain the URI of a C2PA Manifest Repository endpoint implementing the soft binding resolution API.

  3. If the manifest identifier (ID) was not published within the K-V store, it may be obtained via the Soft Binding Resolution API /byBinding route.

  4. The active manifest (and optionally the entire C2PA Manifest Store) may be obtained via the Soft Binding Resolution API /manifests route.

  5. Validation and processing of the recovered C2PA Manifest continues in the usual way.

2.1.2. Publishing to the K-V Store

A claim generator publishing a manifest into a C2PA Manifest Repository may optionally publish a Key-Value pair, comprising the soft binding and endpoint of the C2PA Manifest Repository, in order to make content searchable via the decentralized process

2.1.3. Accessing the Decentralized Key-Value Store

If the location of the Decentralized Key-Value Store is not known, then it may be obtained via the C2PA Soft Binding Algorithm List (SBAL). The SBAL contains an optional field softBindingResolutionApis that may contain the address of one or more Smart Contracts that reference the Key-Value store.

2.2. Schema for Decentralized Key-Value Store

There are two main approaches taken by implementers to create a Key-Value store on a DLT. The store may be contained either a) as state within a Smart Contract, or b) written out by a Smart Contract as state within the Event Log of the DLT. Moreover, the methods of representing information with the Key-Value store may differ across implementations.

In order to capture both implementation approaches a) and b), the Smart Contract referenced by the SBAL must implement a method returning JSON data that describes the format and access detail for the Key-Value store.

The JSON description must follow the schema below:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "array",
  "minItems": 1,
  "items": {
    "type": "object",
    "properties": {
      "resolutionMethod": {
        "type": "string",
        "enum": [
          "smartContract",
          "eventLog"
        ],
        "description": "Category of DLT method for resolving soft bindings."
      },
      "querySmartContract": {
        "type": "object",
        "properties": {
          "smartContractAddress": {
            "type": "string",
            "description": "Address of the smart contract to call upon."
          },
          "byBindingFunctionName": {
            "type": "string",
            "description": "Name of the smart contract function providing lookup by binding, which accepts and returns a JSON string."
          },
          "byBindingInputSchema": {
            "type": "object",
            "description": "A JSON schema describing how to format the soft binding value input to the byBindingFunctionName input string parameter.",
            "properties": {
              "softBindingValue": {
                "type": "string",
                "description": "A base64-encoded string describing, in algorithm specific format, the value of the soft binding to be used as the query."
              }
            },
            "required": ["softBindingValue"],
            "additionalProperties": false
          },
          "byBindingOutputSchema": {
            "type": "object",
            "description": "A JSON schema describing how to parse the endpoint and manifest ID (optional) from byBindingFunctionName output string.",
            "properties": {
              "endpoints": {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uri"
                },
                "description": "The URL(s) of the Softbinding Resolution API that may resolve this manifest ID."
              },
              "manifestId": {
                "type": "string",
                "description": "The optional unique identifier of the C2PA manifest, used to retrieve specific metadata. This may be absent if the manifest ID is not published within the K-V store."
              }
            },
            "required": ["endpoints"],
            "additionalProperties": false
          }
        },
        "required": [
          "smartContractAddress",
          "byBindingFunctionName",
          "byBindingInputSchema",
          "byBindingOutputSchema"
        ]
      },
      "queryEventLog": {
        "type": "object",
        "properties": {
          "smartContractAddress": {
            "type": "string",
            "description": "Address of the smart contract function to filter events by."
          },
          "keyTopic": {
            "type": "string",
            "description": "Topic used as key to lookup soft binding identifier."
          },
          "byBindingOutputSchema": {
            "type": "object",
            "description": "A JSON schema describing how to parse the endpoint and manifest ID (optional) from an event log message.",
            "properties": {
              "endpoints": {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uri"
                },
                "description": "The URL(s) of the Softbinding Resolution API that may resolve this manifest ID."
              },
              "manifestId": {
                "type": "string",
                "description": "The optional unique identifier of the C2PA manifest, used to retrieve specific metadata. This may be absent if the manifest ID is not published within the K-V store."
              }
            },
            "required": ["endpoints"],
            "additionalProperties": false
          }
        },
        "required": [
          "smartContractAddress",
          "keyTopic",
          "byBindingOutputSchema"
        ]
      }
    },
    "oneOf": [
      {
        "required": [
          "querySmartContract"
        ]
      },
      {
        "required": [
          "queryEventLog"
        ]
      }
    ]
  }
}

The schema describes an array containing one or more methods of decentralized resolution, which contain two fields. First, a field resolutionMethod that indicates whether the method stores the K-V store within a smart contract (smartContract) or within an event log (eventLog). Second, a field named either querySmartContract or queryEventLog respectively, that contains the detail on the resolution method.

2.2.1. Smart Contract K-V Stores

In the case of querySmartContract, the JSON object contains four required sub-fields.

smartContractAddress: a hex address (0x…​) which specifies the address of the smart contract (which may be different to the smart contract containing the describe method) byBindingFunctionName: the name of the function on that Smart Contract that may be called to query the K-V store using a soft binding. The function must accept and return a single JSON string. byBindingInputSchema: the schema of the input JSON string, indicating how the soft binding is to be encoded. byBindingOutputSchema: the schema of the output JSON string, indicating how the endpoint (and optionally, the C2PA Manifest ID) are represented in the value returned by the query.

The byBindingInputSchema object defines how the soft binding value is structured in the input to the smart contract function. It describes an object with one required field, softBindingValue, which is expected to be a base64-encoded string representing the soft binding identifier (e.g., a watermark ID). This identifier is passed in an algorithm-specific format.

The byBindingOutputSchema object defines the structure of the response returned by the smart contract function. It includes two fields.

endpoints: An array of URIs representing the Soft Binding Resolution APIs that may be used to resolve the manifest ID. manifestId: The unique identifier of the C2PA manifest, if available. This field is not required, as it may not be present in all cases.

Example JSON for a Smart Contract K-V Store:

[
  {
    "resolutionMethod": "smartContract",
    "querySmartContract": {
      "smartContractAddress": "0xABC123DEF4567890ABCDEF1234567890ABCDEF12",
      "byBindingFunctionName": "getManifestByBinding",
      "byBindingInputSchema": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "softBindingValue": {
            "type": "string",
            "description": "A base64-encoded string describing, in algorithm specific format, the value of the soft binding to be used as the query."
          }
        },
        "required": ["softBindingValue"],
        "additionalProperties": false
      },
      "byBindingOutputSchema": {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "endpoints": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            },
            "description": "The URL(s) of the Softbinding Resolution API that may resolve this manifest ID."
          },
          "manifestId": {
            "type": "string",
            "description": "The optional unique identifier of the C2PA manifest, used to retrieve specific metadata. This may be absent if the manifest ID is not published within the K-V store."
          }
        },
        "required": ["endpoints"],
        "additionalProperties": false
      }
    }
  }
]

2.2.2. Event Log K-V Stores

In the case of queryEventLog, the JSON object contains three required sub-fields:

smartContractAddress: a hex address (0x…​) which specifies the address of the smart contract writing the event log entries, and thus the means to identify those log entries. keyTopic: The topic used to filter event logs for the soft binding key. byBindingOutputSchema: JSON schema describing how to parse the endpoint and manifest ID from an event log message. The format is identical to the identically named field described for the Smart Contract K-V Store case.

Example JSON for an Event Log K-V Store:

{
  "resolutionMethod": "eventLog",
  "queryEventLog": {
    "smartContractAddress": "0xDEF4567890ABCDEF1234567890ABCDEF12345678",
    "keyTopic": "topic1",
    "byBindingOutputSchema": {
      "$schema": "https://json-schema.org/draft/2020-12/schema",
      "type": "object",
      "properties": {
        "endpoints": {
          "type": "array",
          "items": {
            "type": "string",
            "format": "uri"
          },
          "description": "The URL(s) of the Softbinding Resolution API that may resolve this manifest ID."
        },
        "manifestId": {
          "type": "string",
          "description": "The optional unique identifier of the C2PA manifest, used to retrieve specific metadata. This may be absent if the manifest ID is not published within the K-V store."
        }
      },
      "required": ["endpoints"],
      "additionalProperties": false
    }
  }
}

2.2.3. Accessing the JSON Schema

For EVM compatible chains, the Smart Contract referenced by the SBAL must implement a function describe as specified below, that returns the aforementioned JSON schema.

/// @title C2PA Decentralized Manifest Resolution
interface C2PASoftBindingResolution  {
    /// @dev This returns a JSON schema describing how manifests may be
    ///  recovered using a soft binding identifier using either or both of a
    ///  smart contract call or the event log.
    function describe() external view returns (string _name);
    ....

Further definitions for Smart Contracts on non-EVM compatible DLTs may follow in future versions of this document.