/*
  This file is part of TALER
  Copyright (C) 2014-2025 Taler Systems SA

  TALER is free software; you can redistribute it and/or modify it under the
  terms of the GNU Affero General Public License as published by the Free Software
  Foundation; either version 3, or (at your option) any later version.

  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License along with
  TALER; see the file COPYING.LIB.  If not, see <http://www.gnu.org/licenses/>
*/
/**
 * @file taler_merchant_service.h
 * @brief C interface of libtalermerchant, a C library to use merchant's HTTP API
 *        This library is not thread-safe, all APIs must only be used from a single thread.
 *        This library calls abort() if it runs out of memory. Be aware of these limitations.
 * @author Christian Grothoff
 * @author Marcello Stanisci
 * @author Priscilla HUANG
 */
#ifndef _TALER_MERCHANT_SERVICE_H
#define _TALER_MERCHANT_SERVICE_H

#include <taler/taler_util.h>
#include <taler/taler_error_codes.h>
#include <taler/taler_exchange_service.h>
#include <gnunet/gnunet_curl_lib.h>
#include <jansson.h>

/**
 * Library version (in hex) for compatibility tests.
 */
#define TALER_MERCHANT_SERVICE_VERSION 0x00100001


/**
 * General information about the HTTP response we obtained
 * from the merchant for a request.
 */
struct TALER_MERCHANT_HttpResponse
{

  /**
   * The complete JSON reply. NULL if we failed to parse the
   * reply (too big, invalid JSON).
   */
  const json_t *reply;

  /**
   * The complete JSON reply from the exchange, if we generated an error in
   * response to an exchange error.  Usually set if @e http_status is
   * #MHD_HTTP_FAILED_DEPENDENCY or #MHD_HTTP_SERVICE_UNAVAILABLE. NULL if we
   * failed to obtain a JSON reply from the exchange or if we did not receive
   * an error from the exchange.
   */
  const json_t *exchange_reply;

  /**
   * Set to the human-readable 'hint' that is optionally
   * provided by the exchange together with errors. NULL
   * if no hint was provided or if there was no error.
   */
  const char *hint;

  /**
   * The error hint from the exchange, if we generated an error in
   * response to an exchange error.  Usually set if @e http_status is
   * #MHD_HTTP_FAILED_DEPENDENCY or #MHD_HTTP_SERVICE_UNAVAILABLE. NULL if we
   * failed to obtain a hint from the exchange or if we did not receive
   * an error from the exchange.
   */
  const char *exchange_hint;

  /**
   * HTTP status code for the response.  0 if the
   * HTTP request failed and we did not get any answer, or
   * if the answer was invalid and we set @a ec to a
   * client-side error code.
   */
  unsigned int http_status;

  /**
   * The HTTP status code from the exchange, if we generated an error in
   * response to an exchange error.  Usually set if @e http_status is
   * #MHD_HTTP_FAILED_DEPENDENCY or #MHD_HTTP_SERVICE_UNAVAILABLE. 0 if we
   * failed to obtain a JSON reply from the exchange or if we did not receive
   * an error from the exchange.
   */
  unsigned int exchange_http_status;

  /**
   * Taler error code.  #TALER_EC_NONE if everything was
   * OK.  Usually set to the "code" field of an error
   * response, but may be set to values created at the
   * client side, for example when the response was
   * not in JSON format or was otherwise ill-formed.
   */
  enum TALER_ErrorCode ec;

  /**
   * The error code from the reply from the exchange, if we generated an error in
   * response to an exchange error.  Usually set if @e http_status is
   * #MHD_HTTP_FAILED_DEPENDENCY or #MHD_HTTP_SERVICE_UNAVAILABLE. NULL if we
   * failed to obtain a error code from the exchange or if we did not receive
   * an error from the exchange.
   */
  enum TALER_ErrorCode exchange_code;

};


/**
 * Contains information gathered from parsing a taler://pay URI.
 */
struct TALER_MERCHANT_PayUriData
{
  /**
   * Hostname (and possibly port) of the merchant.
   */
  char *merchant_host;

  /**
   * Prefix to the base url of the merchant backend. May be NULL.
   */
  char *merchant_prefix_path;

  /**
   * The id of the order to pay.
   */
  char *order_id;

  /**
   * Session id to use when paying the order. May be NULL.
   */
  char *session_id;

  /**
   * Claim token to use when claiming the order. May be NULL.
   */
  struct TALER_ClaimTokenP *claim_token;

  /**
   * A WLAN SSID that the wallet can use to connect to the internet in order to
   * to pay. May be NULL.
   */
  char *ssid;

  /**
   * true if the URI used taler+http.
   */
  bool use_http;
};


/**
 * Extracts information from a taler://pay URI.
 *
 * @param pay_uri the URI to parse.
 * @param[out] parse_data data extracted from the URI. Must be free'd.
 * @return #GNUNET_SYSERR if @e pay_uri is malformed, #GNUNET_OK otherwise.
 */
enum GNUNET_GenericReturnValue
TALER_MERCHANT_parse_pay_uri (const char *pay_uri,
                              struct TALER_MERCHANT_PayUriData *parse_data);


/**
 * Frees data contained in the result of parsing a taler://pay URI.
 *
 * @param[in] parse_data the data to free.
 */
void
TALER_MERCHANT_parse_pay_uri_free (
  struct TALER_MERCHANT_PayUriData *parse_data);


/**
 * Contains information gathered from parsing a taler://refund URI.
 */
struct TALER_MERCHANT_RefundUriData
{
  /**
   * Hostname (and possibly port) of the merchant.
   */
  char *merchant_host;

  /**
   * Prefix to the base url of the merchant backend. May be NULL.
   */
  char *merchant_prefix_path;

  /**
   * The id of the order to pay.
   */
  char *order_id;

  /**
   * A WLAN SSID that the wallet can use to connect to the internet in order to
   * to pay. May be NULL.
   */
  char *ssid;

  /**
   * true if the URI used taler+http.
   */
  bool use_http;
};


/**
 * Extracts information from a taler://refund URI.
 *
 * @param refund_uri the URI to parse.
 * @param[out] parse_data data extracted from the URI. Must be free'd.
 * @return #GNUNET_SYSERR if @e refund_uri is malformed, #GNUNET_OK otherwise.
 */
enum GNUNET_GenericReturnValue
TALER_MERCHANT_parse_refund_uri (
  const char *refund_uri,
  struct TALER_MERCHANT_RefundUriData *parse_data);


/**
 * Frees data contained in the result of parsing a taler://refund URI.
 *
 * @param parse_data the data to free.
 */
void
TALER_MERCHANT_parse_refund_uri_free (
  struct TALER_MERCHANT_RefundUriData *parse_data);


/* ********************* /public/config ****************** */


/**
 * How compatible are the protocol version of the auditor and this
 * client?  The bits (1,2,4) can be used to test if the auditor's
 * version is incompatible, older or newer respectively.
 */
enum TALER_MERCHANT_VersionCompatibility
{

  /**
   * The auditor runs exactly the same protocol version.
   */
  TALER_MERCHANT_VC_MATCH = 0,

  /**
   * The auditor is too old or too new to be compatible with this
   * implementation (bit)
   */
  TALER_MERCHANT_VC_INCOMPATIBLE = 1,

  /**
   * The auditor is older than this implementation (bit)
   */
  TALER_MERCHANT_VC_OLDER = 2,

  /**
   * The auditor is too old to be compatible with
   * this implementation.
   */
  TALER_MERCHANT_VC_INCOMPATIBLE_OUTDATED
    = TALER_MERCHANT_VC_INCOMPATIBLE
      | TALER_MERCHANT_VC_OLDER,

  /**
   * The auditor is more recent than this implementation (bit).
   */
  TALER_MERCHANT_VC_NEWER = 4,

  /**
   * The auditor is too recent for this implementation.
   */
  TALER_MERCHANT_VC_INCOMPATIBLE_NEWER
    = TALER_MERCHANT_VC_INCOMPATIBLE
      | TALER_MERCHANT_VC_NEWER,

  /**
   * We could not even parse the version data.
   */
  TALER_MERCHANT_VC_PROTOCOL_ERROR = 8

};


/**
 * @brief Config information we get from the backend.
 */
struct TALER_MERCHANT_ConfigInformation
{
  /**
   * Default currency of the merchant.  See cspecs
   * for all currencies supported by the merchant.
   */
  const char *currency;

  /**
   * Supported Taler protocol version by the merchant.
   * String in the format current:revision:age using the
   * semantics of GNU libtool.  See
   * https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
   */
  const char *version;

};


/**
 * Information about an exchange the merchant backend trusts.
 */
struct TALER_MERCHANT_ExchangeConfigInfo
{
  /**
   * Base URL of the exchange REST API.
   */
  const char *base_url;

  /**
   * Currency for which the merchant is configured to
   * trust the exchange.
   */
  const char *currency;

  /**
   * Master public key of the exchange.
   */
  struct TALER_MasterPublicKeyP master_pub;

};

/**
 * Response to /config request.
 */
struct TALER_MERCHANT_ConfigResponse
{
  /**
   * HTTP response.
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Status-dependent details.
   */
  union
  {
    /**
     * Information returned on #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * basic information about the merchant
       */
      struct TALER_MERCHANT_ConfigInformation ci;

      /**
       * protocol compatibility information
       */
      enum TALER_MERCHANT_VersionCompatibility compat;

      /**
       * Length of the @e cspecs array.
       */
      unsigned int num_cspecs;

      /**
       * Array with rendering specifications for the currencies
       * supported by this merchant backend.
       */
      const struct TALER_CurrencySpecification *cspecs;

      /**
       * Length of the @e exchanges array.
       */
      unsigned int num_exchanges;

      /**
       * Array details about exchanges trusted
       * by this merchant backend.
       */
      const struct TALER_MERCHANT_ExchangeConfigInfo *exchanges;

    } ok;
  } details;
};


/**
 * Function called with information about the merchant.
 *
 * @param cls closure
 * @param cr response data
 */
typedef void
(*TALER_MERCHANT_ConfigCallback) (
  void *cls,
  const struct TALER_MERCHANT_ConfigResponse *cr);


/**
 * Handle for a #TALER_MERCHANT_config_get() operation.
 */
struct TALER_MERCHANT_ConfigGetHandle;


/**
 * Get the config data of a merchant. Will connect to the merchant backend
 * and obtain information about the backend.  The respective information will
 * be passed to the @a config_cb once available.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param config_cb function to call with the
 *        backend's config information
 * @param config_cb_cls closure for @a config_cb
 * @return the config check handle; NULL upon error
 */
struct TALER_MERCHANT_ConfigGetHandle *
TALER_MERCHANT_config_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  TALER_MERCHANT_ConfigCallback config_cb,
  void *config_cb_cls);


/**
 * Cancel /config request.  Must not be called by clients after
 * the callback was invoked.
 *
 * @param[in] vgh request to cancel.
 */
void
TALER_MERCHANT_config_get_cancel (struct TALER_MERCHANT_ConfigGetHandle *vgh);


/* ********************* /instances *********************** */


/**
 * @brief Information about a merchant instance.
 */
struct TALER_MERCHANT_InstanceInformation
{
  /**
   * Id of this instance.  This $ID can be used to construct the URL of the
   * instance, by combining it using "$MERCHANT_BASEURL/instances/$ID/".
   */
  const char *id;

  /**
   * Legal name of the merchant/instance.
   */
  const char *name;

  /**
   * Public key of the instance.
   */
  struct TALER_MerchantPublicKeyP merchant_pub;

  /**
   * JSON array of payment targets (strings) supported by this backend
   * instance.
   */
  const json_t *payment_targets;

};


/**
 * Handle for a GET /instances operation.
 */
struct TALER_MERCHANT_InstancesGetHandle;


/**
 * Response to a GET /instances request.
 */
struct TALER_MERCHANT_InstancesGetResponse
{
  /**
   * HTTP response data
   */
  struct TALER_MERCHANT_HttpResponse hr;

  union
  {
    /**
     * Data returned on #MHD_HTTP_OK status.
     */
    struct
    {
      /**
       * length of the @e iis array
       */
      unsigned int iis_length;

      /**
       * array with instance information of length @e iis_length
       */
      const struct TALER_MERCHANT_InstanceInformation *iis;
    } ok;
  } details;

};


/**
 * Function called with the result of the GET /instances operation.
 *
 * @param cls closure
 * @param igr response data
 */
typedef void
(*TALER_MERCHANT_InstancesGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_InstancesGetResponse *igr);


/**
 * Get the instance data of a backend. Will connect to the merchant backend
 * and obtain information about the instances.  The respective information will
 * be passed to the @a instances_cb once available.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param instances_cb function to call with the
 *        backend's instances information
 * @param instances_cb_cls closure for @a config_cb
 * @return the instances handle; NULL upon error
 */
struct TALER_MERCHANT_InstancesGetHandle *
TALER_MERCHANT_instances_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  TALER_MERCHANT_InstancesGetCallback instances_cb,
  void *instances_cb_cls);


/**
 * Cancel /instances request.  Must not be called by clients after
 * the callback was invoked.
 *
 * @param igh request to cancel.
 */
void
TALER_MERCHANT_instances_get_cancel (
  struct TALER_MERCHANT_InstancesGetHandle *igh);


/**
 * Handle for a POST /instances/$ID operation.
 */
struct TALER_MERCHANT_InstancesPostHandle;


/**
 * Function called with the result of the POST /instances/$ID operation.
 *
 * @param cls closure
 * @param hr HTTP response data
 */
