AIP-153

Import and export

Many users want to be able to load data into an API, or get their existing data out of an API. This is particularly important for enterprise users, who are often concerned about vendor lock-in.

Guidance

APIs may support import and export operations, which may create multiple new resources, or they may populate data into a single resource.

Multiple resources

Services may support importing and exporting multiple resources into or out of an API, and should implement a common pattern to do so:

rpc ImportBooks(ImportBooksRequest) returns (google.longrunning.Operation) {
  option (google.api.http) = {
    post: "/v1/{parent=publishers/*}/books:import"
    body: "*"
  };
  option (google.longrunning.operation_info) = {
    response_type: "ImportBooksResponse"
    metadata_type: "ImportBooksMetadata"
  };
}

rpc ExportBooks(ExportBooksRequest) returns (google.longrunning.Operation) {
  option (google.api.http) = {
    post: "/v1/{parent=publishers/*}/books:export"
    body: "*"
  };
  option (google.longrunning.operation_info) = {
    response_type: "ExportBooksResponse"
    metadata_type: "ExportBooksMetadata"
  };
}
  • The method must return a long-running operation (see AIP-151) unless the service can guarantee that it will never need more than a few seconds to complete.
  • The HTTP verb must be POST, and the body must be "*".
  • A parent field should be included as part of the URI.
    • If importing into or exporting from multiple resources is required, the API should keep the parent field and allow the user to use the - character to indicate multiple parents (see AIP-159).
    • On import, if the user provides a specific parent, the API must reject any imported resources that would be added to a different parent.
  • The URI suffix should be :import or :export.

Data for a single resource

Services may support importing and exporting data into or out of a single resource, and should implement a common pattern to do so:

rpc ImportPages(ImportPagesRequest) returns (google.longrunning.Operation) {
  option (google.api.http) = {
    post: "/v1/{book=publishers/*/books/*}:importPages"
    body: "*"
  };
  option (google.longrunning.operation_info) = {
    response_type: "ImportPagesResponse"
    metadata_type: "ImportPagesMetadata"
  };
}

rpc ExportPages(ExportPagesRequest) returns (google.longrunning.Operation) {
  option (google.api.http) = {
    post: "/v1/{book=publishers/*/books/*}:exportPages"
    body: "*"
  };
  option (google.longrunning.operation_info) = {
    response_type: "ExportPagesResponse"
    metadata_type: "ExportPagesMetadata"
  };
}
  • The method must return a long-running operation (see AIP-151) unless the service can guarantee that it will never need more than a few seconds to complete.
  • The HTTP verb must be POST, and the body must be "*".
  • A field representing the resource that data is being imported into should be included as part of the URI. The field should be named after the resource (and should not be called name).
  • The URI suffix should include both the verb and a noun for the data itself, such as :importPages or :exportPages.

Request object

Imports and exports often require two fundamentally different types of configuration:

  1. Configuration specific to the source or destination.
  2. Configuration regarding the imported or exported data itself.

Source or destination configuration should be grouped into a single message and placed inside a oneof:

message ImportBooksRequest {
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "library.googleapis.com/Book"
    }];
  oneof source {
    AuthorSource author_source = 2;
    TranslatorSource translator_source = 3;
  }
  string isbn_prefix = 4;
}

message ExportBooksRequest {
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "library.googleapis.com/Book"
    }];
  oneof destination {
    PrinterDestination printer_destination = 2;
    TranslatorDestination translator_destination = 3;
  }
  string filter = 4;
}
  • The source configuration messages must be placed within a oneof source (for import) or oneof destination (for export), even if there is only one. (This maintains flexibility to add more later.)
  • Configuration related to the data itself (and therefore common across all sources) must be placed at the top-level of the request message.

Note: The configuration for import and export may be different from one another. (For example, it would be sensible to import from a file but export to a directory.)

Inline sources

APIs may also permit import and export "inline", where the contents to be imported or exported are provided in the request or response.

message InlineSource {
  repeated Book books = 1;
}
  • The source or destination should be named InlineSource or InlineDestination.
  • The message should include a repeated field representing the resource. However, if the resource structure is complex, the API may use a separate inline representation. In this situation, the same format must be used for both import and export.

Partial failures

While partial failures are normally discouraged, import and export RPCs should include partial failure information in the metadata object. Each individual error should be a google.rpc.Status object describing the error. For more on errors, see AIP-193.