Documentation

API Reference

Three sources of truth for any agent: REST/OpenAPI, the live A2A Agent Card, and the Skill bundle. The protocol core is Intent, Proposal, Match Session, and Match Token; PCD is the display artifact.

How to use this page

Each section is a different integration surface. Typical order:

  1. OpenAPI — quick-start with `GET /v1/recommend`, or move deeper into `/v1/intents`, `/v1/proposals`, `/v1/match`, and `/v1/match-tokens`. Copy-paste snippets live on Connect.
  2. Agent Card — point your A2A or discovery client at /.well-known/agent-card.json so capabilities stay aligned with this gateway.
  3. SKILL.md — for Claude / OpenClaw-style hosts, run the one-line installer on Connect; the skill maps natural language into recommend / card / showcase calls.
  4. Intent matching (v0.2) — merchant agents register, submit proposals, demand agents create match sessions, and accepted proposals mint match tokens. Event and object shapes are in the protocol docs below.

Open Connect Open Try

OpenAPI 3.0

Canonical REST contract for this gateway. The raw specification lives at /openapi.json — the same manifest consumed by ChatGPT custom GPTs and the Gemini extension.

Moras A2A Gateway

Recommend high-converting TikTok Shop products with KOC videos. Each card carries an attribution-tracking buy link that MUST be passed to the user verbatim.

Browser playground & integration guides: https://a2a.moras.ai/ — try the API live, copy ready-made snippets for OpenClaw / Cursor / Claude Code / ChatGPT / Gemini / Codex / Hermes.

OpenAPI 3.0.3 · v0.1.0

recommend

Discovery endpoints — public, free, optional channel header.

GET /v1/recommend Recommend product cards by natural-language intent Details

Parameters

Name In Required Type Description
intent query yes string User's natural-language intent. e.g. "gift for my 3yo nephew".
limit query no integer
region query no string ISO country code (US, UK, ...)
channel query no string Channel hint (openclaw|cursor|gemini|chatgpt|hermes|...)

Responses

CodeDescription
200

OK

Body schema — application/json · RecommendResponse

{
  "type": "object",
  "properties": {
    "intent": {
      "type": "string"
    },
    "intent_id": {
      "type": "string"
    },
    "count": {
      "type": "integer"
    },
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "rec_id": {
            "type": "string",
            "description": "Globally unique recommendation id; primary key for attribution."
          },
          "product": {
            "$ref": "#/components/schemas/Product"
          },
          "hero_pitch": {
            "$ref": "#/components/schemas/HeroPitch"
          },
          "selection_story": {
            "$ref": "#/components/schemas/SelectionStory"
          },
          "videos": {
            "type": "array",
            "items": {
              "$ref": "(max depth)"
            }
          },
          "cta": {
            "$ref": "#/components/schemas/Cta"
          },
          "compliance": {
            "type": "object",
            "properties": {
              "region_allow": {
                "$ref": "(max depth)"
              },
              "risk_level": {
                "$ref": "(max depth)"
              }
            }
          },
          "generated_at": {
            "type": "string",
            "format": "date-time"
          },
          "channel": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "rec_id",
          "product",
          "hero_pitch",
          "selection_story",
          "videos",
          "cta",
          "generated_at"
        ]
      }
    },
    "proposals": {
      "type": "array",
      "items": {
        "type": "object"
      }
    },
    "proposal_count": {
      "type": "integer"
    },
    "match_session_id": {
      "type": "string"
    },
    "shopper_guide": {
      "type": "string",
      "description": "Warm, human-facing copy from the shopper agent (Gemini); explains how picks relate to the user's intent."
    },
    "note": {
      "type": "string",
      "description": "Optional machine hint e.g. intent_plus_trending, trending_suggested.",
      "nullable": true
    },
    "match_tier": {
      "type": "string",
      "description": "raw_substring | strict | narrow | fuzzy | broadened | none — how intent rows were retrieved before trending fill."
    },
    "intent_source": {
      "type": "string"
    },
    "resolved_keywords": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "resolved_categories": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "retrieval": {
      "type": "object",
      "properties": {
        "intent_hits": {
          "type": "integer"
        },
        "trending_fill": {
          "type": "integer"
        }
      }
    },
    "generated_at": {
      "type": "string",
      "format": "date-time"
    }
  }
}
503