typedef void
(*TALER_MERCHANT_InstancesPostCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Setup an new instance in the backend.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param instance_id identity of the instance to get information about
 * @param name name of the merchant instance
 * @param address physical address of the merchant instance
 * @param jurisdiction jurisdiction of the merchant instance
 * @param use_stefan use STEFAN curve for acceptable fees
 * @param default_wire_transfer_delay default wire transfer delay merchant will ask for
 * @param default_pay_delay default validity period for offers merchant makes
 * @param default_refund_delay default refund period
 * @param auth_token authentication token to use for access control, NULL for external auth; MUST follow RFC 8959
 * @param cb function to call with the
 *        backend's instances information
 * @param cb_cls closure for @a config_cb
 * @return the instances handle; NULL upon error
 */
struct TALER_MERCHANT_InstancesPostHandle *
TALER_MERCHANT_instances_post (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *instance_id,
  const char *name,
  const json_t *address,
  const json_t *jurisdiction,
  bool use_stefan,
  struct GNUNET_TIME_Relative default_wire_transfer_delay,
  struct GNUNET_TIME_Relative default_pay_delay,
  struct GNUNET_TIME_Relative default_refund_delay,
  const char *auth_token,
  TALER_MERCHANT_InstancesPostCallback cb,
  void *cb_cls);


/**
 * Cancel /instances request.  Must not be called by clients after
 * the callback was invoked.
 *
 * @param iph request to cancel.
 */
void
TALER_MERCHANT_instances_post_cancel (
  struct TALER_MERCHANT_InstancesPostHandle *iph);


/**
 * Handle for a PATCH /instances/$ID operation.
 */
struct TALER_MERCHANT_InstancePatchHandle;


/**
 * Function called with the result of the GET /instances/$ID operation.
 *
 * @param cls closure
 * @param hr HTTP response data
 */
typedef void
(*TALER_MERCHANT_InstancePatchCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Modify an existing instance in the backend.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend (top-level "default" instance
 *                    or base URL of an instance if @a instance_id is NULL)
 * @param instance_id identity of the instance to modify information about; NULL
 *                    if the instance is identified as part of the @a backend_url
 * @param name name of the merchant instance
 * @param address physical address of the merchant instance
 * @param jurisdiction jurisdiction of the merchant instance
 * @param use_stefan use STEFAN curve for acceptable fees
 * @param default_wire_transfer_delay default wire transfer delay merchant will ask for
 * @param default_pay_delay default validity period for offers merchant makes
 * @param default_refund_delay default refund period
 * @param cb function to call with the
 *        backend's instances information
 * @param cb_cls closure for @a config_cb
 * @return the instances handle; NULL upon error
 */
struct TALER_MERCHANT_InstancePatchHandle *
TALER_MERCHANT_instance_patch (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *instance_id,
  const char *name,
  const json_t *address,
  const json_t *jurisdiction,
  bool use_stefan,
  struct GNUNET_TIME_Relative default_wire_transfer_delay,
  struct GNUNET_TIME_Relative default_pay_delay,
  struct GNUNET_TIME_Relative default_refund_delay,
  TALER_MERCHANT_InstancePatchCallback cb,
  void *cb_cls);


/**
 * Cancel /instances request.  Must not be called by clients after
 * the callback was invoked.
 *
 * @param iph request to cancel.
 */
void
TALER_MERCHANT_instance_patch_cancel (
  struct TALER_MERCHANT_InstancePatchHandle *iph);


/**
 * Handle for an operation to modify authentication settings.
 */
struct TALER_MERCHANT_InstanceAuthPostHande;


/**
 * Function called with the result of the GET /instances/$ID operation.
 *
 * @param cls closure
 * @param hr HTTP response data
 */
typedef void
(*TALER_MERCHANT_InstanceAuthPostCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Modify authentication for an existing instance in the backend.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend (top-level "default" instance
 *                    or base URL of an instance if @a instance_id is NULL)
 * @param instance_id identity of the instance to patch the authentication for; NULL
 *                    if the instance is identified as part of the @a backend_url
 * @param auth_token authorization token needed to access the instance, can be NULL
 *                   to switch to no (or external) authentication; MUST follow RFC 8959
 * @param cb function to call with the backend's response
 * @param cb_cls closure for @a config_cb
 * @return the instances handle; NULL upon error
 */
struct TALER_MERCHANT_InstanceAuthPostHandle *
TALER_MERCHANT_instance_auth_post (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *instance_id,
  const char *auth_token,
  TALER_MERCHANT_InstanceAuthPostCallback cb,
  void *cb_cls);


/**
 * Cancel /private/auth request.  Must not be called by clients after
 * the callback was invoked.  Afterwards, the authentication may or
 * may not have been updated.
 *
 * @param iaph request to cancel.
 */
void
TALER_MERCHANT_instance_auth_post_cancel (
  struct TALER_MERCHANT_InstanceAuthPostHandle *iaph);

/**
 * Handle for an operation to get access token.
 */
struct TALER_MERCHANT_InstanceTokenPostHande;


/**
 * Function called with the result of the GET /instances/$ID/private/token
 * operation.
 *
 * @param cls closure
 * @param hr HTTP response data
 */
typedef void
(*TALER_MERCHANT_InstanceTokenPostCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);

/**
 * Get access token for an existing instance in the backend.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend (top-level "default" instance
 *                    or base URL of an instance if @a instance_id is NULL)
 * @param instance_id identity of the instance to patch the authentication for; NULL
 *                    if the instance is identified as part of the @a backend_url
 * @param scope       authorization scope for token needed to access the instance, can be NULL
 * @param duration    requested authorization duration
 * @param refreshable requesting a refreshable token or not
 * @param cb function to call with the backend's response
 * @param cb_cls closure for @a config_cb
 * @return the instances handle; NULL upon error
 */
struct TALER_MERCHANT_InstanceTokenPostHandle *
TALER_MERCHANT_instance_token_post (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *instance_id,
  const char *scope,
  struct GNUNET_TIME_Relative duration,
  bool refreshable,
  TALER_MERCHANT_InstanceTokenPostCallback cb,
  void *cb_cls);


/**
 * Cancel /private/token request.  Must not be called by clients after
 * the callback was invoked.  Afterwards, the authentication may or
 * may not have been updated.
 *
 * @param itph request to cancel.
 */
void
TALER_MERCHANT_instance_token_post_cancel (
  struct TALER_MERCHANT_InstanceTokenPostHandle *itph);

/**
 * Handle for a DELETE /instances/$ID/private/token operation.
 */
struct TALER_MERCHANT_InstanceTokenDeleteHandle;


/**
 * Function called with the result of the DELETE /instances/$ID/private/token operation.
 *
 * @param cls closure
 * @param hr response data
 */
typedef void
(*TALER_MERCHANT_InstanceTokenDeleteCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Remove token instance in the backend.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param instance_id identity of the instance to patch the authentication for; NULL
 *                    if the instance is identified as part of the @a backend_url
 * @param cb function to call with the response
 * @param cb_cls closure for @a config_cb
 * @return the instances handle; NULL upon error
 */
struct TALER_MERCHANT_InstanceTokenDeleteHandle *
TALER_MERCHANT_instance_token_delete (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *instance_id,
  TALER_MERCHANT_InstanceTokenDeleteCallback cb,
  void *cb_cls);


/**
 * Cancel DELETE token request.  Must not be called by clients after
 * the callback was invoked.
 *
 * @param tdh request to cancel.
 */
void
TALER_MERCHANT_instance_token_delete_cancel (
  struct TALER_MERCHANT_InstanceTokenDeleteHandle *tdh);


/**
 * Handle for a GET /instances/$ID operation.
 */
struct TALER_MERCHANT_InstanceGetHandle;


/**
 * Details about an instance.
 */
struct TALER_MERCHANT_InstanceDetails
{
  /**
   * Name of the merchant instance
   */
  const char *name;

  /**
   * public key of the merchant instance
   */
  struct TALER_MerchantPublicKeyP merchant_pub;

  /**
   * physical address of the merchant instance
   */
  const json_t *address;

  /**
   * jurisdiction of the merchant instance
   */
  const json_t *jurisdiction;

  /**
   * Are we using STEFAN curves to determine acceptable
   * fees?
   */
  bool use_stefan;

  /**
   * default wire transfer delay merchant will ask for
   */
  struct GNUNET_TIME_Relative default_wire_transfer_delay;

  /**
   * default validity period for offers merchant makes
   */
  struct GNUNET_TIME_Relative default_pay_delay;

  /**
   * default refund period for offers merchant makes
   */
  struct GNUNET_TIME_Relative default_refund_delay;

  /**
   * Default interval by which we round up wire transfer deadlines
   * computed using the @e default_wire_transfer_delay.
   */
  enum GNUNET_TIME_RounderInterval default_wire_transfer_rounding_interval;

};


struct TALER_MERCHANT_InstanceGetResponse
{
  /**
   * HTTP response data
   */
  struct TALER_MERCHANT_HttpResponse hr;

  union
  {

    /**
     * Data returned on #MHD_HTTP_OK.
     */
    struct
    {
      /**
       * Details about the instance.
       */
      struct TALER_MERCHANT_InstanceDetails details;

    } ok;
  }
  details;
};


/**
 * Function called with the result of the GET /instances/$ID operation.
 *
 * @param cls closure
 * @param igr response details
 */
typedef void
(*TALER_MERCHANT_InstanceGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_InstanceGetResponse *igr);


/**
 * Get the details on one of the instances of a backend. Will connect to the
 * merchant backend and obtain information about the instance.  The respective
 * information will be passed to the @a cb once available.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param instance_id identity of the instance to get information about
 * @param cb function to call with the
 *        backend's instances information
 * @param cb_cls closure for @a config_cb
 * @return the instances handle; NULL upon error
 */
struct TALER_MERCHANT_InstanceGetHandle *
TALER_MERCHANT_instance_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *instance_id,
  TALER_MERCHANT_InstanceGetCallback cb,
  void *cb_cls);


/**
 * Cancel /instances request.  Must not be called by clients after
 * the callback was invoked.
 *
 * @param igh request to cancel.
 */
void
TALER_MERCHANT_instance_get_cancel (
  struct TALER_MERCHANT_InstanceGetHandle *igh);


/**
 * Handle for a DELETE /instances operation.
 */
struct TALER_MERCHANT_InstanceDeleteHandle;


/**
 * Function called with the result of the DELETE /instances operation.
 *
 * @param cls closure
 * @param hr HTTP response data
 */
typedef void
(*TALER_MERCHANT_InstanceDeleteCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Delete the private key of an instance of a backend, thereby disabling the
 * instance for future requests.  Will preserve the other instance data
 * (i.e. for taxation).
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend (top-level "default" instance
 *                    or base URL of an instance if @a instance_id is NULL)
 * @param instance_id identity of the instance to modify information about; NULL
 *                    if the instance is identified as part of the @a backend_url
 * @param instances_cb function to call with the
 *        backend's return
 * @param instances_cb_cls closure for @a config_cb
 * @return the instances handle; NULL upon error
 */
struct TALER_MERCHANT_InstanceDeleteHandle *
TALER_MERCHANT_instance_delete (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *instance_id,
  TALER_MERCHANT_InstanceDeleteCallback instances_cb,
  void *instances_cb_cls);


/**
 * Purge all data associated with an instance. Use with
 * extreme caution.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param instance_id which instance should be deleted
 * @param instances_cb function to call with the
 *        backend's return
 * @param instances_cb_cls closure for @a config_cb
 * @return the instances handle; NULL upon error
 */
struct TALER_MERCHANT_InstanceDeleteHandle *
TALER_MERCHANT_instance_purge (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *instance_id,
  TALER_MERCHANT_InstanceDeleteCallback instances_cb,
  void *instances_cb_cls);


/**
 * Cancel /instances DELETE request.  Must not be called by clients after
 * the callback was invoked.
 *
 * @param idh request to cancel.
 */
void
TALER_MERCHANT_instance_delete_cancel (
  struct TALER_MERCHANT_InstanceDeleteHandle *idh);


/**
 * Cancel /instances DELETE request.  Must not be called by clients after
 * the callback was invoked.
 *
 * @param arg request to cancel.
 */
#define TALER_MERCHANT_instance_purge_cancel(arg) \
        TALER_MERCHANT_instance_delete_cancel (arg)


/* *************** Accounts **************** */

/**
 * Handle for a POST /instances/$ID/accounts operation.
 */
struct TALER_MERCHANT_AccountsPostHandle;


/**
 * Response for a POST /instances/$ID/account operation.
 */
struct TALER_MERCHANT_AccountsPostResponse
{
  /**
   * HTTP response data
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details depending on HTTP status.
   */
  union
  {

    /**
     * Details returned on #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * Hash of @e payto_uri and @e salt.
       */
      struct TALER_MerchantWireHashP h_wire;

      /**
       * salt used to compute h_wire
       */
      struct TALER_WireSaltP salt;
    } ok;

  } details;
};


/**
 * Function called with the result of the POST /instances/$ID/accounts operation.
 *
 * @param cls closure
 * @param par response data
 */
typedef void
(*TALER_MERCHANT_AccountsPostCallback)(
  void *cls,
  const struct TALER_MERCHANT_AccountsPostResponse *par);


/**
 * Setup an new account for an instance in the backend.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param payto_uri URI of the bank account as per RFC 8905
 * @param credit_facade_url credit facade for the account, can be NULL
 * @param credit_facade_credentials credentials for credit facade, can be NULL
 * @param cb function to call with the response
 * @param cb_cls closure for @a config_cb
 * @return the instances handle; NULL upon error
 */
struct TALER_MERCHANT_AccountsPostHandle *
TALER_MERCHANT_accounts_post (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  struct TALER_FullPayto payto_uri,
  const char *credit_facade_url,
  const json_t *credit_facade_credentials,
  TALER_MERCHANT_AccountsPostCallback cb,
  void *cb_cls);


/**
 * Cancel POST /accounts request.  Must not be called by clients after
 * the callback was invoked.
 *
 * @param pah request to cancel.
 */
void
TALER_MERCHANT_accounts_post_cancel (
  struct TALER_MERCHANT_AccountsPostHandle *pah);


/**
 * Handle for a GET /accounts/$ID operation.
 */
struct TALER_MERCHANT_AccountGetHandle;


/**
 * Details about a merchant's bank account.
 */
struct TALER_MERCHANT_AccountDetails
{
  /**
   * salt used to compute h_wire
   */
  struct TALER_WireSaltP salt;

  /**
   * payto:// URI of the account.
   */
  struct TALER_FullPayto payto_uri;

  /**
   * Credit facade URL of the account.
   */
  const char *credit_facade_url;

  /**
   * Hash of @e payto_uri and @e salt.
   */
  struct TALER_MerchantWireHashP h_wire;

  /**
   * true if the account is active,
   * false if it is historic.
   */
  bool active;
};


/**
 * Response returned with details about an account.
 */
struct TALER_MERCHANT_AccountGetResponse
{
  /**
   * HTTP response data
   */
  struct TALER_MERCHANT_HttpResponse hr;

  union
  {

    /**
     * Data returned on #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * bank accounts of the merchant instance
       */
      struct TALER_MERCHANT_AccountDetails ad;

    } ok;
  }
  details;
};


/**
 * Function called with the result of the GET /instances/$ID/accounts/$H_WIRE operation.
 *
 * @param cls closure
 * @param igr response details
 */
typedef void
(*TALER_MERCHANT_AccountGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_AccountGetResponse *igr);


/**
 * Get the details on one of the accounts of an instance. Will connect to the
 * merchant backend and obtain information about the account.  The respective
 * information will be passed to the @a cb once available.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param instance_id identity of the instance to get information about
 * @param h_wire hash of the wire details
 * @param cb function to call with the
 *        backend's instances information
 * @param cb_cls closure for @a config_cb
 * @return the instances handle; NULL upon error
 */
struct TALER_MERCHANT_AccountGetHandle *
TALER_MERCHANT_account_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *instance_id,
  const struct TALER_MerchantWireHashP *h_wire,
  TALER_MERCHANT_AccountGetCallback cb,
  void *cb_cls);


/**
 * Cancel GET /accounts/$H_WIRE request.  Must not be called by clients after
 * the callback was invoked.
 *
 * @param igh request to cancel.
 */
void
TALER_MERCHANT_account_get_cancel (
  struct TALER_MERCHANT_AccountGetHandle *igh);


/**
 * Handle for a GET /accounts operation.
 */
struct TALER_MERCHANT_AccountsGetHandle;

/**
 * Individual account (minimal information
 * returned via GET /accounts).
 */
struct TALER_MERCHANT_AccountEntry
{
  /**
   * account payto URI.
   */
  struct TALER_FullPayto payto_uri;

  /**
   * Hash of @e payto_uri and salt.
   */
  struct TALER_MerchantWireHashP h_wire;

};


/**
 * Response to a GET /accounts operation.
 */
struct TALER_MERCHANT_AccountsGetResponse
{
  /**
   * HTTP response details
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details depending on status.
   */
  union
  {
    /**
     * Details if status is #MHD_HTTP_OK.
     */
    struct
    {
      /**
       * length of the @e accounts array
       */
      unsigned int accounts_length;

      /**
       * array of accounts the requested instance offers
       */
      const struct TALER_MERCHANT_AccountEntry *accounts;
    } ok;
  } details;
};


/**
 * Function called with the result of the GET /accounts operation.
 *
 * @param cls closure
 * @param tgr response details
 */
typedef void
(*TALER_MERCHANT_AccountsGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_AccountsGetResponse *tgr);


/**
 * Make a GET /accounts request.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param cb function to call with the backend information
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_AccountsGetHandle *
TALER_MERCHANT_accounts_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  TALER_MERCHANT_AccountsGetCallback cb,
  void *cb_cls);


/**
 * Cancel GET /accounts operation.
 *
 * @param tgh operation to cancel
 */
void
TALER_MERCHANT_accounts_get_cancel (
  struct TALER_MERCHANT_AccountsGetHandle *tgh);


/**
 * Handle for a PATCH /account operation.
 */
struct TALER_MERCHANT_AccountPatchHandle;


/**
 * Function called with the result of the PATCH /account operation.
 *
 * @param cls closure
 * @param hr HTTP response details
 */
typedef void
(*TALER_MERCHANT_AccountPatchCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Make a PATCH /accounts/$H_WIRE request to update account details. Cannot be used to change the payto URI or the salt.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param h_wire identifies the account to patch
 * @param credit_facade_url credit facade for the account, can be NULL
 * @param credit_facade_credentials credentials for credit facade, can be NULL
 * @param cb function to call with the backend's result
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_AccountPatchHandle *
TALER_MERCHANT_account_patch (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const struct TALER_MerchantWireHashP *h_wire,
  const char *credit_facade_url,
  const json_t *credit_facade_credentials,
  TALER_MERCHANT_AccountPatchCallback cb,
  void *cb_cls);


/**
 * Cancel PATCH /accounts/$H_WIRE operation.
 *
 * @param[in] tph operation to cancel
 */
void
TALER_MERCHANT_account_patch_cancel (
  struct TALER_MERCHANT_AccountPatchHandle *tph);


/**
 * Handle for a DELETE /instances/$ID/account/$H_WIRE operation.
 */
struct TALER_MERCHANT_AccountDeleteHandle;


/**
 * Response for a DELETE /instances/$ID/account operation.
 */
struct TALER_MERCHANT_AccountDeleteResponse
{
  /**
   * HTTP response data
   */
  struct TALER_MERCHANT_HttpResponse hr;
};


/**
 * Function called with the result of the DELETE /instances/$ID/account/$H_WIRE operation.
 *
 * @param cls closure
 * @param par response data
 */
typedef void
(*TALER_MERCHANT_AccountDeleteCallback)(
  void *cls,
  const struct TALER_MERCHANT_AccountDeleteResponse *par);


/**
 * Remove bank account from an instance in the backend.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param h_wire wire hash of the bank accounts to delete
 * @param cb function to call with the response
 * @param cb_cls closure for @a config_cb
 * @return the instances handle; NULL upon error
 */
struct TALER_MERCHANT_AccountDeleteHandle *
TALER_MERCHANT_account_delete (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const struct TALER_MerchantWireHashP *h_wire,
  TALER_MERCHANT_AccountDeleteCallback cb,
  void *cb_cls);


/**
 * Cancel /account request.  Must not be called by clients after
 * the callback was invoked.
 *
 * @param pah request to cancel.
 */
void
TALER_MERCHANT_account_delete_cancel (
  struct TALER_MERCHANT_AccountDeleteHandle *pah);


/* ********************* /products *********************** */


/**
 * Handle for a GET /products operation.
 */
struct TALER_MERCHANT_ProductsGetHandle;

/**
 * Individual product from the inventory (minimal information
 * returned via GET /products).
 */
struct TALER_MERCHANT_InventoryEntry
{
  /**
   * Product identifier.
   */
  const char *product_id;

  /**
   * Serial ID of the product.
   */
  uint64_t product_serial;
};


/**
 * Response to a GET /products request.
 */
struct TALER_MERCHANT_GetProductsResponse
{
  /**
   * HTTP response details
   */
  struct TALER_MERCHANT_HttpResponse hr;

  union
  {
    struct
    {

      /**
       * length of the @a products array
       */
      unsigned int products_length;

      /**
       * array of products the requested instance offers
       */
      const struct TALER_MERCHANT_InventoryEntry *products;
    } ok;

  } details;
};


/**
 * Function called with the result of the GET /products operation.
 *
 * @param cls closure
 * @param gpr response details
 */
typedef void
(*TALER_MERCHANT_ProductsGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_GetProductsResponse *gpr);


/**
 * Make a GET /products request.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param cb function to call with the backend's inventory information
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_ProductsGetHandle *
TALER_MERCHANT_products_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  TALER_MERCHANT_ProductsGetCallback cb,
  void *cb_cls);


/**
 * Cancel GET /products operation.
 *
 * @param pgh operation to cancel
 */
void
TALER_MERCHANT_products_get_cancel (
  struct TALER_MERCHANT_ProductsGetHandle *pgh);


/**
 * Handle for a GET /product/$ID operation. Gets details
 * about a single product. Do not confused with a
 * `struct TALER_MERCHANT_ProductsGetHandle`, which
 * obtains a list of all products.
 */
struct TALER_MERCHANT_ProductGetHandle;


/**
 * Response to GET /product/$ID operation.
 */
struct TALER_MERCHANT_ProductGetResponse
{
  /**
   * HTTP response details
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details depending on HTTP status.
   */
  union
  {
    /**
     * Details for #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * description of the product
       */
      const char *description;

      /**
       * Map from IETF BCP 47 language tags to localized descriptions
       */
      const json_t *description_i18n;

      /**
       * unit in which the product is measured (liters, kilograms, packages, etc.)
       */
      const char *unit;

      /**
       * the price for one @a unit of the product, zero is used to imply that
       * this product is not sold separately or that the price is
       * not fixed and must be supplied by the front-end.  If
       * non-zero, price must include applicable taxes.
       */
      struct TALER_Amount price;

      /**
       * Optional list of price tiers as provided by the backend.
       */
      const struct TALER_Amount *unit_price;

      /**
       * Size of unit_price array
       */
      size_t unit_price_len;

      /**
       * base64-encoded product image, can be NULL if none is set.
       */
      const char *image;

      /**
       * list of taxes paid by the merchant, can be NULL if no taxes were specified.
       */
      const json_t *taxes;

      /**
       * total_stock in @e units, -1 to indicate "infinite" (i.e. electronic
       * books), does NOT indicate remaining stocks, to get remaining stocks,
       * subtract @e total_sold and @e total_lost. Note that this still does
       * not then say how many of the remaining inventory are locked.
       */
      int64_t total_stock;

      /**
       * Set to true if fractional quantities are allowed for this product.
       */
      bool unit_allow_fraction;

      /**
       * Suggested fractional precision for fractional quantities.
       */
      uint32_t unit_precision_level;

      /**
       * Stock level encoded as a decimal string. Preferred source of truth for fractional stock.
       */
      const char *unit_total_stock;

      /**
       * in @e units, total number of @e unit of product sold
       */
      uint64_t total_sold;

      /**
       * in @e units, total number of @e unit of product lost from inventory
       */
      uint64_t total_lost;

      /**
       * where the product is in stock, can be NULL if no location was given.
       */
      const json_t *location;

      /**
       * when the next restocking is expected to happen, 0 for unknown,
       * #GNUNET_TIME_UNIT_FOREVER_ABS for 'never'.
       */
      struct GNUNET_TIME_Timestamp next_restock;

      /**
       * name of the product
       */
      const char *product_name;
    } ok;

  } details;

};


/**
 * Function called with the result of the GET /products operation.
 *
 * @param cls closure
 * @param pgr response details
 */
typedef void
(*TALER_MERCHANT_ProductGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_ProductGetResponse *pgr);


/**
 * Make a GET /product/$ID request to get details about an
 * individual product.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param product_id identifier of the product to inquire about
 * @param cb function to call with the backend's product information
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_ProductGetHandle *
TALER_MERCHANT_product_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *product_id,
  TALER_MERCHANT_ProductGetCallback cb,
  void *cb_cls);


/**
 * Cancel GET /products/$ID operation.
 *
 * @param pgh operation to cancel
 */
void
TALER_MERCHANT_product_get_cancel (
  struct TALER_MERCHANT_ProductGetHandle *pgh);


/* ********************* /products/$HASH/image *********************** */


/**
 * Handle for a GET /products/$HASH/image operation.
 */
struct TALER_MERCHANT_ProductImageGetHandle;


/**
 * Response to GET /products/$HASH/image operation.
 */
struct TALER_MERCHANT_ProductImageGetResponse
{
  /**
   * HTTP response details
   */
  struct TALER_MERCHANT_HttpResponse hr;

  union
  {
    /**
     * Details for #MHD_HTTP_OK.
     */
    struct
    {
      /**
       * Base64-encoded data URL containing the product image.
       */
      const char *image;
    } ok;
  } details;
};


/**
 * Function called with the result of the GET /products/$HASH/image operation.
 *
 * @param cls closure
 * @param pir response details
 */
typedef void
(*TALER_MERCHANT_ProductImageGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_ProductImageGetResponse *pir);


/**
 * Make a GET /products/$HASH/image request.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param image_hash the image hash to fetch
 * @param cb function to call with the backend's response
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_ProductImageGetHandle *
TALER_MERCHANT_product_image_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *image_hash,
  TALER_MERCHANT_ProductImageGetCallback cb,
  void *cb_cls);


/**
 * Cancel GET /products/$HASH/image operation.
 *
 * @param pigh operation to cancel
 */
void
TALER_MERCHANT_product_image_get_cancel (
  struct TALER_MERCHANT_ProductImageGetHandle *pigh);


/**
 * Handle for a POST /products operation.
 */
struct TALER_MERCHANT_ProductsPostHandle;


/**
 * Function called with the result of the POST /products operation.
 *
 * @param cls closure
 * @param hr HTTP response details
 */
typedef void
(*TALER_MERCHANT_ProductsPostCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Make a POST /products request to add a product to the
 * inventory.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param product_id identifier to use for the product
 * @param description description of the product
 * @param description_i18n Map from IETF BCP 47 language tags to localized descriptions
 * @param unit unit in which the product is measured (liters, kilograms, packages, etc.)
 * @param price the price for one @a unit of the product, zero is used to imply that
 *              this product is not sold separately or that the price is not fixed and
 *              must be supplied by the front-end.  If non-zero, price must include
 *              applicable taxes.
 * @param image base64-encoded product image
 * @param taxes list of taxes paid by the merchant
 * @param total_stock in @a units, -1 to indicate "infinite" (i.e. electronic books)
 * @param address where the product is in stock
 * @param next_restock when the next restocking is expected to happen, 0 for unknown,
 *                     #GNUNET_TIME_UNIT_FOREVER_ABS for 'never'.
 * @param cb function to call with the backend's result
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_ProductsPostHandle *
TALER_MERCHANT_products_post (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *product_id,
  const char *description,
  const json_t *description_i18n,
  const char *unit,
  const struct TALER_Amount *price,
  const char *image,
  const json_t *taxes,
  int64_t total_stock,
  const json_t *address,
  struct GNUNET_TIME_Timestamp next_restock,
  TALER_MERCHANT_ProductsPostCallback cb,
  void *cb_cls);


/**
 * Make a POST /products request to add a product to the
 * inventory.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param product_id identifier to use for the product
 * @param description description of the product
 * @param description_i18n Map from IETF BCP 47 language tags to localized descriptions
 * @param unit unit in which the product is measured (liters, kilograms, packages, etc.)
 * @param price the price for one @a unit of the product, zero is used to imply that
 *              this product is not sold separately or that the price is not fixed and
 *              must be supplied by the front-end.  If non-zero, price must include
 *              applicable taxes.
 * @param image base64-encoded product image
 * @param taxes list of taxes paid by the merchant
 * @param total_stock in @a units, -1 to indicate "infinite" (i.e. electronic books)
 * @param address where the product is in stock
 * @param next_restock when the next restocking is expected to happen, 0 for unknown,
 *                     #GNUNET_TIME_UNIT_FOREVER_ABS for 'never'.
 * @param minimum_age minimum age the buyer must have
 * @param cb function to call with the backend's result
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_ProductsPostHandle *
TALER_MERCHANT_products_post2 (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *product_id,
  const char *description,
  const json_t *description_i18n,
  const char *unit,
  const struct TALER_Amount *price,
  const char *image,
  const json_t *taxes,
  int64_t total_stock,
  const json_t *address,
  struct GNUNET_TIME_Timestamp next_restock,
  uint32_t minimum_age,
  TALER_MERCHANT_ProductsPostCallback cb,
  void *cb_cls);


/**
 * Make a POST /products request to add a product to the
 * inventory.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param product_id identifier to use for the product
 * @param description description of the product
 * @param description_i18n Map from IETF BCP 47 language tags to localized descriptions
 * @param unit unit in which the product is measured (liters, kilograms, packages, etc.)
 * @param price the price for one @a unit of the product, zero is used to imply that
 *              this product is not sold separately or that the price is not fixed and
 *              must be supplied by the front-end.  If non-zero, price must include
 *              applicable taxes.
 * @param image base64-encoded product image
 * @param taxes list of taxes paid by the merchant
 * @param total_stock in @a units, -1 to indicate "infinite" (i.e. electronic books)
 * @param address where the product is in stock
 * @param next_restock when the next restocking is expected to happen, 0 for unknown,
 *                     #GNUNET_TIME_UNIT_FOREVER_ABS for 'never'.
 * @param minimum_age minimum age the buyer must have
 * @param num_cats length of the @a cats array
 * @param cats array of categories the product is in
 * @param cb function to call with the backend's result
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_ProductsPostHandle *
TALER_MERCHANT_products_post3 (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *product_id,
  const char *description,
  const json_t *description_i18n,
  const char *unit,
  const struct TALER_Amount *price,
  const char *image,
  const json_t *taxes,
  int64_t total_stock,
  const json_t *address,
  struct GNUNET_TIME_Timestamp next_restock,
  uint32_t minimum_age,
  unsigned int num_cats,
  const uint64_t *cats,
  TALER_MERCHANT_ProductsPostCallback cb,
  void *cb_cls);


/**
 * Make a POST /products request to add a product to the
 * inventory.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param product_id identifier to use for the product
 * @param description description of the product
 * @param description_i18n Map from IETF BCP 47 language tags to localized descriptions
 * @param unit unit in which the product is measured (liters, kilograms, packages, etc.)
 * @param unit_prices array of price tiers (at least one entry)
 * @param unit_price_len length of @a unit_prices
 * @param image base64-encoded product image
 * @param taxes list of taxes paid by the merchant
 * @param total_stock integer quantity to use when @a unit_allow_fraction is false;
 *        set to -1 for unlimited stock
 * @param total_stock_frac fractional component (0-#MERCHANT_UNIT_FRAC_BASE) to use when
 *        @a unit_allow_fraction is true; ignored otherwise. Clients should use 0
 *        when there is no fractional part or when @a total_stock is -1 (unlimited).
 * @param unit_allow_fraction whether fractional quantity purchases are allowed
 * @param unit_precision_level optional override for the fractional precision; pass NULL to use the default derived from @a unit
 * @param address where the product is in stock
 * @param next_restock when the next restocking is expected to happen, 0 for unknown
 * @param minimum_age minimum age the buyer must have
 * @param num_cats length of the @a cats array
 * @param cats array of categories the product is in
 * @param cb function to call with the backend's result
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_ProductsPostHandle *
TALER_MERCHANT_products_post4 (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *product_id,
  const char *description,
  const json_t *description_i18n,
  const char *unit,
  const struct TALER_Amount *unit_prices,
  size_t unit_price_len,
  const char *image,
  const json_t *taxes,
  int64_t total_stock,
  uint32_t total_stock_frac,
  bool unit_allow_fraction,
  const uint32_t *unit_precision_level,
  const json_t *address,
  struct GNUNET_TIME_Timestamp next_restock,
  uint32_t minimum_age,
  unsigned int num_cats,
  const uint64_t *cats,
  TALER_MERCHANT_ProductsPostCallback cb,
  void *cb_cls);


/**
 * Cancel POST /products operation.
 *
 * @param pph operation to cancel
 */
void
TALER_MERCHANT_products_post_cancel (
  struct TALER_MERCHANT_ProductsPostHandle *pph);


/**
 * Handle for a PATCH /products operation.
 */
struct TALER_MERCHANT_ProductPatchHandle;


/**
 * Function called with the result of the PATCH /products operation.
 *
 * @param cls closure
 * @param hr HTTP response details
 */
typedef void
(*TALER_MERCHANT_ProductPatchCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Make a PATCH /products request to update product details in the
 * inventory.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param product_id identifier to use for the product; the product must exist,
 *                    or the transaction will fail with a #MHD_HTTP_NOT_FOUND
 *                    HTTP status code
 * @param description description of the product
 * @param description_i18n Map from IETF BCP 47 language tags to localized descriptions
 * @param unit unit in which the product is measured (liters, kilograms, packages, etc.)
 * @param price the price for one @a unit of the product, zero is used to imply that
 *              this product is not sold separately or that the price is not fixed and
 *              must be supplied by the front-end.  If non-zero, price must include
 *              applicable taxes.
 * @param image base64-encoded product image
 * @param taxes list of taxes paid by the merchant
 * @param total_stock in @a units, -1 to indicate "infinite" (i.e. electronic books),
 *               must be larger than previous values
 * @param total_lost in @a units, must be larger than previous values, and may
 *               not exceed total_stock minus total_sold; if it does, the transaction
 *               will fail with a #MHD_HTTP_CONFLICT HTTP status code
 * @param address where the product is in stock
 * @param next_restock when the next restocking is expected to happen
 * @param cb function to call with the backend's result
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_ProductPatchHandle *
TALER_MERCHANT_product_patch (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *product_id,
  const char *description,
  const json_t *description_i18n,
  const char *unit,
  const struct TALER_Amount *price,
  const char *image,
  const json_t *taxes,
  int64_t total_stock,
  uint64_t total_lost,
  const json_t *address,
  struct GNUNET_TIME_Timestamp next_restock,
  TALER_MERCHANT_ProductPatchCallback cb,
  void *cb_cls);


/**
 * Make a PATCH /products request to update a product using the
 * extended inventory fields.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param product_id identifier of the product to modify
 * @param description description of the product
 * @param description_i18n localized descriptions
 * @param unit sales unit
 * @param unit_prices array of price tiers (at least one entry)
 * @param unit_price_len number of entries in @a unit_prices
 * @param image base64-encoded image
 * @param taxes list of taxes
 * @param total_stock integer quantity when @a unit_allow_fraction is false
 * @param total_stock_frac fractional quantity component (0-#MERCHANT_UNIT_FRAC_BASE) when
 *        @a unit_allow_fraction is true; ignored otherwise
 * @param unit_allow_fraction whether fractional quantity purchases are allowed
 * @param unit_precision_level optional override for the fractional precision; pass NULL to use the default derived from @a unit
 * @param total_lost stock lost so far
 * @param address inventory address
 * @param next_restock expected restock date
 * @param cb function to call with the backend's result
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_ProductPatchHandle *
TALER_MERCHANT_product_patch2 (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *product_id,
  const char *description,
  const json_t *description_i18n,
  const char *unit,
  const struct TALER_Amount *unit_prices,
  size_t unit_price_len,
  const char *image,
  const json_t *taxes,
  int64_t total_stock,
  uint32_t total_stock_frac,
  bool unit_allow_fraction,
  const uint32_t *unit_precision_level,
  uint64_t total_lost,
  const json_t *address,
  struct GNUNET_TIME_Timestamp next_restock,
  TALER_MERCHANT_ProductPatchCallback cb,
  void *cb_cls);


/**
 * Cancel PATCH /products operation.
 *
 * @param pph operation to cancel
 */
void
TALER_MERCHANT_product_patch_cancel (
  struct TALER_MERCHANT_ProductPatchHandle *pph);


/**
 * Handle for a POST /products/$ID/lock operation.
 */
struct TALER_MERCHANT_ProductLockHandle;


/**
 * Function called with the result of the POST /product/$ID/lock operation.
 *
 * @param cls closure
 * @param hr HTTP response details
 */
typedef void
(*TALER_MERCHANT_ProductLockCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Make a POST /products/$ID/lock request to reserve a certain
 * amount of product in inventory to a reservation UUID.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param product_id identifier of the product
 * @param uuid UUID that identifies the client holding the lock
 * @param duration how long should the lock be held
 * @param quantity how much product should be locked (integer part)
 * @param quantity_frac fractional component to lock when
 *        @a use_fractional_quantity is true; value is expressed in units of
 *        1/1000000 of the base unit
 * @param use_fractional_quantity set to true when @a quantity_frac is used
 * @param cb function to call with the backend's lock status
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_ProductLockHandle *
TALER_MERCHANT_product_lock2 (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *product_id,
  const char *uuid,
  struct GNUNET_TIME_Relative duration,
  uint64_t quantity,
  uint32_t quantity_frac,
  bool use_fractional_quantity,
  TALER_MERCHANT_ProductLockCallback cb,
  void *cb_cls);


/**
 * Legacy helper that locks products using integer quantities only.
 * Prefer using #TALER_MERCHANT_product_lock2 for fractional quantities.
 */
struct TALER_MERCHANT_ProductLockHandle *
TALER_MERCHANT_product_lock (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *product_id,
  const char *uuid,
  struct GNUNET_TIME_Relative duration,
  uint32_t quantity,
  TALER_MERCHANT_ProductLockCallback cb,
  void *cb_cls);


/**
 * Cancel POST /products/$ID/lock operation. Note that the
 * lock may or may not be acquired despite the cancellation.
 *
 * @param plh operation to cancel
 */
void
TALER_MERCHANT_product_lock_cancel (
  struct TALER_MERCHANT_ProductLockHandle *plh);


/**
 * Handle for a DELETE /products/$ID operation.
 */
struct TALER_MERCHANT_ProductDeleteHandle;


/**
 * Function called with the result of the DELETE /product/$ID operation.
 *
 * @param cls closure
 * @param hr HTTP response details
 */
typedef void
(*TALER_MERCHANT_ProductDeleteCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Make a DELETE /products/$ID request to delete a product from our
 * inventory.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param product_id identifier of the product
 * @param cb function to call with the backend's deletion status
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_ProductDeleteHandle *
TALER_MERCHANT_product_delete (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *product_id,
  TALER_MERCHANT_ProductDeleteCallback cb,
  void *cb_cls);


/**
 * Cancel DELETE /products/$ID operation.
 *
 * @param pdh operation to cancel
 */
void
TALER_MERCHANT_product_delete_cancel (
  struct TALER_MERCHANT_ProductDeleteHandle *pdh);


/* ********************* /tokenfamilies ************************** */

/**
 * Handle for a GET /tokenfamilies/$SLUG operation.
 */
struct TALER_MERCHANT_TokenFamilyGetHandle;


/**
 * Response to GET /tokenfamilies/$SLUG operation.
 */
struct TALER_MERCHANT_TokenFamilyGetResponse
{
  /**
   * HTTP response details
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details depending on HTTP status.
   */
  union
  {
    /**
     * Details for #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * Identifier for the token family consisting of unreserved characters
       * according to RFC 3986.
       */
      const char *slug;

      /**
       * Human-readable name for the token family.
       */
      const char *name;

      /**
       * description of the token family
       */
      const char *description;

      /**
       * Optional map from IETF BCP 47 language tags to localized descriptions.
       */
      const json_t *description_i18n;

      /**
       * Additional data about the token family (such as expected_domains).
       */
      const json_t *extra_data;

      /**
       * Start time of the token family's validity period.
       */
      struct GNUNET_TIME_Timestamp valid_after;

      /**
       * End time of the token family's validity period.
       */
      struct GNUNET_TIME_Timestamp valid_before;

      /**
       * Validity duration of an issued token.
       */
      struct GNUNET_TIME_Relative duration;

      /**
       * Granularity of the validity periods of the token.
       */
      struct GNUNET_TIME_Relative validity_granularity;

      /**
       * Offset subtracted from the rounded start time to determine
       * the actual start time.
       */
      struct GNUNET_TIME_Relative start_offset;

      /**
       * Kind of token family, "subscription" or "discount".
       */
      const char *kind;

      /**
       * How many tokens have been issued for this family.
       */
      uint64_t issued;

      /**
       * How many tokens have been used for this family.
       */
      uint64_t used;
    } ok;

  } details;

};

/**
 * Cancel GET /tokenfamilies/$SLUG operation.
 *
 * @param handle operation to cancel
 */
void
TALER_MERCHANT_token_family_get_cancel (
  struct TALER_MERCHANT_TokenFamilyGetHandle *handle);


/**
 * Function called with the result of the GET /tokenfamilies/$SLUG operation.
 *
 * @param cls closure
 * @param pgr response details
 */
typedef void
(*TALER_MERCHANT_TokenFamilyGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_TokenFamilyGetResponse *pgr);

/**
 * Handle for a POST /tokenfamilies operation.
 */
struct TALER_MERCHANT_TokenFamiliesPostHandle;


/**
 * Function called with the result of the POST /tokenfamilies operation.
 *
 * @param cls closure
 * @param hr HTTP response details
 */
typedef void
(*TALER_MERCHANT_TokenFamiliesPostCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Make a POST /tokenfamilies request to add a token family to the
 * merchant instance.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param slug short, url-safe identifier for the token family
 * @param name human-readable name for the token family
 * @param description description of the token family
 * @param description_i18n Map from IETF BCP 47 language tags to localized descriptions
 * @param extra_data additional meta-data about the token family
 * @param valid_after when the token family becomes valid
 * @param valid_before when the token family expires
 * @param duration how long tokens issued by this token family are valid for
 * @param validity_granularity rounding duration of token family
 * @param start_offset time to subtract after rounding down to get
 *        the actual start time for each round
 * @param kind kind of token family, "subscription" or "discount"
 * @param cb function to call with the backend's result
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_TokenFamiliesPostHandle *
TALER_MERCHANT_token_families_post (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *slug,
  const char *name,
  const char *description,
  const json_t *description_i18n,
  const json_t *extra_data,
  struct GNUNET_TIME_Timestamp valid_after,
  struct GNUNET_TIME_Timestamp valid_before,
  struct GNUNET_TIME_Relative duration,
  struct GNUNET_TIME_Relative validity_granularity,
  struct GNUNET_TIME_Relative start_offset,
  const char *kind,
  TALER_MERCHANT_TokenFamiliesPostCallback cb,
  void *cb_cls);


/**
 * Cancel POST /tokenfamilies operation.
 *
 * @param handle operation to cancel
 */
void
TALER_MERCHANT_token_families_post_cancel (
  struct TALER_MERCHANT_TokenFamiliesPostHandle *handle);


/* FIXME: token_families_patch API is missing... */


/* ********************* /orders ************************** */


/**
 * Handle to a POST /private/orders operation
 */
struct TALER_MERCHANT_PostOrdersHandle;


/**
 * Possible details from a reply to POST /private/orders.
 */
struct TALER_MERCHANT_PostOrdersReply
{

  /**
   * HTTP response details. HTTP status code
   * determines what parts of @e details are valid.
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details of the reply, depending on the HTTP
   * status code.
   */
  union
  {

    /**
     * Details provided if the @e hr.http_status is
     * #MHD_HTTP_OK and the order was created.
     */
    struct
    {

      /**
       * order id of the newly created order
       */
      const char *order_id;

      /**
       * the claim token generated by the merchant,
       * (NULL if it was NOT generated).
       */
      const struct TALER_ClaimTokenP *token;

      /**
       * When will the order have to be paid?
       * Note: only available since protocol v21,
       * will be zero if server is older.
       */
      struct GNUNET_TIME_Timestamp pay_deadline;

    } ok;

    /**
     * Details provided if the @e hr.http_status is
     * #MHD_HTTP_GONE because a product was out of stock.
     */
    struct
    {
      /**
       * ID of the product of the order that is out of
       * stock.
       */
      const char *product_id;

      /**
       * How many units were requested by the order.
       */
      uint64_t requested_quantity;

      /**
       * Fractional component of the requested quantity in units of
       * 1/#TALER_AMOUNT_FRAC_BASE. Absent or zero when the request did not
       * include a fractional part.
       */
      uint32_t requested_quantity_frac;

      /**
       * How many units are actually still in stock.
       */
      uint64_t available_quantity;

      /**
       * Fractional component of the available quantity in units of
       * 1/#TALER_AMOUNT_FRAC_BASE.
       */
      uint32_t available_quantity_frac;

      /**
       * When does the backend expect the stock to be
       * restocked? 0 for unknown.
       */
      struct GNUNET_TIME_Timestamp restock_expected;

    } gone;

  } details;

};


/**
 * Callbacks of this type are used to serve the result of submitting a
 * POST /using-templates and POST /orders request to a merchant.
 *
 * @param cls closure
 * @param por response details
 */
typedef void
(*TALER_MERCHANT_PostOrdersCallback) (
  void *cls,
  const struct TALER_MERCHANT_PostOrdersReply *por);


/**
 * POST to /orders at the backend to setup an order and obtain
 * the order ID (which may have been set by the front-end).
 *
 * @param ctx execution context
 * @param backend_url URL of the backend
 * @param order basic information about this purchase, to be extended by the backend
 * @param refund_delay how long can refunds happen for this order; 0 to use
 *             absolute value from contract (or not allow refunds).
 * @param cb the callback to call when a reply for this request is available
 * @param cb_cls closure for @a cb
 * @return a handle for this request, NULL on error
 */
struct TALER_MERCHANT_PostOrdersHandle *
TALER_MERCHANT_orders_post (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const json_t *order,
  struct GNUNET_TIME_Relative refund_delay,
  TALER_MERCHANT_PostOrdersCallback cb,
  void *cb_cls);

/**
 * Information needed per product for constructing orders from
 * the inventory.
 */
struct TALER_MERCHANT_InventoryProduct
{

  /**
   * Identifier of the product.
   */
  char *product_id;

  /**
   * How many units of this product should be ordered.
   */
  uint64_t quantity;

  /**
   * Fractional component of the quantity in units of 1/1000000 of the
   * base value.
   */
  uint32_t quantity_frac;

  /**
   * Set to true if this product uses fractional quantity fields.
   */
  bool use_fractional_quantity;
};


/**
 * POST to /orders at the backend to setup an order and obtain
 * the order ID (which may have been set by the front-end).
 *
 * @param ctx execution context
 * @param backend_url URL of the backend
 * @param order basic information about this purchase, to be extended by the backend
 * @param refund_delay how long can refunds happen for this order; 0 to use
 *             absolute value from contract (or not allow refunds).
 * @param payment_target desired payment target identifier (to select merchant bank details)
 * @param inventory_products_length length of the @a inventory_products array
 * @param inventory_products products to add to the order from the inventory
 * @param uuids_length length of the @a uuids array
 * @param uuids array of UUIDs with locks on @a inventory_products
 * @param create_token whether to create a claim token
 * @param cb the callback to call when a reply for this request is available
 * @param cb_cls closure for @a cb
 * @return a handle for this request, NULL on error
 */
struct TALER_MERCHANT_PostOrdersHandle *
TALER_MERCHANT_orders_post2 (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const json_t *order,
  struct GNUNET_TIME_Relative refund_delay,
  const char *payment_target,
  unsigned int inventory_products_length,
  const struct TALER_MERCHANT_InventoryProduct inventory_products[],
  unsigned int uuids_length,
  const char *uuids[static uuids_length],
  bool create_token,
  TALER_MERCHANT_PostOrdersCallback cb,
  void *cb_cls);


/**
 * POST to /orders at the backend to setup an order and obtain
 * the order ID (which may have been set by the front-end).
 *
 * @param ctx execution context
 * @param backend_url URL of the backend
 * @param order basic information about this purchase, to be extended by the backend
 * @param session_id session ID to set for the order
 * @param refund_delay how long can refunds happen for this order; 0 to use
 *             absolute value from contract (or not allow refunds).
 * @param payment_target desired payment target identifier (to select merchant bank details)
 * @param inventory_products_length length of the @a inventory_products array
 * @param inventory_products products to add to the order from the inventory
 * @param uuids_length length of the @a uuids array
 * @param uuids array of UUIDs with locks on @a inventory_products
 * @param create_token whether to create a claim token
 * @param cb the callback to call when a reply for this request is available
 * @param cb_cls closure for @a cb
 * @return a handle for this request, NULL on error
 */
struct TALER_MERCHANT_PostOrdersHandle *
TALER_MERCHANT_orders_post3 (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const json_t *order,
  const char *session_id,
  struct GNUNET_TIME_Relative refund_delay,
  const char *payment_target,
  unsigned int inventory_products_length,
  const struct TALER_MERCHANT_InventoryProduct inventory_products[],
  unsigned int uuids_length,
  const char *uuids[static uuids_length],
  bool create_token,
  TALER_MERCHANT_PostOrdersCallback cb,
  void *cb_cls);


/**
 * Cancel a POST /orders request.  This function cannot be used
 * on a request handle if a response is already served for it.
 *
 * @param[in] po the proposal operation request handle
 */
void
TALER_MERCHANT_orders_post_cancel (
  struct TALER_MERCHANT_PostOrdersHandle *po);


/**
 * Handle for a GET /orders operation.
 */
struct TALER_MERCHANT_OrdersGetHandle;

/**
 * Individual order (minimal information returned via GET /orders).
 */
struct TALER_MERCHANT_OrderEntry
{
  /**
   * Order identifier.
   */
  const char *order_id;

  /**
   * Time when the order was created. Useful for filtering by
   * 'date' (in #TALER_MERCHANT_orders_get2()).
   */
  struct GNUNET_TIME_Timestamp timestamp;

  /**
   * Serial ID of the order. Useful for filtering by 'start_row'
   * (in #TALER_MERCHANT_orders_get2()).
   */
  uint64_t order_serial;

  /**
   * The amount of the order.
   */
  struct TALER_Amount amount;

  /**
   * The summary of the order.
   */
  const char *summary;

  /**
   * Whether it is possible to refund a part of the order still.
   */
  bool refundable;

  /**
   * Whether the order has been paid.
   */
  bool paid;

  /**
   * Total amount of refunds granted (but not necessarily
   * accepted by the wallet).  Only set if @e paid, otherwise
   * set to an invalid amount!
   */
  struct TALER_Amount refund_amount;

  /**
   * Total amount of refunds pending (wallet did not pick them up).
   * Only set if @e paid, otherwise set to an invalid amount!
   */
  struct TALER_Amount pending_refund_amount;

};


/**
 * Response for a GET /private/orders request.
 */
struct TALER_MERCHANT_OrdersGetResponse
{
  /**
   * HTTP response details.
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details depending on HTTP status.
   */
  union
  {
    /**
     * Details for #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * length of the @e orders array
       */
      unsigned int orders_length;

      /**
       * array of orders the requested instance has made
       */
      const struct TALER_MERCHANT_OrderEntry *orders;
    } ok;
  } details;

};


/**
 * Function called with the result of the GET /orders operation.
 *
 * @param cls closure
 * @param ogr response details
 */
typedef void
(*TALER_MERCHANT_OrdersGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_OrdersGetResponse *ogr);


/**
 * Make a GET /orders request.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param cb function to call with the backend's inventory information
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_OrdersGetHandle *
TALER_MERCHANT_orders_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  TALER_MERCHANT_OrdersGetCallback cb,
  void *cb_cls);


/**
 * Make a GET /orders request with filters.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param paid filter on payment status
 * @param refunded filter on refund status
 * @param wired filter on wire transfer status
 * @param date range limit by date
 * @param start_row range limit by order table row
 * @param delta range from which @a date and @a start_row apply, positive
 *              to return delta items after the given limit(s), negative to
 *              return delta items before the given limit(s)
 * @param timeout how long to wait (long polling) of zero results match the query
 * @param cb function to call with the backend's inventory information
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_OrdersGetHandle *
TALER_MERCHANT_orders_get2 (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  enum TALER_EXCHANGE_YesNoAll paid,
  enum TALER_EXCHANGE_YesNoAll refunded,
  enum TALER_EXCHANGE_YesNoAll wired,
  struct GNUNET_TIME_Timestamp date,
  uint64_t start_row,
  int64_t delta,
  struct GNUNET_TIME_Relative timeout,
  TALER_MERCHANT_OrdersGetCallback cb,
  void *cb_cls);


/**
 * Make a GET /orders request with more filters.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param paid filter on payment status
 * @param refunded filter on refund status
 * @param wired filter on wire transfer status
 * @param session_id filter by session ID
 * @param fulfillment_url filter by fulfillment URL
 * @param date range limit by date
 * @param start_row range limit by order table row
 * @param delta range from which @a date and @a start_row apply, positive
 *              to return delta items after the given limit(s), negative to
 *              return delta items before the given limit(s)
 * @param timeout how long to wait (long polling) of zero results match the query
 * @param cb function to call with the backend's inventory information
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_OrdersGetHandle *
TALER_MERCHANT_orders_get3 (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  enum TALER_EXCHANGE_YesNoAll paid,
  enum TALER_EXCHANGE_YesNoAll refunded,
  enum TALER_EXCHANGE_YesNoAll wired,
  const char *session_id,
  const char *fulfillment_url,
  struct GNUNET_TIME_Timestamp date,
  uint64_t start_row,
  int64_t delta,
  struct GNUNET_TIME_Relative timeout,
  TALER_MERCHANT_OrdersGetCallback cb,
  void *cb_cls);


/**
 * Cancel GET /orders operation.
 *
 * @param[in] pgh operation to cancel
 */
void
TALER_MERCHANT_orders_get_cancel (
  struct TALER_MERCHANT_OrdersGetHandle *pgh);


/**
 * Handle for a GET /orders/$ID operation. (Wallet's public endpoint,
 * not to be confused with the private endpoint for the merchant.)
 */
struct TALER_MERCHANT_OrderWalletGetHandle;


/**
 * Response to a GET /orders/$ID request.
 */
struct TALER_MERCHANT_OrderWalletGetResponse
{
  /**
   * Full HTTP response details.
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Response details depending on the HTTP status.
   */
  union
  {
    /**
     * Response details if the response code is #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * True if there is at least on refund on this payment.
       */
      bool refunded;

      /**
       * True if there are refunds waiting to be
       * obtained.
       */
      bool refund_pending;

      /**
       * Amount that was refunded, only set if
       * @e refunded is #GNUNET_YES.
       */
      struct TALER_Amount refund_amount;

    } ok;

    /**
     * Response if a payment is required from the client.
     */
    struct
    {

      /**
       * The URI that instructs the wallet to process
       * the payment.
       */
      const char *taler_pay_uri;

      /**
       * Equivalent order that this customer paid already, or NULL for none.
       */
      const char *already_paid_order_id;

    } payment_required;

  } details;
};


/**
 * Callback to process a GET /orders/$ID response
 *
 * @param cls closure
 * @param owgs HTTP response details
 */
typedef void
(*TALER_MERCHANT_OrderWalletGetCallback) (
  void *cls,
  const struct TALER_MERCHANT_OrderWalletGetResponse *owgs);


/**
 * Checks the status of a payment.  Issue a GET /orders/$ID request to the
 * backend.  The @a h_contract serves as identification of the wallet and is
 * used to authorize the request.
 *
 * @param ctx execution context
 * @param backend_url base URL of the merchant backend
 * @param order_id order id to identify the payment
 * @param h_contract hash of the contract to authenticate the wallet
 * @param timeout timeout to use in long polling (how long may the server wait to reply
 *        before generating an unpaid response). Note that this is just provided to
 *        the server, we as client will block until the response comes back or until
 *        #TALER_MERCHANT_wallet_order_get_cancel() is called.
 * @param session_id for which session should the payment status be checked. Use
 *        NULL to disregard sessions.
 * @param min_refund long poll for the service to approve a refund exceeding this value;
 *        use NULL to not wait for any refund (only for payment). Only makes sense
 *        with a non-zero @a timeout. Can be NULL.
 * @param await_refund_obtained long poll for the order's refunds to be
 *        picked up by the wallet.
 * @param cb callback which will work the response gotten from the backend
 * @param cb_cls closure to pass to @a cb
 * @return handle for this operation, NULL upon errors
 */
struct TALER_MERCHANT_OrderWalletGetHandle *
TALER_MERCHANT_wallet_order_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *order_id,
  const struct TALER_PrivateContractHashP *h_contract,
  struct GNUNET_TIME_Relative timeout,
  const char *session_id,
  const struct TALER_Amount *min_refund,
  bool await_refund_obtained,
  TALER_MERCHANT_OrderWalletGetCallback cb,
  void *cb_cls);

/**
 * Cancel a GET /orders/$ID request.
 *
 * @param[in] owgh handle to the request to be canceled
 */
void
TALER_MERCHANT_wallet_order_get_cancel (
  struct TALER_MERCHANT_OrderWalletGetHandle *owgh);


/**
 * Handle for a GET /private/orders/$ID operation (merchant's internal
 * API, not to be confused with the endpoint for wallets).
 */
struct TALER_MERCHANT_OrderMerchantGetHandle;


/**
 * Details about a wire transfer to the merchant related to the order.
 */
struct TALER_MERCHANT_WireTransfer
{
  /**
   * Base URL of the exchange that made the transfer.
   */
  const char *exchange_url;

  /**
   * When the transfer took place (note: may not be exact,
   * as the time at which the exchange initiated the transfer
   * may differ from the time the bank or the merchant observed).
   */
  struct GNUNET_TIME_Timestamp execution_time;

  /**
   * Wire transfer subject.
   */
  struct TALER_WireTransferIdentifierRawP wtid;

  /**
   * Total amount that was transferred.
   */
  struct TALER_Amount total_amount;

  /**
   * Whether this transfer was confirmed by the merchant using
   * the POST /transfers API, or whether it was merely claimed
   * by the exchange.
   */
  bool confirmed;
};


/**
 * Details about a failures returned by the exchange when
 * tracking wire transfers.
 */
struct TALER_MERCHANT_WireReport
{

  /**
   * Error code explaining the nature of the problem.
   */
  enum TALER_ErrorCode code;

  /**
   * Human-readable error description.
   */
  const char *hint;

  /**
   * Public key of the coin involved.
   */
  struct TALER_CoinSpendPublicKeyP coin_pub;

  /**
   * HTTP response data from the exchange (fields are MAY BE NULL or 0 if not
   * available).
   */
  struct TALER_EXCHANGE_HttpResponse hr;

};


/**
 * Detail returned by the merchant backend about refunds.
 */
struct TALER_MERCHANT_RefundOrderDetail
{

  /**
   * Human-readable reason given for the refund.
   */
  const char *reason;

  /**
   * Time when the refund was granted.
   */
  struct GNUNET_TIME_Timestamp refund_time;

  /**
   * Total amount that was refunded.
   */
  struct TALER_Amount refund_amount;

};


/**
 * Status of an order.
 */
enum TALER_MERCHANT_OrderStatusCode
{
  /**
   * The order was paid.
   */
  TALER_MERCHANT_OSC_PAID = 1,

  /**
  * The order was claimed but not yet paid.
  */
  TALER_MERCHANT_OSC_CLAIMED = 2,

  /**
   * The order was never paid or claimed.
   */
  TALER_MERCHANT_OSC_UNPAID = 3
};


/**
 * Details about the status of an order.
 */
struct TALER_MERCHANT_OrderStatusResponse
{
  /**
   * HTTP response details.
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details provided depending on the HTTP status code.
   */
  union
  {
    /**
     * Details provided if the HTTP status is #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * Status of the order.
       */
      enum TALER_MERCHANT_OrderStatusCode status;

      /**
       * Details depending on the payment status given in @e status.
       */
      union
      {

        /**
         * Details provided if @e status is #TALER_MERCHANT_OSC_PAID.
         */
        struct
        {
          /**
           * Amount that was refunded.
           */
          struct TALER_Amount refund_amount;

          /**
           * Amount that was deposited into our bank account,
           * excluding fees.
           */
          struct TALER_Amount deposit_total;

          /**
           * The full contract terms of the order.
           */
          const json_t *contract_terms;

          /**
           * Array of wire transfers made for this payment to the
           * merchant by the exchange. Of length @e wts_len.
           */
          struct TALER_MERCHANT_WireTransfer *wts;

          /**
           * Length of the @e wts array.
           */
          unsigned int wts_len;

          /**
           * Details returned by the merchant backend about refunds.
           * Of length @e refunds_len.
           */
          struct TALER_MERCHANT_RefundOrderDetail *refunds;

          /**
           * Length of the @e refunds array.
           */
          unsigned int refunds_len;

          /**
           * Error code encountered trying to contact the exchange
           * about the wire tracking, 0 for none.
           */
          enum TALER_ErrorCode exchange_ec;

          /**
           * HTTP status code encountered trying to contact the exchange
           * about the wire tracking, 0 for no error.
           */
          unsigned int exchange_hc;

          /**
           * true if there is at least on refund on this payment,
           * false if there are no refunds.
           */
          bool refunded;

          /**
           * true if refunds were approved that have not yet been obtained
           * by the wallet.
           */
          bool refund_pending;

          /**
           * true if the exchange paid the merchant for this order,
           * false if not.
           */
          bool wired;

          /**
           * Time of the last payment made on this order.
           * Only available if the server supports protocol
           * **v14** or higher, otherwise zero.
           */
          struct GNUNET_TIME_Timestamp last_payment;
        } paid;

        /**
         * Details provided if @e status is #TALER_MERCHANT_OSC_CLAIMED.
         */
        struct
        {

          /**
           * The full contract terms of the claimed order (including client nonce from claiming).
           */
          const json_t *contract_terms;

        } claimed;

        /**
         * Details provided if @e status is #TALER_MERCHANT_OSC_UNPAID.
         */
        struct
        {

          /**
           * URI that should be shown to the wallet to trigger a payment.
           */
          const char *taler_pay_uri;

          /**
           * Alternative order ID which was paid for already in the same session.
           * Only given if the same product was purchased before in the same session.
           * Otherwise NULL.
           */
          const char *already_paid_order_id;

          /**
           * Order summary.
           */
          const char *summary;

          /**
           * Time when the order was created.
           */
          struct GNUNET_TIME_Timestamp creation_time;

          /**
           * Total amount the order is about (amount to be paid by customer).
           */
          struct TALER_Amount contract_amount;

        } unpaid;

      } details;

    } ok;

  } details;
};


/**
 * Callback to process a GET /orders/$ID request
 *
 * @param cls closure
 * @param osr order status response details
 */
typedef void
(*TALER_MERCHANT_OrderMerchantGetCallback) (
  void *cls,
  const struct TALER_MERCHANT_OrderStatusResponse *osr);


/**
 * Checks the status of a payment.  Issue a GET /private/orders/$ID request to
 * the backend.
 *
 * @param ctx execution context
 * @param backend_url base URL of the merchant backend
 * @param order_id order id to identify the payment
 * @param session_id session id for the payment (or NULL if the check is not
 *                   bound to a session)
 * @param timeout timeout to use in long polling (how long may the server wait to reply
 *        before generating an unpaid response). Note that this is just provided to
 *        the server, we as client will block until the response comes back or until
 *        #TALER_MERCHANT_merchant_order_get_cancel() is called.
 * @param cb callback which will work the response gotten from the backend
 * @param cb_cls closure to pass to @a cb
 * @return handle for this operation, NULL upon errors
 */
struct TALER_MERCHANT_OrderMerchantGetHandle *
TALER_MERCHANT_merchant_order_get (struct GNUNET_CURL_Context *ctx,
                                   const char *backend_url,
                                   const char *order_id,
                                   const char *session_id,
                                   struct GNUNET_TIME_Relative timeout,
                                   TALER_MERCHANT_OrderMerchantGetCallback cb,
                                   void *cb_cls);


/**
 * Cancel a GET /private/orders/$ID request.
 *
 * @param[in] omgh handle to the request to be canceled
 */
void
TALER_MERCHANT_merchant_order_get_cancel (
  struct TALER_MERCHANT_OrderMerchantGetHandle *omgh);


/**
 * Handle for a DELETE /orders/$ID operation.
 */
struct TALER_MERCHANT_OrderDeleteHandle;


/**
 * Function called with the result of the DELETE /orders/$ID operation.
 *
 * @param cls closure
 * @param hr HTTP response details
 */
typedef void
(*TALER_MERCHANT_OrderDeleteCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Make a DELETE /orders/$ID request to delete a order from our
 * inventory.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param order_id identifier of the order
 * @param force force deletion of claimed (but unpaid) orders
 * @param cb function to call with the backend's deletion status
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_OrderDeleteHandle *
TALER_MERCHANT_order_delete (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *order_id,
  bool force,
  TALER_MERCHANT_OrderDeleteCallback cb,
  void *cb_cls);


/**
 * Cancel DELETE /orders/$ID operation.
 *
 * @param[in] odh operation to cancel
 */
void
TALER_MERCHANT_order_delete_cancel (
  struct TALER_MERCHANT_OrderDeleteHandle *odh);


/**
 * Handle to a POST /orders/$ID/claim handle
 */
struct TALER_MERCHANT_OrderClaimHandle;


/**
 * Response to a POST /orders/$ID/claim request.
 */
struct TALER_MERCHANT_OrderClaimResponse
{
  /**
   * HTTP response details
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details depending on HTTP status.
   */
  union
  {
    /**
     * Details for #MHD_HTTP_OK.
     */
    struct
    {
      /**
       * the details of the contract
       */
      const json_t *contract_terms;

      /**
       * merchant's signature over @e contract_terms (already verified)
       */
      struct TALER_MerchantSignatureP sig;

      /**
       * hash over @e contract_terms (computed client-side to verify @e sig)
       */
      struct TALER_PrivateContractHashP h_contract_terms;
    } ok;

  } details;
};

/**
 * Callback called to process a POST /orders/$ID/claim response.
 *
 * @param cls closure
 * @param ocr response details
 */
typedef void
(*TALER_MERCHANT_OrderClaimCallback) (
  void *cls,
  const struct TALER_MERCHANT_OrderClaimResponse *ocr);


/**
 * Calls the POST /orders/$ID/claim API at the backend.  That is,
 * retrieve the final contract terms including the client nonce.
 *
 * This is a PUBLIC API for wallets.
 *
 * @param ctx execution context
 * @param backend_url base URL of the merchant backend
 * @param order_id order id used to perform the lookup
 * @param nonce nonce to use to claim the proposal
 * @param claim_token the token used to verify the claim (NULL for none)
 * @param cb callback which will work the response gotten from the backend
 * @param cb_cls closure to pass to @a cb
 * @return handle for this handle, NULL upon errors
 */
struct TALER_MERCHANT_OrderClaimHandle *
TALER_MERCHANT_order_claim (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *order_id,
  const struct GNUNET_CRYPTO_EddsaPublicKey *nonce,
  const struct TALER_ClaimTokenP *claim_token,
  TALER_MERCHANT_OrderClaimCallback cb,
  void *cb_cls);


/**
 * Cancel a POST /order/$ID/claim request.
 *
 * @param[in] och handle to the request to be canceled
 */
void
TALER_MERCHANT_order_claim_cancel (struct TALER_MERCHANT_OrderClaimHandle *och);


/**
 * All the details about a token that are generated during issuance and
 * that may be needed for future operations on the coin.
 */
struct TALER_MERCHANT_PrivateTokenDetails
{

  /**
   * Master secret used to derive the private key from.
   */
  struct TALER_TokenUseMasterSecretP master;

  /**
   * Private key of the token.
   */
  struct TALER_TokenUsePrivateKeyP token_priv;

  /**
   * Public key of the token.
   */
  struct TALER_TokenUsePublicKeyP token_pub;

  /**
   * Public key of the token.
   */
  struct TALER_TokenUsePublicKeyHashP h_token_pub;

  /**
   * Blinded public key of the token.
   */
  struct TALER_TokenEnvelope envelope;

  /**
   * Value used to blind the key for the signature.
   */
  union GNUNET_CRYPTO_BlindingSecretP blinding_secret;

  /**
   * Inputs needed from the merchant for blind signing.
   */
  struct TALER_TokenUseMerchantValues blinding_inputs;

  /**
   * Token issue public key.
   */
  struct TALER_TokenIssuePublicKey issue_pub;

  /**
   * Unblinded token issue signature made by the merchant.
   */
  struct TALER_TokenIssueSignature issue_sig;

  /**
   * Blinded token issue signature made by the merchant.
   */
  struct TALER_BlindedTokenIssueSignature blinded_sig;

};

/**
 * @brief Handle to a POST /orders/$ID/pay operation at a merchant.  Note that
 * we use the same handle for interactions with frontends (API for wallets) or
 * backends (API for frontends).  The difference is that for the frontend API,
 * we need the private keys of the coins, while for the backend API we need
 * the public keys and signatures received from the wallet.
 */
struct TALER_MERCHANT_OrderPayHandle;


/**
 * Information returned in response to a payment.
 */
struct TALER_MERCHANT_PayResponse
{

  /**
   * General HTTP response details.
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details returned depending on @e hr.
   */
  union
  {

    /**
     * Details returned on success.
     */
    struct
    {

      /**
       * Signature affirming that the order was paid.
       */
      struct TALER_MerchantSignatureP merchant_sig;

      /**
       * Optional payment confirmation code returned by the service.
       */
      const char *pos_confirmation;

      /**
       * Array of tokens that were issued for the payment.
       */
      struct TALER_MERCHANT_OutputToken *tokens;

      /**
       * Length of the @e tokens array.
       */
      unsigned int num_tokens;

    } ok;

    // TODO: might want to return further details on errors,
    // especially refund signatures on double-pay conflict.

    struct
    {

      /**
       * Array of exchange URLs which had legal problems.
       */
      const char **exchanges;

      /**
       * Length of the @e exchanges array.
       */
      unsigned int num_exchanges;

    } unavailable_for_legal_reasons;

  } details;

};


/**
 * Callbacks of this type are used to serve the result of submitting a
 * POST /orders/$ID/pay request to a merchant.
 *
 * @param cls closure
 * @param pr HTTP response details
 */
typedef void
(*TALER_MERCHANT_OrderPayCallback) (
  void *cls,
  const struct TALER_MERCHANT_PayResponse *pr);


/**
 * Information we need from the frontend (ok, the frontend sends just JSON)
 * when forwarding a payment to the backend.
 */
struct TALER_MERCHANT_PaidCoin
{
  /**
   * Denomination key with which the coin is signed
   */
  struct TALER_DenominationPublicKey denom_pub;

  /**
   * Exchange’s unblinded signature of the coin
   */
  struct TALER_DenominationSignature denom_sig;

  /**
   * Overall value that coins of this @e denom_pub have.
   */
  struct TALER_Amount denom_value;

  /**
   * Coin's public key.
   */
  struct TALER_CoinSpendPublicKeyP coin_pub;

  /**
   * Coin's signature key.
   */
  struct TALER_CoinSpendSignatureP coin_sig;

  /**
   * Amount this coin contributes to (including fee).
   */
  struct TALER_Amount amount_with_fee;

  /**
   * Amount this coin contributes to (without fee).
   */
  struct TALER_Amount amount_without_fee;

  /**
   * What is the URL of the exchange that issued @a coin_pub?
   */
  const char *exchange_url;

};


/**
 * Information the frontend forwards to the backend to use a token for
 * an order. Note that this does not include the token use private key,
 * but only public keys and signatures.
 */
struct TALER_MERCHANT_UsedToken
{

  /**
   * Signature on TALER_TokenUseRequestPS made with the token use private key.
   */
  struct TALER_TokenUseSignatureP token_sig;

  /**
   * Public key of the token. This was blindly signed by the merchant
   * during the issuance and is now being revealed to the merchant.
   */
  struct TALER_TokenUsePublicKeyP token_pub;

  /**
   * Unblinded signature made by the token issue public key of the merchant.
   */
  struct TALER_TokenIssueSignature ub_sig;

  /**
   * Token issue public key associated with this token.
   */
  struct TALER_TokenIssuePublicKey issue_pub;

};


/**
 * Information the frontend forwards to the backend for an output token. The
 * blinded issue signature is set once the request return with an HTTP_OK.
 * This does not include the blinding secret or any other private information.
 */
struct TALER_MERCHANT_OutputToken
{

  /**
   * Token envelope.
   */
  struct TALER_TokenEnvelope envelope;

  /**
   * Blinded issue signature made by the merchant.
   */
  struct TALER_BlindedTokenIssueSignature blinded_sig;

};


/**
 * Pay a merchant.  API for frontends talking to backends. Here,
 * the frontend does not have the coin's private keys, but just
 * the public keys and signatures.
 *
 * This is a PUBLIC API, albeit in this form useful for the frontend,
 * in case the frontend is proxying the request.
 *
 * @param ctx execution context
 * @param merchant_url base URL of the merchant
 * @param order_id which order should be paid
 * @param session_id session to pay for, or NULL for none
 * @param wallet_data inputs from the wallet for the contract, NULL for none
 * @param num_coins length of the @a coins array
 * @param coins array of coins to pay with
 * @param num_tokens length of the @a tokens array
 * @param tokens array of tokens used
 * @param j_output_tokens json array of token envelopes, NULL for none
 * @param pay_cb the callback to call when a reply for this request is available
 * @param pay_cb_cls closure for @a pay_cb
 * @return a handle for this request
 */
struct TALER_MERCHANT_OrderPayHandle *
TALER_MERCHANT_order_pay_frontend (
  struct GNUNET_CURL_Context *ctx,
  const char *merchant_url,
  const char *order_id,
  const char *session_id,
  const json_t *wallet_data,
  unsigned int num_coins,
  const struct TALER_MERCHANT_PaidCoin coins[static num_coins],
  unsigned int num_tokens,
  const struct TALER_MERCHANT_UsedToken tokens[static num_tokens],
  json_t *j_output_tokens,
  TALER_MERCHANT_OrderPayCallback pay_cb,
  void *pay_cb_cls);


/**
 * Information we need from the wallet for each coin when doing the
 * payment.
 */
struct TALER_MERCHANT_PayCoin
{
  /**
   * Denomination key with which the coin is signed
   */
  struct TALER_DenominationPublicKey denom_pub;

  /**
   * Exchange’s unblinded signature of the coin
   */
  struct TALER_DenominationSignature denom_sig;

  /**
   * Overall value that coins of this @e denom_pub have.
   */
  struct TALER_Amount denom_value;

  /**
   * Coin's private key.
   */
  struct TALER_CoinSpendPrivateKeyP coin_priv;

  /**
   * Coin's age commitment. Might be NULL, if not applicable.
   */
  const struct TALER_AgeCommitmentHashP *h_age_commitment;

  /**
   * Amount this coin contributes to (including fee).
   */
  struct TALER_Amount amount_with_fee;

  /**
   * Amount this coin contributes to (without fee).
   */
  struct TALER_Amount amount_without_fee;

  /**
   * URL of the exchange that issued @e coin_priv.
   */
  const char *exchange_url;

};


/**
 * Information we need from the wallet to use a token for an order.
 */
struct TALER_MERCHANT_UseToken
{

  /**
   * Token use private key. We will derive the public key from this.
   */
  struct TALER_TokenUsePrivateKeyP token_priv;

  /**
   * Unblinded signature made by the token issue public key of the merchant.
   */
  struct TALER_TokenIssueSignature ub_sig;

  /**
   * Token issue public key associated with this token.
   */
  struct TALER_TokenIssuePublicKey issue_pub;

};


/**
 * Pay a merchant.  API for wallets that have the coin's private keys.
 *
 * This is a PUBLIC API for wallets.
 *
 * @param ctx execution context
 * @param merchant_url base URL of the merchant
 * @param session_id session to pay for, or NULL for none
 * @param h_contract hash of the contact of the merchant with the customer
 * @param choice_index index of the selected contract choice, -1 for none
 * @param amount total value of the contract to be paid to the merchant
 * @param max_fee maximum fee covered by the merchant (according to the contract)
 * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests)
 * @param merchant_sig signature from the merchant over the original contract
 * @param timestamp timestamp when the contract was finalized, must match approximately the current time of the merchant
 * @param refund_deadline date until which the merchant can issue a refund to the customer via the merchant (can be zero if refunds are not allowed)
 * @param pay_deadline maximum time limit to pay for this contract
 * @param h_wire hash of the merchant’s account details
 * @param order_id order id
 * @param num_coins number of coins used to pay
 * @param coins array of coins we use to pay
 * @param num_tokens number of tokens to used in this payment request
 * @param tokens array of tokens we use in this payment request
 * @param num_output_tokens length of the @a output_tokens array
 * @param output_tokens array of output tokens to be issued by the merchant
 * @param pay_cb the callback to call when a reply for this request is available
 * @param pay_cb_cls closure for @a pay_cb
 * @return a handle for this request
 */
struct TALER_MERCHANT_OrderPayHandle *
TALER_MERCHANT_order_pay (
  struct GNUNET_CURL_Context *ctx,
  const char *merchant_url,
  const char *session_id,
  const struct TALER_PrivateContractHashP *h_contract,
  int choice_index,
  const struct TALER_Amount *amount,
  const struct TALER_Amount *max_fee,
  const struct TALER_MerchantPublicKeyP *merchant_pub,
  const struct TALER_MerchantSignatureP *merchant_sig,
  struct GNUNET_TIME_Timestamp timestamp,
  struct GNUNET_TIME_Timestamp refund_deadline,
  struct GNUNET_TIME_Timestamp pay_deadline,
  const struct TALER_MerchantWireHashP *h_wire,
  const char *order_id,
  unsigned int num_coins,
  const struct TALER_MERCHANT_PayCoin coins[static num_coins],
  unsigned int num_tokens,
  const struct TALER_MERCHANT_UseToken tokens[static num_tokens],
  unsigned int num_output_tokens,
  const struct TALER_MERCHANT_OutputToken output_tokens[static num_output_tokens
  ],
  TALER_MERCHANT_OrderPayCallback pay_cb,
  void *pay_cb_cls);

/**
 * Cancel a POST /orders/$ID/pay request.  Note that if you cancel a request
 * like this, you have no assurance that the request has not yet been
 * forwarded to the merchant. Thus, the payment may still succeed or fail.
 * Re-issue the original /pay request to resume/retry and obtain a definitive
 * result, or refresh the coins involved to ensure that the merchant can no
 * longer complete the payment.
 *
 * @param oph the payment request handle
 */
void
TALER_MERCHANT_order_pay_cancel (struct TALER_MERCHANT_OrderPayHandle *oph);


/**
 * @brief Handle to a POST /orders/$ID/paid operation at a merchant.
 */
struct TALER_MERCHANT_OrderPaidHandle;

/**
 * Response to an /orders/$ID/paid request.
 */
struct TALER_MERCHANT_OrderPaidResponse
{
  /**
   * HTTP response details.
   */
  struct TALER_MERCHANT_HttpResponse hr;
  /**
   * HTTP-status code dependent details.
   */
  union
  {
    /**
     * Details on success.
     */
    struct
    {
      /**
       * Set to true if the order was paid but also
       * refunded.
       */
      bool refunded;
    } ok;
  } details;
};


/**
 * Callbacks of this type are used to serve the result of submitting a
 * POST /orders/$ID/paid request to a merchant.
 *
 * @param cls closure
 * @param opr response details
 */
typedef void
(*TALER_MERCHANT_OrderPaidCallback) (
  void *cls,
  const struct TALER_MERCHANT_OrderPaidResponse *opr);


/**
 * Send proof of payment to a merchant.
 *
 * This is a PUBLIC API, albeit in this form useful for the frontend,
 * in case the frontend is proxying the request.
 *
 * @param ctx execution context
 * @param merchant_url base URL of the merchant
 * @param order_id which order should be paid
 * @param session_id session to pay for, or NULL for none
 * @param h_contract_terms hash of the contract terms
 * @param wallet_data_hash inputs from the wallet for the contract, NULL for none; FIXME: this argument is not needed and should be removed!
 * @param merchant_sig signature from the merchant
 *        affirming payment, or NULL on errors
 * @param paid_cb the callback to call when a reply for this request is available
 * @param paid_cb_cls closure for @a paid_cb
 * @return a handle for this request
 */
struct TALER_MERCHANT_OrderPaidHandle *
TALER_MERCHANT_order_paid (
  struct GNUNET_CURL_Context *ctx,
  const char *merchant_url,
  const char *order_id,
  const char *session_id,
  const struct TALER_PrivateContractHashP *h_contract_terms,
  const struct GNUNET_HashCode *wallet_data_hash,
  const struct TALER_MerchantSignatureP *merchant_sig,
  TALER_MERCHANT_OrderPaidCallback paid_cb,
  void *paid_cb_cls);


/**
 * Cancel POST /orders/$ID/paid operation.
 *
 * @param oph operation to cancel
 */
void
TALER_MERCHANT_order_paid_cancel (
  struct TALER_MERCHANT_OrderPaidHandle *oph);


/**
 * Handle for an POST /orders/$ID/abort operation.
 */
struct TALER_MERCHANT_OrderAbortHandle;


/**
 * Entry in the array of refunded coins.
 */
struct TALER_MERCHANT_AbortedCoin
{
  /**
   * Exchange signature affirming the refund.
   */
  struct TALER_ExchangeSignatureP exchange_sig;

  /**
   * Exchange public key affirming the refund.
   */
  struct TALER_ExchangePublicKeyP exchange_pub;
};


/**
 * Response to an /orders/$ID/abort request.
 */
struct TALER_MERCHANT_AbortResponse
{
  /**
   * HTTP response details
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details depending on HTTP status code.
   */
  union
  {
    /**
     * Details for #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * public key of the merchant
       */
      const struct TALER_MerchantPublicKeyP *merchant_pub;

      /**
       * size of the @e aborts array
       */
      unsigned int num_aborts;

      /**
       * merchant signatures refunding coins
       */
      const struct TALER_MERCHANT_AbortedCoin *aborts;
    } ok;

  } details;
};


/**
 * Callbacks of this type are used to serve the result of submitting a
 * /orders/$ID/abort request to a merchant.
 *
 * @param cls closure
 * @param ar response details
 */
typedef void
(*TALER_MERCHANT_AbortCallback) (
  void *cls,
  const struct TALER_MERCHANT_AbortResponse *ar);


/**
 * Information we need from the wallet for each coin when aborting.
 */
struct TALER_MERCHANT_AbortCoin
{

  /**
   * Coin's public key.
   */
  struct TALER_CoinSpendPublicKeyP coin_pub;

  /**
   * Amount this coin contributes to (including fee).
   * FIXME: no longer needed since **v18**. Remove eventually!
   */
  struct TALER_Amount amount_with_fee;

  /**
   * URL of the exchange that issued @e coin_priv.
   */
  const char *exchange_url;

};

/**
 * Run a payment abort operation, asking for the payment to be aborted,
 * yieldingrefunds for coins that were previously spend on a payment that
 * failed to go through.
 *
 * This is a PUBLIC API for wallets.
 *
 * @param ctx execution context
 * @param merchant_url base URL of the merchant
 * @param order_id order to abort
 * @param h_contract hash of the contact of the merchant with the customer
 * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests)
 * @param num_coins number of coins used to pay
 * @param coins array of coins we use to pay
 * @param cb the callback to call when a reply for this request is available
 * @param cb_cls closure for @a cb
 * @return a handle for this request
 */
struct TALER_MERCHANT_OrderAbortHandle *
TALER_MERCHANT_order_abort (
  struct GNUNET_CURL_Context *ctx,
  const char *merchant_url,
  const char *order_id,
  const struct TALER_MerchantPublicKeyP *merchant_pub,
  const struct TALER_PrivateContractHashP *h_contract,
  unsigned int num_coins,
  const struct TALER_MERCHANT_AbortCoin coins[static num_coins],
  TALER_MERCHANT_AbortCallback cb,
  void *cb_cls);


/**
 * Cancel a POST /orders/$ID/abort request.  Note that if you cancel a request
 * like this, you have no assurance that the request has not yet been
 * forwarded to the merchant.
 *
 * @param oah the abort request handle
 */
void
TALER_MERCHANT_order_abort_cancel (struct TALER_MERCHANT_OrderAbortHandle *oah);


/**
 * Handle for an PATCH /orders/$ID/forget operation.
 */
struct TALER_MERCHANT_OrderForgetHandle;


/**
 * Callbacks of this type are used to serve the result of submitting a
 * /orders/$ID/forget request to a merchant.
 *
 * @param cls closure
 * @param hr HTTP response details
 */
typedef void
(*TALER_MERCHANT_ForgetCallback) (
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Run an order forget operation, which forgets certain fields in an order's
 * contract terms without changing the hash of the contract terms.
 *
 * @param ctx execution context.
 * @param merchant_url base URL of the merchant.
 * @param order_id order to forget.
 * @param fields_length length of @e fields.
 * @param fields the fields in the contract terms to forget.
 * @param cb the callback to call when a reply for this request is available.
 * @param cb_cls closure for @a cb.
 * @return a handle for this request.
 */
struct TALER_MERCHANT_OrderForgetHandle *
TALER_MERCHANT_order_forget (
  struct GNUNET_CURL_Context *ctx,
  const char *merchant_url,
  const char *order_id,
  unsigned int fields_length,
  const char *fields[static fields_length],
  TALER_MERCHANT_ForgetCallback cb,
  void *cb_cls);


/**
 * Cancel a PATCH /orders/$ID/forget request.  Note that if you cancel a request
 * like this, you have no assurance that the request has not yet been
 * forwarded to the merchant.
 *
 * @param[in] ofh the forget request handle
 */
void
TALER_MERCHANT_order_forget_cancel (
  struct TALER_MERCHANT_OrderForgetHandle *ofh);


/**
 * Handle for a POST /orders/ID/refund operation.
 */
struct TALER_MERCHANT_OrderRefundHandle;


/**
 * Response to a POST /orders/$ID/refund request
 */
struct TALER_MERCHANT_RefundResponse
{
  /**
   * HTTP response details this request
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details depending on HTTP status.
   */
  union
  {
    /**
     * Details if status is #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * the refund uri offered to the wallet
       */
      const char *taler_refund_uri;

      /**
       * Hash of the contract a wallet may need to authorize obtaining the HTTP
       * response.
       */
      struct TALER_PrivateContractHashP h_contract;
    } ok;
  } details;
};


/**
 * Callback to process a POST /orders/$ID/refund request
 *
 * @param cls closure
 * @param rr response details this request
 */
typedef void
(*TALER_MERCHANT_RefundCallback) (
  void *cls,
  const struct TALER_MERCHANT_RefundResponse *rr);


/**
 * Increase the refund granted for an order
 *
 * @param ctx the CURL context used to connect to the backend
 * @param backend_url backend's base URL, including final "/"
 * @param order_id id of the order whose refund is to be increased
 * @param refund amount to which increase the refund
 * @param reason human-readable reason justifying the refund
 * @param cb callback processing the response from /refund
 * @param cb_cls closure for cb
 */
struct TALER_MERCHANT_OrderRefundHandle *
TALER_MERCHANT_post_order_refund (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *order_id,
  const struct TALER_Amount *refund,
  const char *reason,
  TALER_MERCHANT_RefundCallback cb,
  void *cb_cls);

/**
 * Cancel a POST /refund request.
 *
 * @param orh the refund increasing operation to cancel
 */
void
TALER_MERCHANT_post_order_refund_cancel (
  struct TALER_MERCHANT_OrderRefundHandle *orh);


/**
 * Handle for a (public) POST /orders/ID/refund operation.
 */
struct TALER_MERCHANT_WalletOrderRefundHandle;


/**
 * Detail about a refund lookup result.
 */
struct TALER_MERCHANT_RefundDetail
{

  /**
   * Exchange response details.  Full details are only included
   * upon failure (HTTP status is not #MHD_HTTP_OK).
   */
  struct TALER_EXCHANGE_HttpResponse hr;

  /**
   * Coin this detail is about.
   */
  struct TALER_CoinSpendPublicKeyP coin_pub;

  /**
   * Refund transaction ID used.
   */
  uint64_t rtransaction_id;

  /**
   * Amount to be refunded for this coin.
   */
  struct TALER_Amount refund_amount;

  /**
   * Details depending on exchange HTTP status.
   */
  union
  {
    /**
     * Details if exchange status is #MHD_HTTP_OK.
     */
    struct
    {
      /**
       * Public key of the exchange affirming the refund,
       * only valid if the @e hr http_status is #MHD_HTTP_OK.
       */
      struct TALER_ExchangePublicKeyP exchange_pub;

      /**
       * Signature of the exchange affirming the refund,
       * only valid if the @e hr http_status is #MHD_HTTP_OK.
       */
      struct TALER_ExchangeSignatureP exchange_sig;
    } ok;
  } details;
};


/**
 * Response to a POST /orders/$ID/refund request
 * for wallet API.
 */
struct TALER_MERCHANT_WalletRefundResponse
{
  /**
   * HTTP response details this request
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details depending on HTTP status.
   */
  union
  {
    /**
     * Details if status is #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * Total amount of the refund that was granted
       */
      struct TALER_Amount refund_amount;

      /**
       * public key of the merchant signing the @e refunds
       */
      struct TALER_MerchantPublicKeyP merchant_pub;

      /**
       * array with details about the refunds obtained
       */
      const struct TALER_MERCHANT_RefundDetail *refunds;

      /**
       * length of the @e refunds array
       */
      unsigned int refunds_length;
    } ok;
  } details;
};


