{
  "openapi": "3.1.0",
  "info": {
    "title": "Awaken Embedded & Partner API",
    "version": "1.0.0",
    "description": "Server-to-server API for hosted tax portals, custom embedded tax integrations, signup links, and partner discounts."
  },
  "servers": [
    {
      "url": "https://api.awaken.tax"
    }
  ],
  "security": [
    {
      "partnerClientId": [],
      "partnerApiSecret": []
    },
    {
      "partnerApiKey": []
    }
  ],
  "tags": [
    {
      "name": "Hosted Portal",
      "description": "Create and deliver branded signup links."
    },
    {
      "name": "Users",
      "description": "Create and retrieve embedded tax users."
    },
    {
      "name": "Accounts",
      "description": "Attach wallet accounts and monitor imports."
    },
    {
      "name": "Tax Engine",
      "description": "Recalculate and retrieve tax previews."
    },
    {
      "name": "Reports",
      "description": "Generate, list, and download tax reports."
    },
    {
      "name": "Partners",
      "description": "Partner-specific convenience and discount operations."
    }
  ],
  "paths": {
    "/api/access-tokens": {
      "post": {
        "tags": [
          "Hosted Portal"
        ],
        "summary": "Mint a short-lived access token for the embedded portal",
        "operationId": "createAccessToken",
        "x-request-example": {
          "referenceId": "user-42",
          "email": "user@example.com",
          "expiresInSeconds": 3600
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "referenceId"
                ],
                "properties": {
                  "referenceId": {
                    "type": "string"
                  },
                  "expiresInSeconds": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 86400
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token minted. Open portalUrl in the browser, or use accessToken as a Bearer token."
          },
          "400": {
            "description": "Invalid body. referenceId is missing, or email or expiresInSeconds is malformed."
          },
          "401": {
            "description": "Partner credentials missing or invalid."
          },
          "403": {
            "description": "An access token cannot mint another access token. Use a partner credential."
          },
          "404": {
            "description": "No client with that referenceId belongs to this partner."
          }
        },
        "x-response-example": {
          "type": "success",
          "message": "Access token created successfully",
          "data": {
            "accessToken": "<access-token-jwt>",
            "tokenType": "Bearer",
            "referenceId": "user-42",
            "expiresInSeconds": 3600,
            "expiresAt": "2026-07-30T00:42:57.891Z",
            "portalUrl": "https://embed.awaken.tax/portal?code=user-42&token=<access-token-jwt>&email=user%40example.com"
          }
        }
      }
    },
    "/api/links": {
      "post": {
        "tags": [
          "Hosted Portal"
        ],
        "summary": "Create a hosted portal link",
        "operationId": "createLink",
        "x-request-example": {
          "wallets": [
            {
              "address": "0xabc…",
              "name": "Primary wallet"
            }
          ]
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LinkRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Existing link"
          },
          "201": {
            "description": "Link created"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    },
    "/api/links/email": {
      "post": {
        "tags": [
          "Hosted Portal"
        ],
        "summary": "Email a hosted portal link",
        "operationId": "emailLink",
        "x-request-example": {
          "email": "user@example.com",
          "wallets": [
            {
              "address": "0xabc…"
            }
          ]
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/LinkRequest"
                  },
                  {
                    "type": "object",
                    "required": [
                      "email"
                    ],
                    "properties": {
                      "email": {
                        "type": "string",
                        "format": "email"
                      }
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Email accepted"
          },
          "429": {
            "description": "Recipient daily limit reached"
          }
        }
      }
    },
    "/api/crunch": {
      "post": {
        "tags": [
          "Partners"
        ],
        "summary": "Create a card-program user and accounts",
        "operationId": "createUserAndAccounts",
        "x-request-example": {
          "userId": "card-user-42",
          "email": "user@example.com",
          "wallets": [
            {
              "address": "0xabc…",
              "provider": "ethereum",
              "name": "Card rewards"
            }
          ]
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "userId"
                ],
                "properties": {
                  "userId": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  },
                  "wallets": {
                    "type": "array",
                    "maxItems": 4,
                    "items": {
                      "type": "object",
                      "required": [
                        "address"
                      ],
                      "properties": {
                        "address": {
                          "type": "string"
                        },
                        "provider": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "User and supported accounts created"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    },
    "/api/discount-codes": {
      "post": {
        "tags": [
          "Partners"
        ],
        "summary": "Create or retrieve a user's discount code",
        "operationId": "createDiscountCode",
        "x-request-example": {
          "referenceId": "user-42",
          "year": 2025
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "referenceId"
                ],
                "properties": {
                  "referenceId": {
                    "type": "string"
                  },
                  "year": {
                    "type": "integer",
                    "minimum": 2009,
                    "maximum": 2100
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Existing code"
          },
          "201": {
            "description": "Code created"
          },
          "403": {
            "description": "Secret-key authentication required"
          }
        }
      }
    },
    "/api/users": {
      "post": {
        "tags": [
          "Users"
        ],
        "summary": "Create an embedded tax user",
        "operationId": "createUser",
        "x-request-example": {
          "userId": "user-42",
          "email": "user@example.com"
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "userId"
                ],
                "properties": {
                  "userId": {
                    "type": "string",
                    "description": "Your stable identifier; used as referenceId in subsequent paths."
                  },
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "User created"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    },
    "/api/users/{referenceId}/user": {
      "get": {
        "tags": [
          "Users"
        ],
        "summary": "Retrieve a compact embedded user",
        "operationId": "getUser",
        "parameters": [
          {
            "$ref": "#/components/parameters/ReferenceId"
          }
        ],
        "responses": {
          "200": {
            "description": "User and partner branding"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/users/{referenceId}/accounts": {
      "get": {
        "tags": [
          "Accounts"
        ],
        "summary": "List a user's accounts",
        "operationId": "getAccounts",
        "parameters": [
          {
            "$ref": "#/components/parameters/ReferenceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Compact account list"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "post": {
        "tags": [
          "Accounts"
        ],
        "summary": "Add wallet accounts",
        "operationId": "createAccounts",
        "parameters": [
          {
            "$ref": "#/components/parameters/ReferenceId"
          }
        ],
        "x-request-example": {
          "wallets": [
            {
              "address": "0xabc…",
              "chain": "ethereum",
              "name": "Treasury"
            }
          ]
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "wallets"
                ],
                "properties": {
                  "wallets": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "$ref": "#/components/schemas/ChainWallet"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Supported accounts created"
          },
          "400": {
            "description": "Invalid wallet or 10-account limit reached"
          }
        }
      }
    },
    "/api/users/{referenceId}/account_syncs": {
      "get": {
        "tags": [
          "Accounts"
        ],
        "summary": "List account syncs and current account states",
        "operationId": "getAccountSyncs",
        "parameters": [
          {
            "$ref": "#/components/parameters/ReferenceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Sync jobs and account statuses"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "post": {
        "tags": [
          "Accounts"
        ],
        "summary": "Start account syncs",
        "operationId": "createAccountSync",
        "parameters": [
          {
            "$ref": "#/components/parameters/ReferenceId"
          }
        ],
        "x-request-example": {
          "account_ids": [
            "4e0761cc-e588-4e72-8dc7-49fd186ef10d"
          ]
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_ids": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 50,
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    }
                  },
                  "accountIds": {
                    "type": "array",
                    "deprecated": true,
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Syncs accepted"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    },
    "/api/users/{referenceId}/account_syncs/{syncId}": {
      "get": {
        "tags": [
          "Accounts"
        ],
        "summary": "Retrieve one account sync",
        "operationId": "getAccountSync",
        "parameters": [
          {
            "$ref": "#/components/parameters/ReferenceId"
          },
          {
            "name": "syncId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sync progress"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/users/{referenceId}/preview": {
      "get": {
        "tags": [
          "Tax Engine"
        ],
        "summary": "Retrieve a tax preview",
        "operationId": "getTaxPreview",
        "parameters": [
          {
            "$ref": "#/components/parameters/ReferenceId"
          },
          {
            "name": "year",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 2020
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Capital gains, income, futures, and transaction count"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/users/{referenceId}/refresh": {
      "post": {
        "tags": [
          "Tax Engine"
        ],
        "summary": "Start ledger recalculation",
        "operationId": "recalculate",
        "parameters": [
          {
            "$ref": "#/components/parameters/ReferenceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Recalculation job started"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/users/{referenceId}/active-recalculate-job": {
      "get": {
        "tags": [
          "Tax Engine"
        ],
        "summary": "Retrieve the active recalculation job",
        "operationId": "getActiveRecalculateJob",
        "parameters": [
          {
            "$ref": "#/components/parameters/ReferenceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Active job, or null when settled"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/users/{referenceId}/reports": {
      "get": {
        "tags": [
          "Reports"
        ],
        "summary": "List a user's reports",
        "operationId": "getReports",
        "parameters": [
          {
            "$ref": "#/components/parameters/ReferenceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Available and in-progress reports"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "post": {
        "tags": [
          "Reports"
        ],
        "summary": "Generate a tax report",
        "operationId": "createReport",
        "parameters": [
          {
            "$ref": "#/components/parameters/ReferenceId"
          }
        ],
        "x-request-example": {
          "year": 2025,
          "reportType": "tax-forms",
          "email": "user@example.com"
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "year",
                  "reportType"
                ],
                "properties": {
                  "year": {
                    "type": "integer",
                    "minimum": 2020
                  },
                  "reportType": {
                    "type": "string",
                    "description": "A currently supported Awaken ReportType."
                  },
                  "email": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "email"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Report generation accepted"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          }
        }
      }
    },
    "/api/users/{referenceId}/reports/{reportId}/download": {
      "get": {
        "tags": [
          "Reports"
        ],
        "summary": "Download a generated report",
        "operationId": "downloadReportGet",
        "parameters": [
          {
            "$ref": "#/components/parameters/ReferenceId"
          },
          {
            "$ref": "#/components/parameters/ReportId"
          }
        ],
        "responses": {
          "200": {
            "description": "Report file",
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "contentEncoding": "binary"
                }
              }
            }
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "post": {
        "tags": [
          "Reports"
        ],
        "summary": "Download a report with a signed payload",
        "operationId": "downloadReportPost",
        "parameters": [
          {
            "$ref": "#/components/parameters/ReferenceId"
          },
          {
            "$ref": "#/components/parameters/ReportId"
          }
        ],
        "responses": {
          "200": {
            "description": "Report file"
          },
          "401": {
            "description": "Invalid or expired signature"
          }
        }
      }
    },
    "/api/reports/{reportId}/download": {
      "post": {
        "tags": [
          "Reports"
        ],
        "summary": "Retrieve report data through a signed download",
        "operationId": "getReportDownloadUrl",
        "parameters": [
          {
            "$ref": "#/components/parameters/ReportId"
          }
        ],
        "responses": {
          "200": {
            "description": "Base64 report data and filename"
          },
          "401": {
            "description": "Invalid or expired signature"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "partnerApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key"
      },
      "partnerClientId": {
        "type": "apiKey",
        "in": "header",
        "name": "x-client-id"
      },
      "partnerApiSecret": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-secret"
      }
    },
    "parameters": {
      "ReferenceId": {
        "name": "referenceId",
        "in": "path",
        "required": true,
        "description": "Your stable identifier for the embedded user.",
        "schema": {
          "type": "string"
        }
      },
      "ReportId": {
        "name": "reportId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Validation failed",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "The resource was not found for the authenticated partner",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "request_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "Wallet": {
        "type": "object",
        "required": [
          "address"
        ],
        "properties": {
          "address": {
            "type": "string"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "ChainWallet": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Wallet"
          },
          {
            "type": "object",
            "required": [
              "chain"
            ],
            "properties": {
              "chain": {
                "type": "string",
                "description": "A supported Awaken AccountProvider."
              }
            }
          }
        ]
      },
      "LinkRequest": {
        "type": "object",
        "required": [
          "wallets"
        ],
        "properties": {
          "wallets": {
            "type": "array",
            "minItems": 1,
            "maxItems": 10,
            "items": {
              "$ref": "#/components/schemas/Wallet"
            }
          }
        }
      }
    }
  }
}