Intent engine unavailable — set GOOGLE_API_KEY or GEMINI_API_KEY on the gateway. Intent is resolved only via Gemini (no offline dictionary).

Body schema — application/json

{
  "type": "object",
  "properties": {
    "error": {
      "type": "string"
    },
    "message": {
      "type": "string"
    }
  }
}

card

Hydrate or look up a previously generated PCD.

GET /v1/cards/{recId} Look up a previously generated PCD by recId Details

Parameters

Name In Required Type Description
recId path yes string

Responses

CodeDescription
200

OK

Body schema — application/json · PCD

{
  "type": "object",
  "properties": {
    "rec_id": {
      "type": "string",
      "description": "Globally unique recommendation id; primary key for attribution."
    },
    "product": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "title": {
          "type": "string"
        },
        "brand": {
          "type": "string",
          "nullable": true
        },
        "price_usd": {
          "type": "number",
          "nullable": true
        },
        "original_price_usd": {
          "type": "number",
          "nullable": true
        },
        "discount_label": {
          "type": "string",
          "nullable": true
        },
        "main_image": {
          "type": "string",
          "nullable": true
        },
        "gallery": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "category_l1": {
          "type": "string",
          "nullable": true
        },
        "category_l2": {
          "type": "string",
          "nullable": true
        }
      }
    },
    "hero_pitch": {
      "type": "object",
      "properties": {
        "one_liner": {
          "type": "string"
        },
        "why_it_wins_on_tiktok": {
          "type": "string"
        },
        "key_benefits": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "icon": {
                "$ref": "(max depth)"
              },
              "title": {
                "$ref": "(max depth)"
              },
              "desc": {
                "$ref": "(max depth)"
              }
            }
          }
        },
        "target_audience": {
          "type": "object",
          "properties": {
            "persona": {
              "type": "string"
            },
            "age": {
              "type": "string"
            },
            "region": {
              "type": "array",
              "items": {
                "$ref": "(max depth)"
              }
            }
          }
        }
      }
    },
    "selection_story": {
      "type": "object",
      "properties": {
        "headline": {
          "type": "string"
        },
        "bullets": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "moras_score": {
          "type": "number"
        }
      }
    },
    "videos": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "task_id": {
            "type": "string"
          },
          "creator": {
            "type": "object",
            "properties": {
              "username": {
                "$ref": "(max depth)"
              },
              "display_name": {
                "$ref": "(max depth)"
              },
              "avatar": {
                "$ref": "(max depth)"
              },
              "followers": {
                "$ref": "(max depth)"
              }
            }
          },
          "thumbnail": {
            "type": "string",
            "nullable": true
          },
          "video_url": {
            "type": "string",
            "nullable": true
          },
          "duration_s": {
            "type": "integer"
          },
          "gmv_usd": {
            "type": "number"
          },
          "orders": {
            "type": "integer"
          },
          "views": {
            "type": "integer"
          },
          "conversion_score": {
            "type": "number"
          },
          "tiktok_video_url": {
            "type": "string",
            "nullable": true
          }
        }
      }
    },
    "cta": {
      "type": "object",
      "properties": {
        "primary": {
          "type": "object",
          "properties": {
            "label": {
              "type": "string"
            },
            "url": {
              "type": "string",
              "description": "MUST be passed to user verbatim — carries attribution rec_id."
            }
          }
        },
        "secondary": {
          "type": "object",
          "properties": {
            "label": {
              "type": "string"
            },
            "url": {
              "type": "string"
            }
          }
        }
      }
    },
    "compliance": {
      "type": "object",
      "properties": {
        "region_allow": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "risk_level": {
          "type": "string",
          "enum": [
            "low",
            "medium",
            "high"
          ]
        }
      }
    },
    "generated_at": {
      "type": "string",
      "format": "date-time"
    },
    "channel": {
      "type": "string",
      "nullable": true
    }
  },
  "required": [
    "rec_id",
    "product",
    "hero_pitch",
    "selection_story",
    "videos",
    "cta",
    "generated_at"
  ],
  "description": "Product Card Document — the atomic recommendation unit."
}
404