/**
 * Callback to process a (public) POST /orders/ID/refund request
 *
 * @param cls closure
 * @param wrr HTTP response details
 */
typedef void
(*TALER_MERCHANT_WalletRefundCallback) (
  void *cls,
  const struct TALER_MERCHANT_WalletRefundResponse *wrr);


/**
 * Obtain the refunds that have been granted for an order.
 *
 * @param ctx the CURL context used to connect to the backend
 * @param backend_url backend's base URL, including final "/"
 * @param order_id id of the order whose refund is to be increased
 * @param h_contract_terms hash of the contract terms of the order
 * @param cb callback processing the response from /refund
 * @param cb_cls closure for cb
 */
struct TALER_MERCHANT_WalletOrderRefundHandle *
TALER_MERCHANT_wallet_post_order_refund (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *order_id,
  const struct TALER_PrivateContractHashP *h_contract_terms,
  TALER_MERCHANT_WalletRefundCallback cb,
  void *cb_cls);

/**
 * Cancel a (public) POST /refund request.
 *
 * @param orh the refund operation to cancel
 */
void
TALER_MERCHANT_wallet_post_order_refund_cancel (
  struct TALER_MERCHANT_WalletOrderRefundHandle *orh);


/* ********************* /transfers *********************** */

/**
 * @brief Handle to a POST /transfers operation at a merchant's backend.
 */
