@windingtree/wt-write-api
Version:
API to write data to the Winding Tree platform
357 lines • 108 kB
YAML
openapi: 3.0.0
servers:
-
description: 'Demo deployment'
url: 'https://demo-write-api.windingtree.com'
-
description: Localhost
url: 'http://localhost:8000'
info:
description: 'API for creating and updating inventory in Winding Tree platform'
version: will-be-set-at-runtime
title: 'WT Write API'
paths:
/:
get:
summary: 'API info'
responses: {'200': {description: 'Basic information about this API instance.', content: {application/json: {schema: {type: object, required: [docs, info, version, config, wtDirectoryAddress, wtFactoryAddress, ethNetwork, dataFormatVersions], properties: {docs: {type: string, description: 'Link to the API documentation.'}, info: {type: string, description: 'Link to more information about the API.'}, version: {type: string, description: 'Deployed API version number.'}, config: {type: string, description: 'Which config is the API using. It might be useful to name configs after used ETH networks.'}, wtDirectoryAddress: {type: string, description: 'Ethereum address of used Winding Tree Directory.'}, wtFactoryAddress: {type: string, description: 'Ethereum address of used Winding Tree Factory.'}, ethNetwork: {type: string, description: 'Name of the ethereum network against which this instance runs.'}, dataFormatVersions: {description: 'Version number indicating the data format specification version.', type: object, properties: {hotels: {type: string}}}}}}}}}
/accounts:
post:
summary: 'Create account'
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/Account'}}}}
responses: {'200': {description: 'ID and access key for the created account.', content: {application/json: {schema: {type: object, properties: {accountId: {type: string, description: 'ID of the created account.'}, accessKey: {type: string, description: 'Access key to be used for authentication when communicating with the API.'}}}}}}, '400': {$ref: '#/components/responses/BadRequestError'}, '422': {$ref: '#/components/responses/UnprocessableEntityError'}}
'/accounts/{accountId}':
parameters:
- {name: accountId, required: true, in: path, description: 'Account ID as returned by POST /accounts', schema: {type: string}}
put:
summary: 'Update account'
security: [{AccessKey: []}]
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/Account'}}}}
responses: {'204': {description: 'Account was successfully updated.'}, '400': {$ref: '#/components/responses/BadRequestError'}, '401': {$ref: '#/components/responses/UnauthorizedError'}, '403': {$ref: '#/components/responses/ForbiddenError'}, '422': {$ref: '#/components/responses/UnprocessableEntityError'}}
delete:
summary: 'Delete account'
security: [{AccessKey: []}]
responses: {'204': {description: 'Account was successfully deleted.'}, '400': {$ref: '#/components/responses/BadRequestError'}, '401': {$ref: '#/components/responses/UnauthorizedError'}, '403': {$ref: '#/components/responses/ForbiddenError'}, '422': {$ref: '#/components/responses/UnprocessableEntityError'}}
/hotels:
post:
summary: 'Create hotel in WT.'
security: [{AccessKey: [], WalletPassword: []}]
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/Organization'}}}}
responses: {'201': {description: 'Ethereum address of the created hotel.', content: {application/json: {schema: {type: object, properties: {address: {type: string, description: 'Address of the created hotel'}}}}}}, '400': {$ref: '#/components/responses/BadRequestError'}, '401': {$ref: '#/components/responses/UnauthorizedError'}, '403': {$ref: '#/components/responses/ForbiddenError'}, '409': {$ref: '#/components/responses/ConflictError'}, '422': {$ref: '#/components/responses/UnprocessableEntityError'}, '502': {$ref: '#/components/responses/BadGatewayError'}}
'/hotels/{hotelAddress}':
parameters:
- {name: hotelAddress, required: true, in: path, description: 'Hotel address as returned by POST /hotels', schema: {type: string}}
get:
summary: 'Get hotel (provided for convenience to make updates easier) from WT.'
responses: {'200': {description: 'Ethereum address of the created hotel.', content: {application/json: {schema: {$ref: '#/components/schemas/Organization'}}}}, '400': {$ref: '#/components/responses/BadRequestError'}, '401': {$ref: '#/components/responses/UnauthorizedError'}, '403': {$ref: '#/components/responses/ForbiddenError'}, '404': {$ref: '#/components/responses/NotFoundError'}, '422': {$ref: '#/components/responses/UnprocessableEntityError'}, '502': {$ref: '#/components/responses/BadGatewayError'}}
delete:
summary: 'Remove hotel from WT.'
security: [{AccessKey: [], WalletPassword: []}]
parameters: [{name: offChain, required: false, in: query, description: 'If true, off-chain data will be deleted as well (if possible). Default is false.', schema: {type: string, enum: ['true', 'false']}}]
responses: {'204': {description: 'Hotel was successfully deleted.'}, '400': {$ref: '#/components/responses/BadRequestError'}, '401': {$ref: '#/components/responses/UnauthorizedError'}, '403': {$ref: '#/components/responses/ForbiddenError'}, '404': {$ref: '#/components/responses/NotFoundError'}, '422': {$ref: '#/components/responses/UnprocessableEntityError'}, '502': {$ref: '#/components/responses/BadGatewayError'}}
put:
summary: 'Update hotel even if original off-chain data is inaccessible. Replaces all of the data. Can''t use partial update.'
security: [{AccessKey: [], WalletPassword: []}]
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/Organization'}}}}
responses: {'204': {description: 'Hotel was successfully updated.'}, '400': {$ref: '#/components/responses/BadRequestError'}, '401': {$ref: '#/components/responses/UnauthorizedError'}, '403': {$ref: '#/components/responses/ForbiddenError'}, '404': {$ref: '#/components/responses/NotFoundError'}, '422': {$ref: '#/components/responses/UnprocessableEntityError'}, '502': {$ref: '#/components/responses/BadGatewayError'}}
patch:
summary: 'Update hotel only when original off-chain data can be accessed. It is possible to send one of `hotel` or `legalEntity` for partial update.'
security: [{AccessKey: [], WalletPassword: []}]
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/OrganizationPatch'}}}}
responses: {'204': {description: 'Hotel was successfully updated.'}, '400': {$ref: '#/components/responses/BadRequestError'}, '401': {$ref: '#/components/responses/UnauthorizedError'}, '403': {$ref: '#/components/responses/ForbiddenError'}, '404': {$ref: '#/components/responses/NotFoundError'}, '422': {$ref: '#/components/responses/UnprocessableEntityError'}, '502': {$ref: '#/components/responses/BadGatewayError'}}
'/hotels/{hotelAddress}/transfer':
parameters:
- {name: hotelAddress, required: true, in: path, description: 'Hotel address as returned by POST /hotels', schema: {type: string}}
post:
summary: 'Transfer hotel to a different manager.'
security: [{AccessKey: [], WalletPassword: []}]
requestBody: {required: true, content: {application/json: {schema: {type: object, required: [to], properties: {to: {type: string, description: 'Ethereum address of the new manager.'}}}}}}
responses: {'204': {description: 'Hotel was successfully transferred.'}, '400': {$ref: '#/components/responses/BadRequestError'}, '401': {$ref: '#/components/responses/UnauthorizedError'}, '403': {$ref: '#/components/responses/ForbiddenError'}, '404': {$ref: '#/components/responses/NotFoundError'}, '422': {$ref: '#/components/responses/UnprocessableEntityError'}, '502': {$ref: '#/components/responses/BadGatewayError'}}
components:
securitySchemes:
AccessKey:
type: apiKey
in: header
name: X-Access-Key
WalletPassword:
type: apiKey
in: header
name: X-Wallet-Password
responses:
BadRequestError:
description: 'The server does not understand the request (HTTP code 400)'
content: {application/json: {schema: {$ref: '#/components/schemas/Error'}}}
NotFoundError:
description: 'The object was not found (HTTP code 404)'
content: {application/json: {schema: {$ref: '#/components/schemas/Error'}}}
UnauthorizedError:
description: 'Authentication is requested for manipulation of the given resource. (Authentication can be achieved by means of two request headers - `X-Access-Key` and `X-Wallet-Password`.)'
content: {application/json: {schema: {$ref: '#/components/schemas/Error'}}}
ForbiddenError:
description: 'The existing authorization does not give the user permissions for the requested operation.'
content: {application/json: {schema: {$ref: '#/components/schemas/Error'}}}
ConflictError:
description: 'Data cannot be uploaded, typically because of missing uploader configuration.'
content: {application/json: {schema: {$ref: '#/components/schemas/Error'}}}
UnprocessableEntityError:
description: 'Request body or params validation failed.'
content: {application/json: {schema: {$ref: '#/components/schemas/Error'}}}
BadGatewayError:
description: 'The request could not be completed due to upstream errors.'
content: {application/json: {schema: {$ref: '#/components/schemas/Error'}}}
schemas:
Wallet:
type: object
description: 'Web3 secret storage - see https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition.'
required: [address, crypto, id, version]
properties: {address: {type: string}, crypto: {type: object, required: [cipher, ciphertext, cipherparams, kdf, kdfparams, mac], properties: {cipher: {type: string}, ciphertext: {type: string}, cipherparams: {type: object}, kdf: {type: string}, kdfparams: {type: object}, mac: {type: string}}}, id: {type: string}, version: {type: integer}}
Swarm:
description: 'Ethereum Swarm uploader configuration'
type: object
required: [swarm]
properties: {swarm: {type: object, properties: {}}}
S3:
description: 'AWS S3 uploader configuration'
type: object
required: [s3]
properties: {s3: {type: object, required: [accessKeyId, secretAccessKey, region, bucket], properties: {accessKeyId: {type: string}, secretAccessKey: {type: string}, region: {type: string}, bucket: {type: string}, keyPrefix: {type: string}}}}
Uploader:
description: 'Uploader configuration for a single document type.'
oneOf: [{$ref: '#/components/schemas/S3'}, {$ref: '#/components/schemas/Swarm'}]
UploaderConfig:
type: object
description: 'Off-chain uploader configuration for the account.'
properties: {root: {$ref: '#/components/schemas/Uploader'}, description: {$ref: '#/components/schemas/Uploader'}, ratePlans: {$ref: '#/components/schemas/Uploader'}, availability: {$ref: '#/components/schemas/Uploader'}}
Account:
type: object
required: [wallet, uploaders]
properties: {wallet: {$ref: '#/components/schemas/Wallet'}, uploaders: {$ref: '#/components/schemas/UploaderConfig'}}
Organization:
oneOf: [{$ref: '#/components/schemas/OrganizationWithoutData'}, {allOf: [{$ref: '#/components/schemas/OrganizationWithData'}, {type: object, description: 'Organization data.', required: [description]}]}]
OrganizationPatch:
oneOf: [{$ref: '#/components/schemas/OrganizationWithoutData'}, {allOf: [{$ref: '#/components/schemas/OrganizationWithData'}, {type: object, description: 'Patch object to update existing organization data.'}]}]
OrganizationWithData:
type: object
required: [legalEntity, hotel]
properties: {legalEntity: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-LegalEntity'}, guarantee: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-Guarantee'}, hotel: {type: object, description: 'Hotel data.', required: [description], properties: {defaultLocale: {$ref: '#/components/schemas/windingtree-wt-shared-schemas-LanguageCodeType', description: 'Code of language in which all textual information for this record is presented. If no default locale is declared, the texts are expected to be in English language.'}, description: {$ref: '#/components/schemas/windingtree-wt-hotel-schemas-HotelDescription'}, ratePlans: {$ref: '#/components/schemas/windingtree-wt-hotel-schemas-RatePlans'}, availability: {$ref: '#/components/schemas/windingtree-wt-hotel-schemas-Availability'}, notifications: {description: 'URL of a notification service.', $ref: '#/components/schemas/windingtree-wt-shared-schemas-UriType'}, booking: {description: 'URL of a booking service.'}}}}
OrganizationWithoutData:
type: object
required: [orgJson, hash]
properties: {orgJson: {description: 'URL of the ORG.JSON.', $ref: '#/components/schemas/windingtree-wt-shared-schemas-UriType'}, hash: {description: 'kecak256 hash of the ORG.JSON contents with 0x prefix', type: string}}
Error:
title: Error
description: 'Default schema for errors returned by API.'
properties: {status: {type: number, description: 'HTTP status'}, code: {type: string, description: 'Computer-readable error. Use this for comparison.'}, short: {type: string, description: 'Human-readable error with a short description of the error.'}, long: {type: string, description: 'Verbose explanation of what happened.'}}
windingtree-wt-shared-schemas-Contact:
title: Contact
type: object
properties: {email: {description: 'E-mail contact', type: string, format: email, example: joseph.urban@example.com, maxLength: 150}, phone: {description: 'Phone number (with country prefix and a leading + sign)', type: string, maxLength: 18, example: '+44123456789', format: phone}, url: {description: 'Url to the contact web page', type: string, format: uri}, ethereum: {description: 'Address of wallet on Ethereum', $ref: '#/components/schemas/windingtree-wt-shared-schemas-EthereumAddressType'}, additionalContacts: {description: 'More contact options, such as Whatsapp, WeChat, Telegram, twitter handle, facebook address. Once we see high demand for a particular type of contact, we can promote them to regular contact types.', type: array, items: {type: object, required: [title, value], properties: {title: {description: 'Name of this contact options', type: string, maxLength: 100}, value: {description: 'The actual contact', type: string, maxLength: 100}}}}}
windingtree-wt-shared-schemas-CancellationPolicy:
title: 'Cancellation policy'
type: object
description: 'What is the penalty when a guest/passenger wants to cancel a reservation.'
required: [amount]
properties: {from: {description: 'After which date does this cancellation policy apply (including). If not present, this policy applies since the beginning of time. This is related to arrival and departure dates, not the date of the booking.', type: string, format: date, example: '2018-01-30'}, to: {description: 'Before which date does this cancellation policy apply(including). If not present, this policy applies until the end of the universe. This is related to arrival and departure dates, not the date of the booking.', type: string, format: date, example: '2018-02-20'}, deadline: {type: integer, description: 'How many days before hotel arrival or flight departure does this first apply. If not present, this policy applies any time.', example: 30}, amount: {type: number, format: float, description: 'Cost of cancellation in percents of the final price, 100 means non refundable. This means how much money will the hotel keep.', example: 25}}
windingtree-wt-shared-schemas-AddressType:
title: 'Postal address'
description: 'Based on output of Open Street Map''s [Nominatim](https://wiki.openstreetmap.org/wiki/Nominatim). For formatting, take a look [here](https://github.com/OpenCageData/address-formatting).'
type: object
required: [road, houseNumber, city, countryCode]
properties: {houseNumber: {type: string, maxLength: 150}, road: {type: string, maxLength: 150}, city: {type: string, maxLength: 150}, county: {type: string, maxLength: 150}, stateDistrict: {type: string, maxLength: 150}, state: {type: string, maxLength: 150}, postcode: {type: string, maxLength: 13}, countryCode: {type: string, maxLength: 2, minLength: 2, description: 'ISO 3166-1 alpha-2 codes', format: country-code}}
windingtree-wt-shared-schemas-LegalEntityType:
title: 'Legal entity'
type: object
description: 'A legal entity that can be held responsible'
required: [name, address, contact]
properties: {name: {description: 'Entity''s name as registered with the authorities', type: string, maxLength: 300}, address: {description: 'Entity''s postal address as registered with the authorities', $ref: '#/components/schemas/windingtree-wt-shared-schemas-AddressType'}, contact: {description: 'Any way of contacting the entity', $ref: '#/components/schemas/windingtree-wt-shared-schemas-Contact'}, vatin: {description: 'VAT identification number ([EU](https://en.wikipedia.org/wiki/VAT_identification_number), [US](https://www.irs.gov/individuals/international-taxpayers/taxpayer-identification-numbers-tin), or equivalents)', type: string, maxLength: 50}, lei: {description: 'Legal Entity Identifier as defined in ISO 17442, https://en.wikipedia.org/wiki/Legal_Entity_Identifier', type: string, length: 20}}
windingtree-wt-shared-schemas-CurrencyType:
title: 'Currency code'
type: string
minLength: 3
maxLength: 3
description: 'Three letter ISO 4217 currency code.'
format: currency-code
windingtree-wt-shared-schemas-DescriptionType:
title: 'Markdown description'
description: 'Text description in simple Markdown format (bold, italic, titles, line break and paragraph format). Particular flavour of markdown is yet to be decided.'
type: string
maxLength: 3000
windingtree-wt-shared-schemas-EthereumAddressType:
title: 'Ethereum address'
type: string
description: 'Ethereum address in hexadecimal format (with leading 0x) or an ENS name.'
maxLength: 300
windingtree-wt-shared-schemas-NameType:
title: 'Entity name'
description: 'Human readable name identifying an entity (shown to users in search results, hotel/room details, etc)'
type: string
maxLength: 150
windingtree-wt-shared-schemas-ObjectIdType:
title: ID
description: 'Vendor string ID'
type: string
maxLength: 100
example: 1234-abcd
windingtree-wt-shared-schemas-TimezoneType:
title: 'Timezone code'
description: 'Timezone name according to https://www.iana.org/time-zones (refer to zone.tab)'
type: string
maxLength: 40
format: timezone
windingtree-wt-shared-schemas-UriType:
title: URI
description: 'URI for linking resources. The maximal length is 1500 to save space.'
type: string
format: uri
maxLength: 1500
windingtree-wt-shared-schemas-LanguageCodeType:
title: 'Language code'
description: 'Two letter language code based on ISO 639-1 standard'
type: string
format: language-code
length: 2
windingtree-wt-shared-schemas-RelationshipSignatureType:
description: "Organization A (`subject`) publishes this object to tell the world that an Organization B (`guarantor`)\nagreed to be in an asymmetric relationship with the `subject`. Nature of such relationship can change\nto fit any particular use case.\nThe flow should be like this:\n 1. `subject` asks `guarantor` to establish a certain kind of relationship.\n 2. `guarantor` does its due dilligence of the `subject`.\n 3. `guarantor` creates `claim` and signs it. Typically, a `guarantor` address will be of a smart contract,\n which cannot sign data. So a `guarantor` would sign the data with a private key associated with one of\n the `associatedKeys` of the `guarantor`'s Organization smart contract. That is the `signature`.\n 6. `guarantor` sends the `claim` and the `signature` back to the `subject`.\n 7. `subject` publishes the `claim` and `signature` in its data.\n"
type: object
properties: {claim: {description: "A message that is signed by `guarantor`. This cannot be a JSON object due to its serialization rules\nambiguity. Instead, this is a hex encoded representation of a `RelationshipClaimType`\nserialized by the signing party to prevent inconsistencies.\n", type: string}, signature: {description: "Signature of a serialized `claim` signed by a private key associated (either directly or via a `associatedKeys`\nrelationship) with the `claim.guarantor` ETH address. The signature has to conform to the\n[eth_sign](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign) method.\n", type: string}}
windingtree-wt-shared-schemas-RelationshipClaimType:
description: 'A message used to prove an asymmetric relationship between two subjects. It has a limited validity in time.'
type: object
required: [subject, guarantor, expiresAt]
properties: {subject: {description: 'Subjects''s ethereum address', $ref: '#/components/schemas/windingtree-wt-shared-schemas-EthereumAddressType'}, guarantor: {description: 'Guarantor''s ethereum address', $ref: '#/components/schemas/windingtree-wt-shared-schemas-EthereumAddressType'}, expiresAt: {description: 'When the relationship will expire. UNIX timestamp in seconds.', type: string, format: timestamp}}
windingtree-wt-organization-schemas-OrganizationDataIndex:
title: ORG.JSON
description: 'Landing file for each ORG.ID. Link to this document is stored in the 0xORG smart contract.'
type: object
required: [dataFormatVersion, legalEntity, updatedAt]
properties: {dataFormatVersion: {description: 'Version number indicating the data format specification version.', type: string, format: semver, maxLength: 20}, name: {allOf: [{$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-NameType'}, {description: 'Human readable name of the Organization that can be used for quick identification.'}]}, legalEntity: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-LegalEntity'}, updatedAt: {description: 'Date-time when the data was last changed. Possibly used by consumers to handle incremental updates and caching.', type: string, format: date-time}, guarantee: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-Guarantee'}, hotel: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-Hotel'}, airline: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-Airline'}}
windingtree-wt-organization-schemas-LegalEntity:
allOf: [{oneOf: [{$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-LegalEntityType'}, {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-RelationshipSignatureType'}]}, {description: "Legal information about this organization. Either stored directly or as a signed\nrelationship reference to another Organization smart contract. Users must verify that the \nrelationship signature is valid (it did not expire and the signature was produced by someone\nassociated with the organization).\n"}]
windingtree-wt-organization-schemas-Guarantee:
allOf: [{$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-RelationshipSignatureType'}, {description: "*Some other Organization* is guaranteeing that **this Organization** can be trusted. That means\nthat when a user is evaluating trustworthiness of **this Organization**, she should take into\naccount the trustworthiness of *Some other Organization*.\n"}]
windingtree-wt-organization-schemas-Hotel:
allOf: [{$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-HotelDescriptionMinimal'}, {type: object, properties: {apis: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-ApiReferences'}}}]
windingtree-wt-organization-schemas-Airline:
allOf: [{$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-airline-schemas-AirlineDescriptionMinimal'}, {type: object, properties: {apis: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-ApiReferences'}}}]
windingtree-wt-organization-schemas-ApiReferences:
description: 'A list of API services that this organization provides.'
type: array
items: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-ApiReference'}
windingtree-wt-organization-schemas-ApiReference:
title: 'External API reference'
type: object
required: [entrypoint, docs, format, version, segment]
properties: {entrypoint: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-UriType'}, docs: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-UriType'}, format: {description: 'API format, such as `Winding Tree`, `OTA`, `HTNG` or something else. This should be case insensitive.', type: string}, version: {description: 'A version of the API. Can be in `semver` format but other formats are possible.', type: string}}
windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-Contact:
title: Contact
type: object
properties: {email: {description: 'E-mail contact', type: string, format: email, example: joseph.urban@example.com, maxLength: 150}, phone: {description: 'Phone number (with country prefix and a leading + sign)', type: string, maxLength: 18, example: '+44123456789', format: phone}, url: {description: 'Url to the contact web page', type: string, format: uri}, ethereum: {description: 'Address of wallet on Ethereum', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-EthereumAddressType'}, additionalContacts: {description: 'More contact options, such as Whatsapp, WeChat, Telegram, twitter handle, facebook address. Once we see high demand for a particular type of contact, we can promote them to regular contact types.', type: array, items: {type: object, required: [title, value], properties: {title: {description: 'Name of this contact options', type: string, maxLength: 100}, value: {description: 'The actual contact', type: string, maxLength: 100}}}}}
windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-CancellationPolicy:
title: 'Cancellation policy'
type: object
description: 'What is the penalty when a guest/passenger wants to cancel a reservation.'
required: [amount]
properties: {from: {description: 'After which date does this cancellation policy apply (including). If not present, this policy applies since the beginning of time. This is related to arrival and departure dates, not the date of the booking.', type: string, format: date, example: '2018-01-30'}, to: {description: 'Before which date does this cancellation policy apply(including). If not present, this policy applies until the end of the universe. This is related to arrival and departure dates, not the date of the booking.', type: string, format: date, example: '2018-02-20'}, deadline: {type: integer, description: 'How many days before hotel arrival or flight departure does this first apply. If not present, this policy applies any time.', example: 30}, amount: {type: number, format: float, description: 'Cost of cancellation in percents of the final price, 100 means non refundable. This means how much money will the hotel keep.', example: 25}}
windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-AddressType:
title: 'Postal address'
description: 'Based on output of Open Street Map''s [Nominatim](https://wiki.openstreetmap.org/wiki/Nominatim). For formatting, take a look [here](https://github.com/OpenCageData/address-formatting).'
type: object
required: [road, houseNumber, city, countryCode]
properties: {houseNumber: {type: string, maxLength: 150}, road: {type: string, maxLength: 150}, city: {type: string, maxLength: 150}, county: {type: string, maxLength: 150}, stateDistrict: {type: string, maxLength: 150}, state: {type: string, maxLength: 150}, postcode: {type: string, maxLength: 13}, countryCode: {type: string, maxLength: 2, minLength: 2, description: 'ISO 3166-1 alpha-2 codes', format: country-code}}
windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-LegalEntityType:
title: 'Legal entity'
type: object
description: 'A legal entity that can be held responsible'
required: [name, address, contact]
properties: {name: {description: 'Entity''s name as registered with the authorities', type: string, maxLength: 300}, address: {description: 'Entity''s postal address as registered with the authorities', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-AddressType'}, contact: {description: 'Any way of contacting the entity', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-Contact'}, vatin: {description: 'VAT identification number ([EU](https://en.wikipedia.org/wiki/VAT_identification_number), [US](https://www.irs.gov/individuals/international-taxpayers/taxpayer-identification-numbers-tin), or equivalents)', type: string, maxLength: 50}, lei: {description: 'Legal Entity Identifier as defined in ISO 17442, https://en.wikipedia.org/wiki/Legal_Entity_Identifier', type: string, length: 20}}
windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-CurrencyType:
title: 'Currency code'
type: string
minLength: 3
maxLength: 3
description: 'Three letter ISO 4217 currency code.'
format: currency-code
windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-DescriptionType:
title: 'Markdown description'
description: 'Text description in simple Markdown format (bold, italic, titles, line break and paragraph format). Particular flavour of markdown is yet to be decided.'
type: string
maxLength: 3000
windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-EthereumAddressType:
title: 'Ethereum address'
type: string
description: 'Ethereum address in hexadecimal format (with leading 0x) or an ENS name.'
maxLength: 300
windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-NameType:
title: 'Entity name'
description: 'Human readable name identifying an entity (shown to users in search results, hotel/room details, etc)'
type: string
maxLength: 150
windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-ObjectIdType:
title: ID
description: 'Vendor string ID'
type: string
maxLength: 100
example: 1234-abcd
windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-TimezoneType:
title: 'Timezone code'
description: 'Timezone name according to https://www.iana.org/time-zones (refer to zone.tab)'
type: string
maxLength: 40
format: timezone
windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-UriType:
title: URI
description: 'URI for linking resources. The maximal length is 1500 to save space.'
type: string
format: uri
maxLength: 1500
windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-LanguageCodeType:
title: 'Language code'
description: 'Two letter language code based on ISO 639-1 standard'
type: string
format: language-code
length: 2
windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-RelationshipSignatureType:
description: "Organization A (`subject`) publishes this object to tell the world that an Organization B (`guarantor`)\nagreed to be in an asymmetric relationship with the `subject`. Nature of such relationship can change\nto fit any particular use case.\nThe flow should be like this:\n 1. `subject` asks `guarantor` to establish a certain kind of relationship.\n 2. `guarantor` does its due dilligence of the `subject`.\n 3. `guarantor` creates `claim` and signs it. Typically, a `guarantor` address will be of a smart contract,\n which cannot sign data. So a `guarantor` would sign the data with a private key associated with one of\n the `associatedKeys` of the `guarantor`'s Organization smart contract. That is the `signature`.\n 6. `guarantor` sends the `claim` and the `signature` back to the `subject`.\n 7. `subject` publishes the `claim` and `signature` in its data.\n"
type: object
properties: {claim: {description: "A message that is signed by `guarantor`. This cannot be a JSON object due to its serialization rules\nambiguity. Instead, this is a hex encoded representation of a `RelationshipClaimType`\nserialized by the signing party to prevent inconsistencies.\n", type: string}, signature: {description: "Signature of a serialized `claim` signed by a private key associated (either directly or via a `associatedKeys`\nrelationship) with the `claim.guarantor` ETH address. The signature has to conform to the\n[eth_sign](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign) method.\n", type: string}}
windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-RelationshipClaimType:
description: 'A message used to prove an asymmetric relationship between two subjects. It has a limited validity in time.'
type: object
required: [subject, guarantor, expiresAt]
properties: {subject: {description: 'Subjects''s ethereum address', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-EthereumAddressType'}, guarantor: {description: 'Guarantor''s ethereum address', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-shared-schemas-EthereumAddressType'}, expiresAt: {description: 'When the relationship will expire. UNIX timestamp in seconds.', type: string, format: timestamp}}
windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-HotelDataIndex:
title: 'Hotel data index'
description: 'Landing index for hotel resources. Link to this document is stored in WT-Index smart contract hotel record'
type: object
required: [dataFormatVersion, descriptionUri]
properties: {dataFormatVersion: {description: 'Version number indicating the data format specification version.', type: string, format: semver, maxLength: 20}, descriptionUri: {description: 'URI pointing to the HotelDescription data resource', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-UriType'}, ratePlansUri: {description: 'URI pointing to RatePlans data resource', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-UriType'}, availabilityUri: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-UriType', description: 'URI pointing to Availability data resource'}, notificationsUri: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-UriType', description: 'URI pointing to an instance of the WT Notification service.'}, bookingUri: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-UriType', description: 'URI pointing to an instance of the WT Booking service.'}, defaultLocale: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-LanguageCodeType', description: 'Code of language in which all textual information for this record is presented. If no default locale is declared, the texts are expected to be in English language.'}, guarantee: {allOf: [{$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-RelationshipSignatureType'}, {description: "Object used to prove that a hotel is legitimate. A trust level is evaluated for hotel's guarantor\n"}]}}
windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-HotelDescription:
title: 'Hotel description'
allOf: [{$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-HotelDescriptionBase'}, {type: object, required: [name, description, contacts, address, timezone, currency, defaultCancellationAmount]}]
windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-HotelDescriptionMinimal:
title: 'Minimal hotel description definition with a required subset'
allOf: [{$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-HotelDescriptionMinimalBase'}, {type: object, required: [name, location, website]}]
windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-HotelDescriptionMinimalBase:
title: 'Minimal hotel description definition'
description: 'Basic properties of a hotel'
type: object
properties: {location: {description: 'Geo-location in GPS format', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-Location'}, name: {description: 'Name of the hotel to display to users', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-NameType'}, website: {description: 'URL of a hotel website', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-UriType'}, description: {description: 'Short text description of the hotel to show to users.', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-DescriptionType'}, contacts: {type: object, description: 'A set of contacts', required: [general], properties: {general: {description: 'Primary contact', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-Contact'}}}, address: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-AddressType'}}
windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-HotelDescriptionBase:
allOf: [{$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-HotelDescriptionMinimalBase'}, {type: object, title: 'Hotel description definition', description: 'All properties of a hotel', properties: {roomTypes: {description: 'Room types in the hotel', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-RoomTypes'}, operator: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-LegalEntityType'}, timezone: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-TimezoneType'}, currency: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-CurrencyType'}, spokenLanguages: {description: 'List of languages that people can use when communicating with this hotel.', type: array, items: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-LanguageCodeType'}}, category: {description: 'Hotel category for easier filtering. These values are placeholder strings that are coincidentally in English and should be localized by the end user interface.', type: string, enum: [apartment, 'bed and breakfast', boat, cabin, camp, 'holiday home', hostel, hotel, house, inn, 'mobile home', motel, other, spa]}, images: {description: 'Images. We don''t process them in any way, so they should be in the best quality available and in a common format such as JPEG. As we don''t have any tagging, the most important picture should come first.', type: array, items: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-UriType'}}, amenities: {description: 'Hotel products/services provided to guests. If a service is stated here, it is provided.', type: array, items: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-HotelAmenityItem'}}, tags: {description: 'Free form textual tags that can describe the hotel. These can be eventually used for searching.', type: array, items: {type: string}}, updatedAt: {type: string, description: 'Date-time when the data was last changed. Used by consumers to handle incremental updates and caching.', format: date-time}, defaultCancellationAmount: {type: number, format: float, description: 'Cost of cancellation in percents of the final price, 100 means non refundable. This is a default amount of how much money will the hotel keep if no other cancallation policy is applicable.', example: 25}, cancellationPolicies: {description: 'A list of policies under which it is possible to cancel a reservation.', type: array, items: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-CancellationPolicy'}}}}]
windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-RoomTypes:
type: array
description: 'Array of RoomTypes'
items: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-RoomType'}
windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-RoomType:
type: object
required: [id, name, description, occupancy, totalQuantity]
properties: {id: {description: 'ID of the room type', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-ObjectIdType', example: 123-afg-34}, name: {description: 'Name of the room type to show to users', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-NameType'}, description: {description: 'Room type description in plain text', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-DescriptionType'}, category: {type: string, description: 'Room category for easier filtering. These values are placeholder strings that are coincidentally in English and should be localized by the end user interface.', enum: [apartment, barn, boat, bungalow, bunk, cabin, condominium, 'double or twin room', 'double room', 'double room single use', duplex, lodge, other, penthouse, 'quadruple room', 'recreation vehicle', room, 'shared room', 'single room', studio, suite, teepee, tent, 'tree house', 'triple room', 'twin room', villa, yurt]}, totalQuantity: {type: integer, format: int32}, occupancy: {type: object, required: [max], properties: {min: {type: integer, format: int32, description: 'Minimal number of occupants to rent the room.', default: 1, example: 1}, max: {type: integer, format: int32, description: 'Maximal number of occupants to rent the room.', example: 3}}}, amenities: {description: 'Room products/services provided to guests. If a service is stated here, it is provided.', type: array, items: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-RoomAmenityItem'}}, tags: {description: 'Free form textual tags that can describe the room. These can be eventually used for searching.', type: array, items: {type: string}}, images: {description: 'Images. We don''t process them in any way, so they should be in the best quality available and in a common format such as JPEG. As we don''t have any tagging, the most important picture should come first.', type: array, minItems: 0, maxItems: 30, uniqueItems: true, items: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-UriType', description: 'image uri', example: 'https://example.com/my-image.jpg'}}, updatedAt: {type: string, format: date-time, description: 'Date-time when the data was last changed. Used by consumers to handle incremental updates and caching.'}}
windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-RatePlans:
type: array
description: 'Array of RatePlans'
items: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-RatePlan'}
windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-RatePlan:
description: "Rate plan for specified room types. All prices are meant for a single room for a single night for a single person.\nWe recommend using [wt-pricing-algorithms](https://github.com/windingtree/wt-pricing-algorithms) library for this.\n\nAlgorithm to calculate price\n- choose the currency you want to compute the price in\n- pick the right ratePlan(s) based on the chosen currency, availableForTravel field and provided booking dates\n- check restrictions and drop rate plans that the booking doesn't meet\n- for every rate plan as rp_i\n - for every person as p_j\n apply the best of any fitting price modifiers (pro-consumer strategy, this will change)\n multiply the computed rate by length of stay\n - store the final price for rp_i\n- compare all final prices and pick the one based on the chosen resolution strategy\n"
type: object
required: [id, name, price, roomTypeIds]
properties: {id: {description: 'ID of the rate plan', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-ObjectIdType'}, name: {description: 'Name of the rate plan to show to users', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-NameType'}, description: {description: 'Rate plan description in plain text', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-DescriptionType'}, currency: {description: 'Currency in which are all the prices of this rate plan. If not set, the hotel currency setting will be used.', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-CurrencyType'}, price: {type: number, format: float, description: 'Base price for given room type for one night and one person.'}, roomTypeIds: {type: array, description: 'List of all room types that this rate plan applies to', minItems: 1, maxItems: 30, uniqueItems: true, items: {description: 'RoomType id', $ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-ObjectIdType', example: 123-afg-34}}, updatedAt: {type: string, format: date-time, description: 'Date-time when the data was last changed. Used by consumers to handle incremental updates and caching.'}, availableForReservation: {type: object, description: 'A time period during which this rate plan can be used to compute prices for a booking, i. e. a hotel can have different rate plans that are used for reservations for the same date that are placed in different months. If this restriction is not set, the rate plan can be used for booking with no time restriction.', required: [from, to], properties: {from: {type: string, format: date}, to: {type: string, format: date}}}, availableForTravel: {type: object, description: 'A time period of stay during which this rate plan should be used to compute prices, i. e. prices in this rate plan are applicable in August. If this restriction is not set, the rate plan can be used for booking for any time.', required: [from, to], properties: {from: {type: string, format: date}, to: {type: string, format: date}}}, modifiers: {type: array, description: 'List of price modifiers, i. e. discounts based on length of stay. For now, the list is very limited.', items: {$ref: '#/components/schemas/windingtree-wt-organization-schemas-windingtree-wt-hotel-schemas-RatePlanPriceModifier'}}, restrictions: {type: object, description: 'Restrictions for this rate plan. If a booking fits all restrictions, this rate plan can be used. If no restrictions are set, rate plan can be applied at any valid time.', properties