not found

GET /v1/products/{productId}/card Build a fresh PCD for a known product id Details

Parameters

Name In Required Type Description
productId path yes string

Responses

CodeDescription
200

OK

Body schema — application/json · PCD

{
  "type": "object",
  "properties": {
    "rec_id": {
      "type": "string",
      "description": "Globally unique recommendation id; primary key for attribution."
    },
    "product": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "title": {
          "type": "string"
        },
        "brand": {
          "type": "string",
          "nullable": true
        },
        "price_usd": {
          "type": "number",
          "nullable": true
        },
        "original_price_usd": {
          "type": "number",
          "nullable": true
        },
        "discount_label": {
          "type": "string",
          "nullable": true
        },
        "main_image": {
          "type": "string",
          "nullable": true
        },
        "gallery": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "category_l1": {
          "type": "string",
          "nullable": true
        },
        "category_l2": {
          "type": "string",
          "nullable": true
        }
      }
    },
    "hero_pitch": {
      "type": "object",
      "properties": {
        "one_liner": {
          "type": "string"
        },
        "why_it_wins_on_tiktok": {
          "type": "string"
        },
        "key_benefits": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "icon": {
                "$ref": "(max depth)"
              },
              "title": {
                "$ref": "(max depth)"
              },
              "desc": {
                "$ref": "(max depth)"
              }
            }
          }
        },
        "target_audience": {
          "type": "object",
          "properties": {
            "persona": {
              "type": "string"
            },
            "age": {
              "type": "string"
            },
            "region": {
              "type": "array",
              "items": {
                "$ref": "(max depth)"
              }
            }
          }
        }
      }
    },
    "selection_story": {
      "type": "object",
      "properties": {
        "headline": {
          "type": "string"
        },
        "bullets": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "moras_score": {
          "type": "number"
        }
      }
    },
    "videos": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "task_id": {
            "type": "string"
          },
          "creator": {
            "type": "object",
            "properties": {
              "username": {
                "$ref": "(max depth)"
              },
              "display_name": {
                "$ref": "(max depth)"
              },
              "avatar": {
                "$ref": "(max depth)"
              },
              "followers": {
                "$ref": "(max depth)"
              }
            }
          },
          "thumbnail": {
            "type": "string",
            "nullable": true
          },
          "video_url": {
            "type": "string",
            "nullable": true
          },
          "duration_s": {
            "type": "integer"
          },
          "gmv_usd": {
            "type": "number"
          },
          "orders": {
            "type": "integer"
          },
          "views": {
            "type": "integer"
          },
          "conversion_score": {
            "type": "number"
          },
          "tiktok_video_url": {
            "type": "string",
            "nullable": true
          }
        }
      }
    },
    "cta": {
      "type": "object",
      "properties": {
        "primary": {
          "type": "object",
          "properties": {
            "label": {
              "type": "string"
            },
            "url": {
              "type": "string",
              "description": "MUST be passed to user verbatim — carries attribution rec_id."
            }
          }
        },
        "secondary": {
          "type": "object",
          "properties": {
            "label": {
              "type": "string"
            },
            "url": {
              "type": "string"
            }
          }
        }
      }
    },
    "compliance": {
      "type": "object",
      "properties": {
        "region_allow": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "risk_level": {
          "type": "string",
          "enum": [
            "low",
            "medium",
            "high"
          ]
        }
      }
    },
    "generated_at": {
      "type": "string",
      "format": "date-time"
    },
    "channel": {
      "type": "string",
      "nullable": true
    }
  },
  "required": [
    "rec_id",
    "product",
    "hero_pitch",
    "selection_story",
    "videos",
    "cta",
    "generated_at"
  ],
  "description": "Product Card Document — the atomic recommendation unit."
}