struct TALER_MERCHANT_PostTransfersHandle;


/**
 * @brief Response to a POST /transfers operation from a merchant's backend.
 */
struct TALER_MERCHANT_PostTransfersResponse
{
  /**
   * HTTP response details
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details depending on HTTP status.
   */
  union
  {

    /**
     * Details if we got an #MHD_HTTP_BAD_GATEWAY.
     */
    struct
    {
      /**
       * HTTP status of the exchange (or 0 if not available).
       */
      unsigned int exchange_http_status;

      /**
       * Error code of the exchange (or TALER_EC_NONE if not available).
       */
      enum TALER_ErrorCode exchange_ec;

    } bad_gateway;

  } details;

};


/**
 * Callbacks of this type are used to work the result of submitting a
 * POST /transfers request to a merchant
 *
 * @param cls closure
 * @param ptr response details
 */
typedef void
(*TALER_MERCHANT_PostTransfersCallback) (
  void *cls,
  const struct TALER_MERCHANT_PostTransfersResponse *ptr);


/**
 * Request backend to remember that we received the given
 * wire transfer and to request details about the aggregated
 * transactions from the exchange.
 *
 * @param ctx execution context
 * @param backend_url base URL of the backend
 * @param credit_amount how much money did we receive (without wire fee)
 * @param wtid base32 string indicating a wtid
 * @param payto_uri which account was credited by the wire transfer
 * @param exchange_url what is the URL of the exchange that made the transfer
 * @param cb the callback to call when a reply for this request is available
 * @param cls closure for @a cb
 * @return a handle for this request
 */
