{
  "name": "social",
  "summary": "Social add-on for a Duolingo-style app or game: a daily friend streak (friend_daily), a weekly friend quest (friend_weekly), a weekly team quest (team_weekly) and the social notification message types. Apply it after the game starter recipe.",
  "notes": [
    "Requires the currency coins (the game starter recipe creates it). Without the game starter, create it first: POST /v1/currencies {\"code\": \"coins\", \"name\": \"Coins\"}.",
    "Send every call below with the agent token (Authorization: Bearer <agent token>, X-Orishare-Environment: <environment id>) and a fresh Idempotency-Key header on every POST. Apply the definitions in order: create, then the activate call right after it. {id} accepts the key (friend_daily, friend_weekly, team_weekly) or the returned id.",
    "In the sandbox (autonomy auto) the direct routes below work. In production without autonomy auto (an agent-created project starts in limits) an agent credential calling them is refused with 403 confirmation_required, reason agent_direct_write. Propose each call as its own change set instead (POST /v1/change_sets, then POST /v1/change_set_applications): friend_streak_definition.create, friend_quest_definition.create or team_quest_definition.create with the create body as the command's fields, then the matching .activate with key and expected_version; and notification_message_type.create with each notifications item. Under limits they apply when their rewards are within the cost caps (https://docs.orishare.com/docs/autonomy); a refusal answers 403 confirmation_required with a review_url for a person.",
    "Runtime calls are open to an agent-minted secret key in production too: POST /v1/friend_streak_definitions/{id}/activities, POST /v1/friend_quest_definitions/{id}/contributions, POST /v1/team_quest_definitions/{id}/contributions, POST /v1/leagues/{id}/contributions, POST /v1/customers/{id}/friendships.",
    "Friend streak activity and friend or team quest progress are backend calls with the secret key (customer_id is the Orishare customer id, cust_...). No rule action and no customer-session route records them, so an app without a backend needs one small server function (for example a Firebase Cloud Function or a Supabase Edge Function) that forwards 'played today' and 'finished a level'. Everything else (friend codes, requests, friend list, pairing for the friend quest, nudges, high fives, teams, all reads) is a customer-session call from the app.",
    "Customer sessions for social features must be signed in (not anonymous): anonymous sessions get 403 social_unavailable_for_anonymous."
  ],
  "definitions": [
    {
      "name": "friend_daily",
      "method": "POST",
      "path": "/v1/friend_streak_definitions",
      "note": "A pair's day counts when both friends were active that day (environment time zone). Milestone rewards are paid once per pair and length, to both friends.",
      "body": {
        "key": "friend_daily",
        "name": "Friend streak",
        "config": {
          "schema": "friend_streak/v1",
          "timezone": "environment",
          "milestones": [
            { "length": 3, "reward": [{ "currency": "coins", "amount": 10 }] },
            { "length": 7, "reward": [{ "currency": "coins", "amount": 30 }] },
            { "length": 30, "reward": [{ "currency": "coins", "amount": 100 }] }
          ]
        }
      },
      "activate": {
        "method": "POST",
        "path": "/v1/friend_streak_definitions/friend_daily/activate",
        "body": { "expected_revision": 1 }
      }
    },
    {
      "name": "friend_weekly",
      "method": "POST",
      "path": "/v1/friend_quest_definitions",
      "note": "Two friends pair up for the week and finish 10 levels together; both get 50 coins when the pair reaches the target.",
      "body": {
        "key": "friend_weekly",
        "name": "Finish 10 levels together",
        "config": {
          "schema": "friend_quest/v1",
          "period": {
            "kind": "week",
            "start_weekday": 1,
            "start_minute": 0,
            "timezone": "environment"
          },
          "target": 10,
          "metric": { "source": "direct" },
          "reward": [{ "currency": "coins", "amount": 50 }],
          "pairing": "manual"
        }
      },
      "activate": {
        "method": "POST",
        "path": "/v1/friend_quest_definitions/friend_weekly/activate",
        "body": { "expected_revision": 1 }
      }
    },
    {
      "name": "team_weekly",
      "method": "POST",
      "path": "/v1/team_quest_definitions",
      "note": "Optional. Each team works toward 50 levels a week; every member who contributed at least 1 gets 20 coins.",
      "body": {
        "key": "team_weekly",
        "name": "Team: 50 levels this week",
        "config": {
          "schema": "team_quest/v1",
          "period": {
            "kind": "week",
            "start_weekday": 1,
            "start_minute": 0,
            "timezone": "environment"
          },
          "target": 50,
          "metric": { "source": "direct" },
          "reward": [{ "currency": "coins", "amount": 20 }],
          "min_contribution": 1
        }
      },
      "activate": {
        "method": "POST",
        "path": "/v1/team_quest_definitions/team_weekly/activate",
        "body": { "expected_revision": 1 }
      }
    }
  ],
  "notifications": {
    "method": "POST",
    "path": "/v1/notification_message_types",
    "note": "Optional. One POST per item. The catalogue (GET /v1/notification_catalog) fills the name, the event types and the default copy from the key. Orishare sends no real email or push from an unclaimed project; webhooks carry the same events meanwhile.",
    "message_types": [
      {
        "key": "friend_request",
        "routes": [
          { "channel": "mobile_push", "path": "builtin" },
          { "channel": "web_push", "path": "builtin" }
        ]
      },
      {
        "key": "friend_accepted",
        "routes": [
          { "channel": "mobile_push", "path": "builtin" },
          { "channel": "web_push", "path": "builtin" }
        ]
      },
      {
        "key": "friend_nudge",
        "routes": [
          { "channel": "mobile_push", "path": "builtin" },
          { "channel": "web_push", "path": "builtin" }
        ]
      },
      {
        "key": "friend_high_five",
        "routes": [
          { "channel": "mobile_push", "path": "builtin" },
          { "channel": "web_push", "path": "builtin" }
        ]
      },
      {
        "key": "friend_streak_at_risk",
        "routes": [
          { "channel": "mobile_push", "path": "builtin" },
          { "channel": "web_push", "path": "builtin" }
        ]
      },
      {
        "key": "friend_quest_completed",
        "routes": [
          { "channel": "mobile_push", "path": "builtin" },
          { "channel": "web_push", "path": "builtin" }
        ]
      },
      {
        "key": "team_quest_completed",
        "routes": [
          { "channel": "mobile_push", "path": "builtin" },
          { "channel": "web_push", "path": "builtin" }
        ]
      }
    ]
  }
}