creator

Browse a creator's showcase.

GET /v1/creators/{username}/showcase Top products this creator has produced winning videos for Details

Parameters

Name In Required Type Description
username path yes string
limit query no integer

Responses

CodeDescription
200

OK

Body schema — application/json · ShowcaseResponse

{
  "type": "object",
  "properties": {
    "username": {
      "type": "string"
    },
    "count": {
      "type": "integer"
    },
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "rec_id": {
            "type": "string",
            "description": "Globally unique recommendation id; primary key for attribution."
          },
          "product": {
            "$ref": "#/components/schemas/Product"
          },
          "hero_pitch": {
            "$ref": "#/components/schemas/HeroPitch"
          },
          "selection_story": {
            "$ref": "#/components/schemas/SelectionStory"
          },
          "videos": {
            "type": "array",
            "items": {
              "$ref": "(max depth)"
            }
          },
          "cta": {
            "$ref": "#/components/schemas/Cta"
          },
          "compliance": {
            "type": "object",
            "properties": {
              "region_allow": {
                "$ref": "(max depth)"
              },
              "risk_level": {
                "$ref": "(max depth)"
              }
            }
          },
          "generated_at": {
            "type": "string",
            "format": "date-time"
          },
          "channel": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "rec_id",
          "product",
          "hero_pitch",
          "selection_story",
          "videos",
          "cta",
          "generated_at"
        ]
      }
    }
  }
}

intent

First-class intent objects for true A2A commerce flows.

POST /v1/intent-mandates/sign Sign a commerce intent mandate (RSA-SHA256 over canonical payload) Details

Returns a signed Intent Mandate for checkout flows. Requires MORAS_PRIVATE_KEY (RSA PEM) on the gateway; returns 503 if unset.

Parameters

No parameters.

Responses

CodeDescription
201

Signed mandate

Body schema — application/json

{
  "type": "object"
}
400

invalid_body

503

MORAS_PRIVATE_KEY not configured

POST /v1/intents Create a first-class intent Details

Parameters

No parameters.

Responses

CodeDescription
201

created

Body schema — application/json · IntentResponse

{
  "type": "object",
  "properties": {
    "intent": {
      "type": "object",
      "properties": {
        "intent_id": {
          "type": "string"
        },
        "raw_query": {
          "type": "string"
        },
        "normalized_query": {
          "type": "string",
          "nullable": true
        },
        "intent_tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "target_audience": {
          "type": "string",
          "nullable": true
        },
        "budget_range": {
          "type": "object",
          "nullable": true
        },
        "region": {
          "type": "string",
          "nullable": true
        },
        "constraints": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "source_channel": {
          "type": "string",
          "nullable": true
        },
        "resolution_source": {
          "type": "string",
          "nullable": true
        },
        "resolution_summary": {
          "type": "string",
          "nullable": true
        },
        "metadata": {
          "type": "object"
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        }
      }
    }
  }
}
400

missing_fields

GET /v1/intents/{intentId} Fetch an intent by id Details

Parameters

Name In Required Type Description
intentId path yes string

Responses

CodeDescription
200

OK

Body schema — application/json · IntentResponse

{
  "type": "object",
  "properties": {
    "intent": {
      "type": "object",
      "properties": {
        "intent_id": {
          "type": "string"
        },
        "raw_query": {
          "type": "string"
        },
        "normalized_query": {
          "type": "string",
          "nullable": true
        },
        "intent_tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "target_audience": {
          "type": "string",
          "nullable": true
        },
        "budget_range": {
          "type": "object",
          "nullable": true
        },
        "region": {
          "type": "string",
          "nullable": true
        },
        "constraints": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "source_channel": {
          "type": "string",
          "nullable": true
        },
        "resolution_source": {
          "type": "string",
          "nullable": true
        },
        "resolution_summary": {
          "type": "string",
          "nullable": true
        },
        "metadata": {
          "type": "object"
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        }
      }
    }
  }
}
404