struct TALER_MERCHANT_PostTransfersHandle *
TALER_MERCHANT_transfers_post (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const struct TALER_Amount *credit_amount,
  const struct TALER_WireTransferIdentifierRawP *wtid,
  struct TALER_FullPayto payto_uri,
  const char *exchange_url,
  TALER_MERCHANT_PostTransfersCallback cb,
  void *cls);


/**
 * Cancel a POST /transfers request.  This function cannot be used
 * on a request handle if a response is already served for it.
 *
 * @param pth the operation to cancel
 */
void
TALER_MERCHANT_transfers_post_cancel (
  struct TALER_MERCHANT_PostTransfersHandle *pth);


/**
 * Handle for a DELETE /transfers/ID operation.
 */
struct TALER_MERCHANT_TransferDeleteHandle;


/**
 * Function called with the result of the DELETE /transfers/$ID operation.
 *
 * @param cls closure
 * @param hr HTTP response details
 */
typedef void
(*TALER_MERCHANT_TransferDeleteCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Delete an incoming wire transfer at an instance of a backend. This
 * will only succeed if the exchange did not respond to the inquiry
 * about the transfer.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend (top-level "default" instance
 *                    or base URL of an instance if @a instance_id is NULL)
 * @param wire_transfer_serial unique number that identifies the transfer
 * @param td_cb function to call with the backend's result
 * @param td_cb_cls closure for @a td_cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_TransferDeleteHandle *
TALER_MERCHANT_transfer_delete (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  uint64_t wire_transfer_serial,
  TALER_MERCHANT_TransferDeleteCallback td_cb,
  void *td_cb_cls);


/**
 * Cancel deletion operation. Note that the operation may still
 * succeed.
 *
 * @param tdh operation to cancel
 */
void
TALER_MERCHANT_transfer_delete_cancel (
  struct TALER_MERCHANT_TransferDeleteHandle *tdh);


/**
 * @brief Handle to a GET /transfers operation at a merchant's backend.
 */
struct TALER_MERCHANT_GetTransfersHandle;

/**
 * Information about the _total_ amount that was paid back
 * by the exchange for a given h_contract_terms, by _one_ wire
 * transfer.
 */
struct TALER_MERCHANT_TransferData
{

  /**
   * Total amount wired by the exchange (without wire fee)
   */
  struct TALER_Amount credit_amount;

  /**
   * Wire transfer identifier used.
   */
  struct TALER_WireTransferIdentifierRawP wtid;

  /**
   * URI of the target account.
   */
  struct TALER_FullPayto payto_uri;

  /**
   * URL of the exchange that made the transfer.
   */
  const char *exchange_url;

  /**
   * Serial number of the credit operation in the merchant backend.
   * Needed, for example, to delete the transfer using
   * #TALER_MERCHANT_transfer_delete().
   */
  uint64_t credit_serial;

  /**
   * Time of the wire transfer, based on when we received
   * a confirmation for the wire transfer.
   */
  struct GNUNET_TIME_Timestamp execution_time;

  /**
   * True if this wire transfer was expected.
   */
  bool expected;

};


/**
 * Response from a GET /transfers request.
 */
struct TALER_MERCHANT_GetTransfersResponse
{
  /**
   * HTTP response details
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details depending on HTTP status.
   */
  union
  {

    /**
     * Details for status #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * length of the @e transfers array
       */
      unsigned int transfers_length;

      /**
       * array with details about the transfers we received
       */
      const struct TALER_MERCHANT_TransferData *transfers;
    } ok;
  } details;
};