intent_not_found

GET /v1/intents/{intentId}/proposals List proposals attached to an intent Details

Parameters

Name In Required Type Description
intentId path yes string
include_expired query no boolean

Responses

CodeDescription
200

OK

Body schema — application/json · IntentProposalListResponse

{
  "type": "object",
  "properties": {
    "intent_id": {
      "type": "string"
    },
    "count": {
      "type": "integer"
    },
    "proposals": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "proposal_id": {
            "type": "string"
          },
          "merchant_agent_id": {
            "type": "string"
          },
          "intent_id": {
            "type": "string"
          },
          "product_id": {
            "type": "integer"
          },
          "offer_title": {
            "type": "string"
          },
          "price": {
            "type": "number",
            "nullable": true
          },
          "inventory_status": {
            "type": "string"
          },
          "shipping_commitment": {
            "type": "object"
          },
          "commission_plan": {
            "type": "object"
          },
          "service_terms": {
            "type": "object"
          },
          "evidence": {
            "type": "array",
            "items": {
              "$ref": "(max depth)"
            }
          },
          "valid_until": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "proposal_score_inputs": {
            "type": "object"
          },
          "product_snapshot": {
            "type": "object",
            "nullable": true
          },
          "metadata": {
            "type": "object"
          },
          "provenance": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      }
    }
  }
}
404

intent_not_found

proposal

Merchant proposals attached to an intent.

POST /v1/proposals Submit a merchant proposal Details

Parameters

No parameters.

Responses

CodeDescription
201

created

Body schema — application/json · ProposalResponse

{
  "type": "object",
  "properties": {
    "proposal": {
      "type": "object",
      "properties": {
        "proposal_id": {
          "type": "string"
        },
        "merchant_agent_id": {
          "type": "string"
        },
        "intent_id": {
          "type": "string"
        },
        "product_id": {
          "type": "integer"
        },
        "offer_title": {
          "type": "string"
        },
        "price": {
          "type": "number",
          "nullable": true
        },
        "inventory_status": {
          "type": "string"
        },
        "shipping_commitment": {
          "type": "object"
        },
        "commission_plan": {
          "type": "object"
        },
        "service_terms": {
          "type": "object"
        },
        "evidence": {
          "type": "array",
          "items": {
            "type": "object"
          }
        },
        "valid_until": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "proposal_score_inputs": {
          "type": "object"
        },
        "product_snapshot": {
          "type": "object",
          "nullable": true
        },
        "metadata": {
          "type": "object"
        },
        "provenance": {
          "type": "string"
        },
        "status": {
          "type": "string"
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        }
      }
    }
  }
}
401

missing registration token

403

invalid registration token

404

intent_not_found or merchant_not_found

GET /v1/proposals/{proposalId} Fetch a proposal by id Details

Parameters

Name In Required Type Description
proposalId path yes string

Responses

CodeDescription
200

OK

Body schema — application/json · ProposalResponse

{
  "type": "object",
  "properties": {
    "proposal": {
      "type": "object",
      "properties": {
        "proposal_id": {
          "type": "string"
        },
        "merchant_agent_id": {
          "type": "string"
        },
        "intent_id": {
          "type": "string"
        },
        "product_id": {
          "type": "integer"
        },
        "offer_title": {
          "type": "string"
        },
        "price": {
          "type": "number",
          "nullable": true
        },
        "inventory_status": {
          "type": "string"
        },
        "shipping_commitment": {
          "type": "object"
        },
        "commission_plan": {
          "type": "object"
        },
        "service_terms": {
          "type": "object"
        },
        "evidence": {
          "type": "array",
          "items": {
            "type": "object"
          }
        },
        "valid_until": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "proposal_score_inputs": {
          "type": "object"
        },
        "product_snapshot": {
          "type": "object",
          "nullable": true
        },
        "metadata": {
          "type": "object"
        },
        "provenance": {
          "type": "string"
        },
        "status": {
          "type": "string"
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        }
      }
    }
  }
}
404