/**
 * Callbacks of this type are used to work the result of submitting a
 * GET /transfers request to a merchant
 *
 * @param cls closure
 * @param gtr HTTP response details
 */
typedef void
(*TALER_MERCHANT_GetTransfersCallback) (
  void *cls,
  const struct TALER_MERCHANT_GetTransfersResponse *gtr);


/**
 * Request backend to return list of all wire transfers that
 * we received.
 *
 * @param ctx execution context
 * @param backend_url base URL of the backend
 * @param payto_uri filter by this credit account of the merchant
 * @param before limit to transactions before this timestamp, use
 *                 #GNUNET_TIME_UNIT_FOREVER_ABS to not filter by @a before
 * @param after limit to transactions after this timestamp, use
 *                 #GNUNET_TIME_UNIT_ZERO_ABS to not filter by @a after
 * @param limit return at most this number of results; negative to descend in execution time
 * @param offset start at this "credit serial" number (exclusive)
 * @param expected filter results by expectation status
 * @param cb the callback to call when a reply for this request is available
 * @param cb_cls closure for @a cb
 * @return a handle for this request
 */
struct TALER_MERCHANT_GetTransfersHandle *
TALER_MERCHANT_transfers_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  struct TALER_FullPayto payto_uri,
  const struct GNUNET_TIME_Timestamp before,
  const struct GNUNET_TIME_Timestamp after,
  int64_t limit,
  uint64_t offset,
  enum TALER_EXCHANGE_YesNoAll expected,
  TALER_MERCHANT_GetTransfersCallback cb,
  void *cb_cls);


/**
 * Cancel a POST /transfers request.  This function cannot be used
 * on a request handle if a response is already served for it.
 *
 * @param gth the operation to cancel
 */
void
TALER_MERCHANT_transfers_get_cancel (
  struct TALER_MERCHANT_GetTransfersHandle *gth);


/* ********************* /kyc ************************** */

/**
 * Handle for getting the KYC status of instance(s).
 */
struct TALER_MERCHANT_KycGetHandle;


/**
 * Information about KYC actions the merchant still must perform.
 */
struct TALER_MERCHANT_AccountKycRedirectDetail
{

  /**
   * Access token the user needs to start a KYC process,
   * all zero if a KYC auth transfer must be made first.
   */
  struct TALER_AccountAccessTokenP access_token;

  /**
   * Base URL of the exchange this is about.
   */
  const char *exchange_url;

  /**
   * Our bank wire account this is about.
   */
  struct TALER_FullPayto payto_uri;

  /**
   * Array of length @e limits_array with (exposed) limits that apply to the
   * account.
   */
  const struct TALER_EXCHANGE_AccountLimit *limits;