proposal_not_found

match

Rank proposals into match sessions and mint match tokens.

POST /v1/match Create a match session from an intent and proposals Details

Parameters

No parameters.

Responses

CodeDescription
201

created

Body schema — application/json · MatchSessionResponse

{
  "type": "object",
  "properties": {
    "match_session": {
      "type": "object",
      "properties": {
        "match_session_id": {
          "type": "string"
        },
        "intent_id": {
          "type": "string"
        },
        "best_proposal_id": {
          "type": "string",
          "nullable": true
        },
        "ranked_proposals": {
          "type": "array",
          "items": {
            "type": "object"
          }
        },
        "summary": {
          "type": "object"
        },
        "status": {
          "type": "string"
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        }
      }
    }
  }
}
400

missing_fields

404

intent_not_found or proposal_not_found

GET /v1/match/{matchSessionId} Fetch a rendered match session Details

Parameters

Name In Required Type Description
matchSessionId path yes string
limit query no integer

Responses

CodeDescription
200

OK

Body schema — application/json · MatchRenderedResponse

{
  "type": "object",
  "properties": {
    "match_session": {
      "type": "object",
      "properties": {
        "match_session_id": {
          "type": "string"
        },
        "intent_id": {
          "type": "string"
        },
        "best_proposal_id": {
          "type": "string",
          "nullable": true
        },
        "ranked_proposals": {
          "type": "array",
          "items": {
            "type": "object"
          }
        },
        "summary": {
          "type": "object"
        },
        "status": {
          "type": "string"
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        }
      }
    },
    "ranked_proposals": {
      "type": "array",
      "items": {
        "type": "object"
      }
    },
    "match_tokens": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "match_token_id": {
            "type": "string"
          },
          "match_session_id": {
            "type": "string"
          },
          "intent_id": {
            "type": "string"
          },
          "proposal_id": {
            "type": "string"
          },
          "acceptance_state": {
            "type": "string"
          },
          "intent_snapshot": {
            "type": "object"
          },
          "proposal_snapshot": {
            "type": "object"
          },
          "ranking_snapshot": {
            "type": "object"
          },
          "trace_ids": {
            "type": "object"
          },
          "issued_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "accepted_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      }
    },
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "rec_id": {
            "type": "string",
            "description": "Globally unique recommendation id; primary key for attribution."
          },
          "product": {
            "$ref": "#/components/schemas/Product"
          },
          "hero_pitch": {
            "$ref": "#/components/schemas/HeroPitch"
          },
          "selection_story": {
            "$ref": "#/components/schemas/SelectionStory"
          },
          "videos": {
            "type": "array",
            "items": {
              "$ref": "(max depth)"
            }
          },
          "cta": {
            "$ref": "#/components/schemas/Cta"
          },
          "compliance": {
            "type": "object",
            "properties": {
              "region_allow": {
                "$ref": "(max depth)"
              },
              "risk_level": {
                "$ref": "(max depth)"
              }
            }
          },
          "generated_at": {
            "type": "string",
            "format": "date-time"
          },
          "channel": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "rec_id",
          "product",
          "hero_pitch",
          "selection_story",
          "videos",
          "cta",
          "generated_at"
        ]
      }
    }
  }
}
404

match_not_found

POST /v1/match/{matchSessionId}/accept Accept a ranked proposal and mint or confirm the match token Details

Parameters

Name In Required Type Description
matchSessionId path yes string

Responses

CodeDescription
200

OK

Body schema — application/json · MatchTokenResponse

{
  "type": "object",
  "properties": {
    "match_token": {
      "type": "object",
      "properties": {
        "match_token_id": {
          "type": "string"
        },
        "match_session_id": {
          "type": "string"
        },
        "intent_id": {
          "type": "string"
        },
        "proposal_id": {
          "type": "string"
        },
        "acceptance_state": {
          "type": "string"
        },
        "intent_snapshot": {
          "type": "object"
        },
        "proposal_snapshot": {
          "type": "object"
        },
        "ranking_snapshot": {
          "type": "object"
        },
        "trace_ids": {
          "type": "object"
        },
        "issued_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "expires_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "accepted_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        }
      }
    }
  }
}
404

match_not_found

GET /v1/match-tokens/{matchTokenId} Fetch a match token by id Details

Parameters

Name In Required Type Description
matchTokenId path yes string

Responses

CodeDescription
200

OK

Body schema — application/json · MatchTokenResponse

{
  "type": "object",
  "properties": {
    "match_token": {
      "type": "object",
      "properties": {
        "match_token_id": {
          "type": "string"
        },
        "match_session_id": {
          "type": "string"
        },
        "intent_id": {
          "type": "string"
        },
        "proposal_id": {
          "type": "string"
        },
        "acceptance_state": {
          "type": "string"
        },
        "intent_snapshot": {
          "type": "object"
        },
        "proposal_snapshot": {
          "type": "object"
        },
        "ranking_snapshot": {
          "type": "object"
        },
        "trace_ids": {
          "type": "object"
        },
        "issued_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "expires_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "accepted_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        }
      }
    }
  }
}
404

match_token_not_found

merchant

Merchant / supply-side Agent registry and lifecycle endpoints.

POST /v1/merchant/register Register a merchant Agent (intent-matching v0.1) Details

Registers a merchant agent endpoint, subscription tags, capabilities, and routing scope for Moras A2A. Registration is persisted and token-protected; merchants can heartbeat, health-check, receive Intent.Surge dispatches, and submit proposals. See /docs/INTENT_MATCHING_PROTOCOL.md on this gateway.

Parameters

No parameters.

Responses

CodeDescription
200

OK

Body schema — application/json · MerchantRegisterResponse

{
  "type": "object",
  "properties": {
    "status": {
      "type": "string"
    },
    "created": {
      "type": "boolean"
    },
    "merchant_id": {
      "type": "string"
    },
    "registration_token": {
      "type": "string",
      "description": "Secret token used for heartbeat, updates, deactivation, and proposal submission."
    },
    "merchant": {
      "type": "object",
      "properties": {
        "merchant_id": {
          "type": "string"
        },
        "agent_endpoint": {
          "type": "string"
        },
        "subscription_tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "capabilities": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "regions": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "category_tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "inventory_scope": {
          "type": "array",
          "items": {
            "type": "object"
          }
        },
        "protocol_version": {
          "type": "string",
          "nullable": true
        },
        "a2a_capabilities": {
          "type": "object"
        },
        "metadata": {
          "type": "object"
        },
        "status": {
          "type": "string"
        },
        "registered_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "last_seen_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "deactivated_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        }
      }
    }
  }
}
400

missing_fields — merchant_id and agent_endpoint required

GET /v1/merchant/{merchantId} Fetch a registered merchant Agent Details

Parameters

Name In Required Type Description
merchantId path yes string

Responses

CodeDescription
200

OK

Body schema — application/json · MerchantLookupResponse

{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "nullable": true
    },
    "merchant": {
      "type": "object",
      "properties": {
        "merchant_id": {
          "type": "string"
        },
        "agent_endpoint": {
          "type": "string"
        },
        "subscription_tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "capabilities": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "regions": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "category_tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "inventory_scope": {
          "type": "array",
          "items": {
            "type": "object"
          }
        },
        "protocol_version": {
          "type": "string",
          "nullable": true
        },
        "a2a_capabilities": {
          "type": "object"
        },
        "metadata": {
          "type": "object"
        },
        "status": {
          "type": "string"
        },
        "registered_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "last_seen_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "deactivated_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        }
      }
    }
  }
}
404