  /**
   * Array of payto://-URIs with instructions for wire
   * transfers to perform a KYC auth wire transfer for
   * the given account. Needed if @e kyc_url is NULL
   * and @e limits are to be passed.
   */
  struct TALER_FullPayto *payto_kycauths;

  /**
   * Length of the @e limits array.
   */
  unsigned int limits_length;

  /**
   * Length of the @e payto_kycauths array.
   */
  unsigned int pkycauth_length;

  /**
   * HTTP status code returned by the exchange when we asked for
   * information about the KYC status.
   * 0 if there was no response at all.
   */
  unsigned int exchange_http_status;

  /**
   * Error code indicating errors the exchange
   * returned, or #TALER_EC_NONE for none.
   */
  enum TALER_ErrorCode exchange_code;

  /**
   * Set to true if @e access_token was not given.
   */
  bool no_access_token;

  /**
   * Set to true if the merchant backend could not
   * get the exchanges ``/keys`` and thus could not
   * determine default limits or determine an
   * @e auth_conflict.
   */
  bool no_keys;

  /**
   * Set to true if the given account cannot to KYC at the given exchange
   * because no wire method exists that could be used to do the KYC auth wire
   * transfer.
   */
  bool auth_conflict;
};


/**
 * Details in a response to a GET /kyc request.
 */
struct TALER_MERCHANT_KycResponse
{
  /**
   * HTTP response details.
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Response details depending on the HTTP status.
   */
  union
  {
    /**
     * Information returned if the status was #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * Array with information about KYC actions the merchant may perform.
       */
      struct TALER_MERCHANT_AccountKycRedirectDetail *kycs;

      /**
       * Length of the @e pending_kycs array.
       */
      unsigned int kycs_length;

    } ok;

  } details;

};


/**
 * Callback to with a response from a GET [/private]/kyc request
 *
 * @param cls closure
 * @param kr response details
 */
typedef void
(*TALER_MERCHANT_KycGetCallback) (
  void *cls,
  const struct TALER_MERCHANT_KycResponse *kr);


/**
 * Issue a GET /private/kycs/$KYC_ID (private variant) request to the backend.
 * Returns KYC status of bank accounts.
 *
 * @param ctx execution context
 * @param backend_url base URL of the merchant backend
 * @param h_wire which bank account to query, NULL for all
 * @param exchange_url which exchange to query, NULL for all
 * @param lpt target for long polling
 * @param timeout how long to wait for an answer, including possibly long polling for the desired @a lpt status;
 *    note that when pulling for multiple accounts, any
 *    account reaching this status will cause the
 *    response to be returned
 * @param cb function to call with the result
 * @param cb_cls closure for @a cb
 * @return handle for this operation, NULL upon errors
 */
struct TALER_MERCHANT_KycGetHandle *
TALER_MERCHANT_kyc_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const struct TALER_MerchantWireHashP *h_wire,
  const char *exchange_url,
  enum TALER_EXCHANGE_KycLongPollTarget lpt,
  struct GNUNET_TIME_Relative timeout,
  TALER_MERCHANT_KycGetCallback cb,
  void *cb_cls);


/**
 * Issue a GET /management/instances/$INSTANCE/kyc request to the backend.
 * Returns KYC status of bank accounts.
 *
 * @param ctx execution context
 * @param backend_url base URL of the merchant backend
 * @param instance_id specific instance to query
 * @param h_wire which bank account to query, NULL for all
 * @param exchange_url which exchange to query, NULL for all
 * @param lpt target for long polling
 * @param timeout how long to wait for a reply
 * @param cb function to call with the result
 * @param cb_cls closure for @a cb
 * @return handle for this operation, NULL upon errors
 */
struct TALER_MERCHANT_KycGetHandle *
TALER_MERCHANT_management_kyc_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *instance_id,
  const struct TALER_MerchantWireHashP *h_wire,
  const char *exchange_url,
  enum TALER_EXCHANGE_KycLongPollTarget lpt,
  struct GNUNET_TIME_Relative timeout,
  TALER_MERCHANT_KycGetCallback cb,
  void *cb_cls);


/**
 * Cancel a GET [/private]/kyc/$KYC_ID request.
 *
 * @param kyc handle to the request to be canceled
 */
void
TALER_MERCHANT_kyc_get_cancel (
  struct TALER_MERCHANT_KycGetHandle *kyc);


/* ********************* /otp-devices *********************** */


/**
 * Handle for a GET /otp-devices operation.
 */
struct TALER_MERCHANT_OtpDevicesGetHandle;

/**
 * Individual OTP device (minimal information
 * returned via GET /otp-devices).
 */
struct TALER_MERCHANT_OtpDeviceEntry
{
  /**
   * OTP device identifier.
   */
  const char *otp_device_id;

  /**
   * OTP device description.
   */
  const char *device_description;

};


/**
 * Response to a GET /otp-devices operation.
 */
struct TALER_MERCHANT_OtpDevicesGetResponse
{
  /**
   * HTTP response details
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details depending on status.
   */
  union
  {
    /**
     * Details if status is #MHD_HTTP_OK.
     */
    struct
    {
      /**
       * length of the @e otp_devices array
       */
      unsigned int otp_devices_length;

      /**
       * array of otp_devices the requested instance offers
       */
      const struct TALER_MERCHANT_OtpDeviceEntry *otp_devices;
    } ok;
  } details;
};


/**
 * Function called with the result of the GET /otp-devices operation.
 *
 * @param cls closure
 * @param tgr response details
 */
typedef void
(*TALER_MERCHANT_OtpDevicesGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_OtpDevicesGetResponse *tgr);


/**
 * Make a GET /otp-devices request.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param cb function to call with the backend information
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_OtpDevicesGetHandle *
TALER_MERCHANT_otp_devices_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  TALER_MERCHANT_OtpDevicesGetCallback cb,
  void *cb_cls);


/**
 * Cancel GET /otp-devices operation.
 *
 * @param tgh operation to cancel
 */
void
TALER_MERCHANT_otp_devices_get_cancel (
  struct TALER_MERCHANT_OtpDevicesGetHandle *tgh);


/**
 * Handle for a GET /otp-device/$ID operation. Gets details
 * about a single otp_device. Do not confused with a
 * `struct TALER_MERCHANT_OtpDevicesGetHandle`, which
 * obtains a list of all otp_devices.
 */
struct TALER_MERCHANT_OtpDeviceGetHandle;


/**
 * Details in a response to a GET /otp-devices request.
 */
struct TALER_MERCHANT_OtpDeviceGetResponse
{
  /**
   * HTTP response details.
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Response details depending on the HTTP status.
   */
  union
  {
    /**
     * Information returned if the status was #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * description of the otp_device
       */
      const char *otp_device_description;

      /**
       * POS confirmation text with OTP codes that
       * would be returned for a purchase over the
       * amount given in the query for the respective
       * time and algorithm. NULL if the confirmation
       * could not be computed based on the query and
       * OTP algorithm.
       */
      const char *otp_code;

      /**
       * current counter.
       */
      uint64_t otp_ctr;

      /**
       * OTP algorithm used.
       */
      enum TALER_MerchantConfirmationAlgorithm otp_alg;

      /**
       * Timestamp in second used to compute
       * @e otp_code.
       */
      uint64_t otp_timestamp_s;

    } ok;

  } details;

};


/**
 * Function called with the result of the GET /otp-device/$ID operation.
 *
 * @param cls closure
 * @param tgr HTTP response details
 */
typedef void
(*TALER_MERCHANT_OtpDeviceGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_OtpDeviceGetResponse *tgr);


/**
 * Make a GET /otp-device/$ID request to get details about an
 * individual OTP device.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param otp_device_id identifier of the otp_device to inquire about
 * @param cb function to call with the backend's otp_device information
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_OtpDeviceGetHandle *
TALER_MERCHANT_otp_device_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *otp_device_id,
  TALER_MERCHANT_OtpDeviceGetCallback cb,
  void *cb_cls);


/**
 * Cancel GET /otp-devices/$ID operation.
 *
 * @param tgh operation to cancel
 */
void
TALER_MERCHANT_otp_device_get_cancel (
  struct TALER_MERCHANT_OtpDeviceGetHandle *tgh);


/**
 * Handle for a POST /otp-devices operation.
 */
struct TALER_MERCHANT_OtpDevicesPostHandle;


/**
 * Function called with the result of the POST /otp-devices operation.
 *
 * @param cls closure
 * @param hr HTTP response details
 */