merchant_not_found

GET /v1/merchant/{merchantId}/health Probe merchant Agent health Details

Parameters

Name In Required Type Description
merchantId path yes string

Responses

CodeDescription
200

merchant healthy

503

merchant unhealthy or unreachable

POST /v1/merchant/heartbeat Heartbeat a merchant Agent Details

Parameters

No parameters.

Responses

CodeDescription
200

OK

Body schema — application/json · MerchantLookupResponse

{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "nullable": true
    },
    "merchant": {
      "type": "object",
      "properties": {
        "merchant_id": {
          "type": "string"
        },
        "agent_endpoint": {
          "type": "string"
        },
        "subscription_tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "capabilities": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "regions": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "category_tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "inventory_scope": {
          "type": "array",
          "items": {
            "type": "object"
          }
        },
        "protocol_version": {
          "type": "string",
          "nullable": true
        },
        "a2a_capabilities": {
          "type": "object"
        },
        "metadata": {
          "type": "object"
        },
        "status": {
          "type": "string"
        },
        "registered_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "last_seen_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "deactivated_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        }
      }
    }
  }
}
401

missing registration token

403

invalid registration token

POST /v1/merchant/{merchantId}/deactivate Deactivate a merchant Agent Details

Parameters

Name In Required Type Description
merchantId path yes string

Responses

CodeDescription
200

OK

Body schema — application/json · MerchantLookupResponse

{
  "type": "object",
  "properties": {
    "status": {
      "type": "string",
      "nullable": true
    },
    "merchant": {
      "type": "object",
      "properties": {
        "merchant_id": {
          "type": "string"
        },
        "agent_endpoint": {
          "type": "string"
        },
        "subscription_tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "capabilities": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "regions": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "category_tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "inventory_scope": {
          "type": "array",
          "items": {
            "type": "object"
          }
        },
        "protocol_version": {
          "type": "string",
          "nullable": true
        },
        "a2a_capabilities": {
          "type": "object"
        },
        "metadata": {
          "type": "object"
        },
        "status": {
          "type": "string"
        },
        "registered_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "last_seen_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        },
        "deactivated_at": {
          "type": "string",
          "format": "date-time",
          "nullable": true
        }
      }
    }
  }
}
401

missing registration token

403

invalid registration token

report

Supply-side ROI reports (auth required).

GET /v1/report/attribution ROI report (supply side, requires X-Supply-Key) Auth Details

Parameters

Name In Required Type Description
days query no integer
channel query no string
product_id query no string

Responses

CodeDescription
200

OK

401

unauthorized

Intent matching & merchant agents

Moras now exposes the core objects required for true A-to-A commerce between demand-side agents and merchant-side agents.

The merchant tag and protocol note below describe the live v0.2 registration, dispatch, proposal, and match-token contract: Intent-Matching Protocol v0.2. Merchant registry, heartbeats, health checks, proposal submission, match sessions, and match tokens are live in this gateway.

Merchant-side quick start (v0.2)

  1. Send `POST /v1/merchant/register` with `merchant_id`, `agent_endpoint`, and optional tags / capabilities. Store the returned `registration_token`.
  2. Use `X-Merchant-Token` for `POST /v1/merchant/heartbeat`, merchant updates, deactivation, and `POST /v1/proposals`.
  3. Consume `Intent.Surge` or poll `/v1/intents`, submit `/v1/proposals`, then let demand agents call `/v1/match` or `/v1/recommend` to rank and accept offers.

A2A Agent Card

Machine-readable A2A card (live) at /.well-known/agent-card.json. Point your agent runtime here so capabilities stay in sync.

Loading…

SKILL.md

Human-readable skill document served at /skills/moras-shop/SKILL.md — byte-for-byte what the installer copies into your agent's skills folder.

Loading…