typedef void
(*TALER_MERCHANT_OtpDevicesPostCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Make a POST /otp-devices request to add an OTP device
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param otp_id identifier to use for the OTP device
 * @param otp_device_description description of the OTP device
 * @param otp_key key of the OTP device
 * @param otp_alg OTP algorithm used
 * @param otp_ctr counter for counter-based OTP
 * @param cb function to call with the backend's result
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_OtpDevicesPostHandle *
TALER_MERCHANT_otp_devices_post (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *otp_id,
  const char *otp_device_description,
  const char *otp_key,
  enum TALER_MerchantConfirmationAlgorithm otp_alg,
  uint64_t otp_ctr,
  TALER_MERCHANT_OtpDevicesPostCallback cb,
  void *cb_cls);


/**
 * Cancel POST /otp-devices operation.
 *
 * @param[in] tph operation to cancel
 */
void
TALER_MERCHANT_otp_devices_post_cancel (
  struct TALER_MERCHANT_OtpDevicesPostHandle *tph);


/**
 * Handle for a PATCH /otp-device operation.
 */
struct TALER_MERCHANT_OtpDevicePatchHandle;


/**
 * Function called with the result of the PATCH /otp-device operation.
 *
 * @param cls closure
 * @param hr HTTP response details
 */
typedef void
(*TALER_MERCHANT_OtpDevicePatchCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Make a PATCH /otp-device request to update OTP device details
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param otp_id identifier to use for the OTP device; the OTP device must exist,
 *                    or the transaction will fail with a #MHD_HTTP_NOT_FOUND
 *                    HTTP status code
 * @param otp_device_description description of the otp_device
 * @param otp_key key of the OTP device
 * @param otp_alg OTP algorithm used
 * @param otp_ctr counter for counter-based OTP
 * @param cb function to call with the backend's result
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_OtpDevicePatchHandle *
TALER_MERCHANT_otp_device_patch (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *otp_id,
  const char *otp_device_description,
  const char *otp_key,
  enum TALER_MerchantConfirmationAlgorithm otp_alg,
  uint64_t otp_ctr,
  TALER_MERCHANT_OtpDevicePatchCallback cb,
  void *cb_cls);


/**
 * Cancel PATCH /otp-device operation.
 *
 * @param[in] tph operation to cancel
 */
void
TALER_MERCHANT_otp_device_patch_cancel (
  struct TALER_MERCHANT_OtpDevicePatchHandle *tph);


/**
 * Handle for a DELETE /otp-device/$ID operation.
 */
struct TALER_MERCHANT_OtpDeviceDeleteHandle;


/**
 * Function called with the result of the DELETE /otp-device/$ID operation.
 *
 * @param cls closure
 * @param hr HTTP response details
 */
typedef void
(*TALER_MERCHANT_OtpDeviceDeleteCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Make a DELETE /otp-device/$ID request to delete an OTP device.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param otp_device_id identifier of the OTP device
 * @param cb function to call with the backend's deletion status
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_OtpDeviceDeleteHandle *
TALER_MERCHANT_otp_device_delete (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *otp_device_id,
  TALER_MERCHANT_OtpDeviceDeleteCallback cb,
  void *cb_cls);


/**
 * Cancel DELETE /otp-device/$ID operation.
 *
 * @param[in] tdh operation to cancel
 */
void
TALER_MERCHANT_otp_device_delete_cancel (
  struct TALER_MERCHANT_OtpDeviceDeleteHandle *tdh);


/* ********************* /units *********************** */

struct TALER_MERCHANT_UnitEntry
{
  const char *unit;
  const char *unit_name_long;
  const char *unit_name_short;
  const json_t *unit_name_long_i18n;
  const json_t *unit_name_short_i18n;
  bool unit_allow_fraction;
  uint32_t unit_precision_level;
  bool unit_active;
  bool unit_builtin;
};

struct TALER_MERCHANT_UnitsGetResponse
{
  struct TALER_MERCHANT_HttpResponse hr;
  union
  {
    struct
    {
      struct TALER_MERCHANT_UnitEntry *units;
      unsigned int units_length;
    } ok;
  } details;
};

struct TALER_MERCHANT_UnitGetResponse
{
  struct TALER_MERCHANT_HttpResponse hr;
  union
  {
    struct
    {
      struct TALER_MERCHANT_UnitEntry unit;
    } ok;
  } details;
};

typedef void
(*TALER_MERCHANT_UnitsGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_UnitsGetResponse *ugr);

typedef void
(*TALER_MERCHANT_UnitGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_UnitGetResponse *ugr);

typedef void
(*TALER_MERCHANT_UnitsPostCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);

typedef void
(*TALER_MERCHANT_UnitPatchCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);

typedef void
(*TALER_MERCHANT_UnitDeleteCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);

struct TALER_MERCHANT_UnitsGetHandle;
struct TALER_MERCHANT_UnitGetHandle;
struct TALER_MERCHANT_UnitsPostHandle;
struct TALER_MERCHANT_UnitPatchHandle;
struct TALER_MERCHANT_UnitDeleteHandle;

struct TALER_MERCHANT_UnitsGetHandle *
TALER_MERCHANT_units_get (struct GNUNET_CURL_Context *ctx,
                          const char *backend_url,
                          TALER_MERCHANT_UnitsGetCallback cb,
                          void *cb_cls);

void
TALER_MERCHANT_units_get_cancel (
  struct TALER_MERCHANT_UnitsGetHandle *ugh);

struct TALER_MERCHANT_UnitGetHandle *
TALER_MERCHANT_unit_get (struct GNUNET_CURL_Context *ctx,
                         const char *backend_url,
                         const char *unit_id,
                         TALER_MERCHANT_UnitGetCallback cb,
                         void *cb_cls);

void
TALER_MERCHANT_unit_get_cancel (
  struct TALER_MERCHANT_UnitGetHandle *ugh);

struct TALER_MERCHANT_UnitsPostHandle *
TALER_MERCHANT_units_post (struct GNUNET_CURL_Context *ctx,
                           const char *backend_url,
                           const char *unit_id,
                           const char *unit_name_long,
                           const char *unit_name_short,
                           bool unit_allow_fraction,
                           uint32_t unit_precision_level,
                           bool unit_active,
                           const json_t *unit_name_long_i18n,
                           const json_t *unit_name_short_i18n,
                           TALER_MERCHANT_UnitsPostCallback cb,
                           void *cb_cls);

void
TALER_MERCHANT_units_post_cancel (
  struct TALER_MERCHANT_UnitsPostHandle *uph);

struct TALER_MERCHANT_UnitPatchHandle *
TALER_MERCHANT_unit_patch (struct GNUNET_CURL_Context *ctx,
                           const char *backend_url,
                           const char *unit_id,
                           const char *unit_name_long,
                           const char *unit_name_short,
                           const json_t *unit_name_long_i18n,
                           const json_t *unit_name_short_i18n,
                           const bool *unit_allow_fraction,
                           const uint32_t *unit_precision_level,
                           const bool *unit_active,
                           TALER_MERCHANT_UnitPatchCallback cb,
                           void *cb_cls);

void
TALER_MERCHANT_unit_patch_cancel (
  struct TALER_MERCHANT_UnitPatchHandle *uph);

struct TALER_MERCHANT_UnitDeleteHandle *
TALER_MERCHANT_unit_delete (struct GNUNET_CURL_Context *ctx,
                            const char *backend_url,
                            const char *unit_id,
                            TALER_MERCHANT_UnitDeleteCallback cb,
                            void *cb_cls);

void
TALER_MERCHANT_unit_delete_cancel (
  struct TALER_MERCHANT_UnitDeleteHandle *udh);


/* ********************* /templates *********************** */


/**
 * Handle for a GET /templates operation.
 */
struct TALER_MERCHANT_TemplatesGetHandle;

/**
 * Individual template (minimal information
 * returned via GET /templates).
 */
struct TALER_MERCHANT_TemplateEntry
{
  /**
   * template identifier.
   */
  const char *template_id;

};


/**
 * Response to a GET /templates operation.
 */
struct TALER_MERCHANT_TemplatesGetResponse
{
  /**
   * HTTP response details
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details depending on status.
   */
  union
  {
    /**
     * Details if status is #MHD_HTTP_OK.
     */
    struct
    {
      /**
       * length of the @e templates array
       */
      unsigned int templates_length;

      /**
       * array of templates the requested instance offers
       */
      const struct TALER_MERCHANT_TemplateEntry *templates;
    } ok;
  } details;
};


/**
 * Function called with the result of the GET /templates operation.
 *
 * @param cls closure
 * @param tgr response details
 */
typedef void
(*TALER_MERCHANT_TemplatesGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_TemplatesGetResponse *tgr);


/**
 * Make a GET /templates request.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param cb function to call with the backend information
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_TemplatesGetHandle *
TALER_MERCHANT_templates_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  TALER_MERCHANT_TemplatesGetCallback cb,
  void *cb_cls);


/**
 * Cancel GET /templates operation.
 *
 * @param tgh operation to cancel
 */
void
TALER_MERCHANT_templates_get_cancel (
  struct TALER_MERCHANT_TemplatesGetHandle *tgh);


/**
 * Handle for a GET /private/template/$ID operation. Gets details
 * about a single template. Do not confused with a
 * `struct TALER_MERCHANT_TemplatesGetHandle`, which
 * obtains a list of all templates.
 */
struct TALER_MERCHANT_TemplateGetHandle;


/**
 * Details in a response to a GET /private/templates/$ID request.
 */
struct TALER_MERCHANT_TemplateGetResponse
{
  /**
   * HTTP response details.
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Response details depending on the HTTP status.
   */
  union
  {
    /**
     * Information returned if the status was #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * description of the template
       */
      const char *template_description;

      /**
       * OTP device ID used by the POS, NULL if none.
       */
      const char *otp_id;

      /**
       * Template for the contract.
       */
      const json_t *template_contract;

    } ok;

  } details;

};


/**
 * Function called with the result of the GET /private/template/$ID operation.
 *
 * @param cls closure
 * @param tgr HTTP response details
 */
typedef void
(*TALER_MERCHANT_TemplateGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_TemplateGetResponse *tgr);


/**
 * Make a GET /private/template/$ID request to get details about an
 * individual template.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param template_id identifier of the template to inquire about
 * @param cb function to call with the backend's template information
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_TemplateGetHandle *
TALER_MERCHANT_template_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *template_id,
  TALER_MERCHANT_TemplateGetCallback cb,
  void *cb_cls);


/**
 * Cancel GET /private/templates/$ID operation.
 *
 * @param tgh operation to cancel
 */
void
TALER_MERCHANT_template_get_cancel (
  struct TALER_MERCHANT_TemplateGetHandle *tgh);


/**
 * Handle for a (public) GET /template/$ID operation. Gets details about a
 * single template. Do not confused with a `struct
 * TALER_MERCHANT_TemplateGetHandle`, which is for the private API.
 */
struct TALER_MERCHANT_WalletTemplateGetHandle;


/**
 * Details in a response to a GET /templates request.
 */
struct TALER_MERCHANT_WalletTemplateGetResponse
{
  /**
   * HTTP response details.
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Response details depending on the HTTP status.
   */
  union
  {
    /**
     * Information returned if the status was #MHD_HTTP_OK.
     */
    struct
    {

      /**
       * Template for the contract.
       */
      const json_t *template_contract;

    } ok;

  } details;

};


/**
 * Function called with the result of the GET /template/$ID operation.
 *
 * @param cls closure
 * @param tgr HTTP response details
 */
typedef void
(*TALER_MERCHANT_WalletTemplateGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_WalletTemplateGetResponse *tgr);


/**
 * Make a GET /template/$ID request to get details about an
 * individual template.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param template_id identifier of the template to inquire about
 * @param cb function to call with the backend's template information
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_WalletTemplateGetHandle *
TALER_MERCHANT_wallet_template_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *template_id,
  TALER_MERCHANT_WalletTemplateGetCallback cb,
  void *cb_cls);


/**
 * Cancel GET /templates/$ID operation.
 *
 * @param tgh operation to cancel
 */
void
TALER_MERCHANT_wallet_template_get_cancel (
  struct TALER_MERCHANT_WalletTemplateGetHandle *tgh);


/**
 * Handle for a POST /templates operation.
 */
struct TALER_MERCHANT_TemplatesPostHandle;


/**
 * Function called with the result of the POST /templates operation.
 *
 * @param cls closure
 * @param hr HTTP response details
 */
typedef void
(*TALER_MERCHANT_TemplatesPostCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Make a POST /templates request to add a template
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param template_id identifier to use for the template
 * @param template_description description of the template
 * @param otp_id ID of the OTP device, or NULL if OTP is not used
 * @param template_contract is the contract of the company
 * @param cb function to call with the backend's result
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_TemplatesPostHandle *
TALER_MERCHANT_templates_post (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *template_id,
  const char *template_description,
  const char *otp_id,
  const json_t *template_contract,
  TALER_MERCHANT_TemplatesPostCallback cb,
  void *cb_cls);


/**
 * Cancel POST /templates operation.
 *
 * @param[in] tph operation to cancel
 */
void
TALER_MERCHANT_templates_post_cancel (
  struct TALER_MERCHANT_TemplatesPostHandle *tph);


/**
 * Handle for a PATCH /template operation.
 */
struct TALER_MERCHANT_TemplatePatchHandle;


/**
 * Function called with the result of the PATCH /template operation.
 *
 * @param cls closure
 * @param hr HTTP response details
 */
typedef void
(*TALER_MERCHANT_TemplatePatchCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Make a PATCH /template request to update template details
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param template_id identifier to use for the template; the template must exist,
 *                    or the transaction will fail with a #MHD_HTTP_NOT_FOUND
 *                    HTTP status code
 * @param template_description description of the template
 * @param otp_id device ID of the OTP device, or NULL if OTP is not used
 * @param template_contract is the contract of the company
 * @param cb function to call with the backend's result
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_TemplatePatchHandle *
TALER_MERCHANT_template_patch (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *template_id,
  const char *template_description,
  const char *otp_id,
  json_t *template_contract,
  TALER_MERCHANT_TemplatePatchCallback cb,
  void *cb_cls);


/**
 * Cancel PATCH /template operation.
 *
 * @param[in] tph operation to cancel
 */
void
TALER_MERCHANT_template_patch_cancel (
  struct TALER_MERCHANT_TemplatePatchHandle *tph);


/**
 * Handle for a DELETE /template/$ID operation.
 */
struct TALER_MERCHANT_TemplateDeleteHandle;


/**
 * Function called with the result of the DELETE /template/$ID operation.
 *
 * @param cls closure
 * @param hr HTTP response details
 */
typedef void
(*TALER_MERCHANT_TemplateDeleteCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Make a DELETE /template/$ID request to delete a template.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param template_id identifier of the template
 * @param cb function to call with the backend's deletion status
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_TemplateDeleteHandle *
TALER_MERCHANT_template_delete (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *template_id,
  TALER_MERCHANT_TemplateDeleteCallback cb,
  void *cb_cls);


/**
 * Cancel DELETE /template/$ID operation.
 *
 * @param[in] tdh operation to cancel
 */
void
TALER_MERCHANT_template_delete_cancel (
  struct TALER_MERCHANT_TemplateDeleteHandle *tdh);


/**
 * Make a POST /using-templates request to add an using template
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param template_id which template should be used
 * @param summary summary of the using template
 * @param amount to pay given by the customer
 * @param cb function to call with the backend's result
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_UsingTemplatesPostHandle *
TALER_MERCHANT_using_templates_post (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *template_id,
  const char *summary,
  const struct TALER_Amount *amount,
  TALER_MERCHANT_PostOrdersCallback cb,
  void *cb_cls);


/**
 * Cancel POST /using-templates operation.
 *
 * @param[in] utph operation to cancel
 */
void
TALER_MERCHANT_using_templates_post_cancel (
  struct TALER_MERCHANT_UsingTemplatesPostHandle *utph);


/* ********************* /webhooks *********************** */


/**
 * Handle for a GET /webhooks operation.
 */
struct TALER_MERCHANT_WebhooksGetHandle;

/**
 * Individual webhook (minimal information
 * returned via GET /webhooks).
 */
struct TALER_MERCHANT_WebhookEntry
{
  /**
   * webhook identifier.
   */
  const char *webhook_id;

};


/**
 * Response to a GET /webhooks operation.
 */
struct TALER_MERCHANT_WebhooksGetResponse
{
  /**
   * HTTP response details
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details depending on status.
   */
  union
  {
    /**
     * Details if status is #MHD_HTTP_OK.
     */
    struct
    {
      /**
       * length of the @e webhooks array
       */
      unsigned int webhooks_length;

      /**
       * array of templates the requested instance offers
       */
      const struct TALER_MERCHANT_WebhookEntry *webhooks;

    } ok;

  } details;
};


/**
 * Function called with the result of the GET /webhooks operation.
 *
 * @param cls closure
 * @param wgr response details
 */
typedef void
(*TALER_MERCHANT_WebhooksGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_WebhooksGetResponse *wgr);


/**
 * Make a GET /webhooks request.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param cb function to call with the backend information
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_WebhooksGetHandle *
TALER_MERCHANT_webhooks_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  TALER_MERCHANT_WebhooksGetCallback cb,
  void *cb_cls);


/**
 * Cancel GET /webhooks operation.
 *
 * @param[in] tgh operation to cancel
 */
void
TALER_MERCHANT_webhooks_get_cancel (
  struct TALER_MERCHANT_WebhooksGetHandle *tgh);


/**
 * Handle for a GET /webhook/$ID operation. Gets details
 * about a single webhook. Do not confused with a
 * `struct TALER_MERCHANT_WebhooksGetHandle`, which
 * obtains a list of all webhooks.
 */
struct TALER_MERCHANT_WebhookGetHandle;


/**
 * Function called with the result of the GET /webhooks operation.
 *
 * @param cls closure
 * @param hr HTTP response details
 * @param event_type event of the webhook
 * @param url url to trigger webhook at
 * @param http_method use for the webhook
 * @param header_template header of the webhook
 * @param body_template body of the webhook
 */
typedef void
(*TALER_MERCHANT_WebhookGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr,
  const char *event_type,
  const char *url,
  const char *http_method,
  const char *header_template,
  const char *body_template);


/**
 * Make a GET /webhook/$ID request to get details about an
 * individual webhook.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param webhook_id identifier of the webhook to inquire about
 * @param cb function to call with the backend's webhook information
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_WebhookGetHandle *
TALER_MERCHANT_webhook_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *webhook_id,
  TALER_MERCHANT_WebhookGetCallback cb,
  void *cb_cls);


/**
 * Cancel GET /webhooks/$ID operation.
 *
 * @param[in] tgh operation to cancel
 */
void
TALER_MERCHANT_webhook_get_cancel (
  struct TALER_MERCHANT_WebhookGetHandle *tgh);


/**
 * Handle for a POST /webhooks operation.
 */
struct TALER_MERCHANT_WebhooksPostHandle;


/**
 * Function called with the result of the POST /webhooks operation.
 *
 * @param cls closure
 * @param hr HTTP response details
 */
typedef void
(*TALER_MERCHANT_WebhooksPostCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Make a POST /webhooks request to add a webhook
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param webhook_id identifier to use for the webhook
 * @param event_type event of the webhook
 * @param url url use by the customer
 * @param http_method http method use by the merchant
 * @param header_template header of the webhook
 * @param body_template body of the webhook
 * @param cb function to call with the backend's result
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_WebhooksPostHandle *
TALER_MERCHANT_webhooks_post (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *webhook_id,
  const char *event_type,
  const char *url,
  const char *http_method,
  const char *header_template,
  const char *body_template,
  TALER_MERCHANT_WebhooksPostCallback cb,
  void *cb_cls);


/**
 * Cancel POST /webhooks operation.
 *
 * @param[in] wph operation to cancel
 */
void
TALER_MERCHANT_webhooks_post_cancel (
  struct TALER_MERCHANT_WebhooksPostHandle *wph);


/**
 * Handle for a PATCH /webhook operation.
 */
struct TALER_MERCHANT_WebhookPatchHandle;


/**
 * Function called with the result of the PATCH /webhook operation.
 *
 * @param cls closure
 * @param hr HTTP response details
 */
typedef void
(*TALER_MERCHANT_WebhookPatchCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Make a PATCH /webhook request to update webhook details
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param webhook_id identifier to use for the webhook; the webhook must exist,
 *                    or the transaction will fail with a #MHD_HTTP_NOT_FOUND
 *                    HTTP status code
 * @param event_type event of the webhook
 * @param url url use by the customer
 * @param http_method http method use by the merchant
 * @param header_template header of the webhook
 * @param body_template body of the webhook
 * @param cb function to call with the backend's result
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_WebhookPatchHandle *
TALER_MERCHANT_webhook_patch (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *webhook_id,
  const char *event_type,
  const char *url,
  const char *http_method,
  const char *header_template,
  const char *body_template,
  TALER_MERCHANT_WebhookPatchCallback cb,
  void *cb_cls);


/**
 * Cancel PATCH /webhook operation.
 *
 * @param[in] wph operation to cancel
 */
void
TALER_MERCHANT_webhook_patch_cancel (
  struct TALER_MERCHANT_WebhookPatchHandle *wph);


/**
 * Handle for a DELETE /webhook$ID operation.
 */
struct TALER_MERCHANT_WebhookDeleteHandle;


/**
 * Function called with the result of the DELETE /webhook/$ID operation.
 *
 * @param cls closure
 * @param hr HTTP response details
 */
typedef void
(*TALER_MERCHANT_WebhookDeleteCallback)(
  void *cls,
  const struct TALER_MERCHANT_HttpResponse *hr);


/**
 * Make a DELETE /webhook/$ID request to delete a webhook.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param webhook_id identifier of the webhook
 * @param cb function to call with the backend's deletion status
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_WebhookDeleteHandle *
TALER_MERCHANT_webhook_delete (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *webhook_id,
  TALER_MERCHANT_WebhookDeleteCallback cb,
  void *cb_cls);


/**
 * Cancel DELETE /webhook/$ID operation.
 *
 * @param[in] wdh operation to cancel
 */
void
TALER_MERCHANT_webhook_delete_cancel (
  struct TALER_MERCHANT_WebhookDeleteHandle *wdh);

/* ********************* /statistics-[counter,amount] ************************** */

/**
 * Statistic type that can be filtered by
 */
enum TALER_MERCHANT_StatisticsType
{

  /**
   * Get all statistics
   */
  TALER_MERCHANT_STATISTICS_ALL,

  /**
   * Get statistics by interval only
   */
  TALER_MERCHANT_STATISTICS_BY_INTERVAL,

  /**
   * Get statistics by bucket only
   */
  TALER_MERCHANT_STATISTICS_BY_BUCKET,

};

/**
 * Handle for a GET /statistics-counter/$SLUG operation.
 */
struct TALER_MERCHANT_StatisticsCounterGetHandle;

/**
 * Counter by interval result object
 */
struct TALER_MERCHANT_StatisticCounterByInterval
{

  /**
   * Start time of the interval (inclusive).
   * The interval always ends at the response
   * generation time.
   */
  struct GNUNET_TIME_Timestamp start_time;

  /**
   * Sum of all counters falling under the given
   * SLUG within this timeframe.
   */
  uint64_t cumulative_counter;

};

/**
 * Counter by bucket result object
 */
struct TALER_MERCHANT_StatisticCounterByBucket
{

  /**
   * Start time of the bucket (inclusive).
   */
  struct GNUNET_TIME_Timestamp start_time;

  /**
   * End time of the bucket (exclusive).
   */
  struct GNUNET_TIME_Timestamp end_time;

  /**
   * Range of the bucket
   */
  const char *range;

  /**
   * Sum of all counters falling under the given
   * SLUG within this timeframe.
   */
  uint64_t cumulative_counter;

};

/**
 * Response to GET /statistics-counter/$SLUG operation.
 */
struct TALER_MERCHANT_StatisticsCounterGetResponse
{
  /**
   * HTTP response details
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details depending on HTTP status.
   */
  union
  {
    /**
     * Details for #MHD_HTTP_OK.
     */
    struct
    {
      /**
       * length of the @a buckets array
       */
      unsigned int buckets_length;

      /**
       * array of statistics in this bucket
       */
      const struct TALER_MERCHANT_StatisticCounterByBucket *buckets;

      /**
       * description of the statistic of the buckets
       */
      const char *buckets_description;

      /**
       * length of the @a intervals array
       */
      unsigned int intervals_length;

      /**
       * array of statistics in this interval
       */
      const struct TALER_MERCHANT_StatisticCounterByInterval *intervals;

      /**
       * description of the statistic of the intervals
       */
      const char *intervals_description;

    } ok;

  } details;

};

/**
 * Cancel GET /statistics-counter/$SLUG operation.
 *
 * @param handle operation to cancel
 */
void
TALER_MERCHANT_statistic_counter_get_cancel (
  struct TALER_MERCHANT_StatisticsCounterGetHandle *handle);


/**
 * Function called with the result of the GET /statistics-counter/$SLUG operation.
 *
 * @param cls closure
 * @param scgr response details
 */
typedef void
(*TALER_MERCHANT_StatisticsCounterGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_StatisticsCounterGetResponse *scgr);

/**
 * Make a GET /statistics-counter/$SLUG request.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param slug short, url-safe identifier for the statistic
 * @param stype the type of statistic to get, see #TALER_MERCHANT_StatisticsType
 * @param cb function to call with the statistic information
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_StatisticsCounterGetHandle *
TALER_MERCHANT_statistic_counter_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *slug,
  enum TALER_MERCHANT_StatisticsType stype,
  TALER_MERCHANT_StatisticsCounterGetCallback cb,
  void *cb_cls);

/**
 * Handle for a GET /statistics-amount/$SLUG operation.
 */
struct TALER_MERCHANT_StatisticsAmountGetHandle;

/**
 * Amount by interval result object
 */
struct TALER_MERCHANT_StatisticAmountByInterval
{
  /**
   * Start time of the interval (inclusive).
   * The interval always ends at the response
   * generation time.
   */
  struct GNUNET_TIME_Timestamp start_time;

  /**
   * Sum of all amounts falling under the given
   * SLUG within this timeframe.
   */
  struct TALER_Amount *cumulative_amounts;

  /**
   * Length of array @a cumulative_amounts
   */
  unsigned int cumulative_amount_len;

};

/**
 * Amount by bucket result object
 */
struct TALER_MERCHANT_StatisticAmountByBucket
{
  /**
   * Start time of the bucket (inclusive).
   */
  struct GNUNET_TIME_Timestamp start_time;

  /**
   * End time of the bucket (exclusive).
   */
  struct GNUNET_TIME_Timestamp end_time;

  /**
   * Range of the bucket
   */
  const char *range;

  /**
   * Sum of all amounts falling under the given
   * SLUG within this timeframe.
   */
  struct TALER_Amount *cumulative_amounts;

  /**
   * Length of array @a cumulative_amounts
   */
  unsigned int cumulative_amount_len;
};

/**
 * Response to GET /statistics-amount/$SLUG operation.
 */
struct TALER_MERCHANT_StatisticsAmountGetResponse
{
  /**
   * HTTP response details
   */
  struct TALER_MERCHANT_HttpResponse hr;

  /**
   * Details depending on HTTP status.
   */
  union
  {
    /**
     * Details for #MHD_HTTP_OK.
     */
    struct
    {
      /**
       * length of the @a buckets array
       */
      unsigned int buckets_length;

      /**
       * array of statistics in this bucket
       */
      const struct TALER_MERCHANT_StatisticAmountByBucket *buckets;

      /**
       * description of the statistic of the buckets
       */
      const char *buckets_description;

      /**
       * length of the @a intervals array
       */
      unsigned int intervals_length;

      /**
       * array of statistics in this Interval
       */
      const struct TALER_MERCHANT_StatisticAmountByInterval *intervals;

      /**
       * description of the statistic of the intervals
       */
      const char *intervals_description;

    } ok;

  } details;

};

/**
 * Cancel GET /statistics-amount/$SLUG operation.
 *
 * @param handle operation to cancel
 */
void
TALER_MERCHANT_statistic_amount_get_cancel (
  struct TALER_MERCHANT_StatisticsAmountGetHandle *handle);


/**
 * Function called with the result of the GET /statistics-amount/$SLUG operation.
 *
 * @param cls closure
 * @param sagr response details
 */
typedef void
(*TALER_MERCHANT_StatisticsAmountGetCallback)(
  void *cls,
  const struct TALER_MERCHANT_StatisticsAmountGetResponse *sagr);

/**
 * Make a GET /statistics-amount request.
 *
 * @param ctx the context
 * @param backend_url HTTP base URL for the backend
 * @param slug short, url-safe identifier for the statistic
 * @param stype the type of statistic to get, see #TALER_MERCHANT_StatisticsType
 * @param cb function to call with the statistic information
 * @param cb_cls closure for @a cb
 * @return the request handle; NULL upon error
 */
struct TALER_MERCHANT_StatisticsAmountGetHandle *
TALER_MERCHANT_statistic_amount_get (
  struct GNUNET_CURL_Context *ctx,
  const char *backend_url,
  const char *slug,
  enum TALER_MERCHANT_StatisticsType stype,
  TALER_MERCHANT_StatisticsAmountGetCallback cb,
  void *cb_cls);


#endif  /* _TALER_MERCHANT_SERVICE_H */
