{
  "openapi": "3.1.0",
  "info": {
    "title": "wyro API",
    "version": "0.1.0",
    "description": "Publica en redes sociales desde tu agente. Empieza sin registro con POST /v1/sandbox: la clave de prueba simula todas las redes, es gratis y dura 72 horas. Guía para agentes: https://wyroapi.vercel.app/AGENTS.md"
  },
  "servers": [
    {
      "url": "https://wyroapi.vercel.app"
    }
  ],
  "security": [
    {
      "bearer": []
    }
  ],
  "paths": {
    "/v1/sandbox": {
      "post": {
        "operationId": "createSandbox",
        "summary": "Crear una clave de prueba (sin registro)",
        "description": "Crea un espacio de trabajo anónimo con cuentas simuladas y devuelve una clave que dura 72 horas. Límite: 5 por IP por hora.",
        "security": [],
        "parameters": [
          {
            "name": "client",
            "in": "query",
            "description": "Quién crea la clave: claude-code, codex, cursor, n8n, cli, curl, web.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "utm_source",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "utm_campaign",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "201": {
            "description": "Clave creada",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Sandbox"
                }
              }
            }
          },
          "429": {
            "description": "Demasiadas claves desde esta IP (sandbox_limit)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/me": {
      "get": {
        "operationId": "getMe",
        "summary": "Estado de la clave",
        "description": "Modo de la clave (sandbox, trial, paid, expired), vencimiento y link para conectar cuentas reales.",
        "responses": {
          "200": {
            "description": "Estado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Me"
                }
              }
            }
          },
          "401": {
            "description": "Clave faltante, inválida o vencida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/accounts": {
      "get": {
        "operationId": "listAccounts",
        "summary": "Listar cuentas",
        "description": "Cuentas disponibles para publicar. Con clave de prueba son simuladas.",
        "responses": {
          "200": {
            "description": "Cuentas",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "accounts": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Account"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Clave faltante, inválida o vencida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/posts": {
      "post": {
        "operationId": "createPost",
        "summary": "Publicar o programar",
        "description": "Publica ya o programa un post en una o varias redes. Devuelve preview_url: muéstraselo al usuario. Instagram y Pinterest necesitan imagen o video; TikTok y YouTube, video.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePost"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Post creado",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Post"
                }
              }
            }
          },
          "400": {
            "description": "Datos inválidos (validation_error, media_required, text_too_long, platform_not_supported)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Clave faltante, inválida o vencida",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listPosts",
        "summary": "Listar publicaciones",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Publicaciones",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "posts": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Post"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/posts/{id}": {
      "get": {
        "operationId": "getPost",
        "summary": "Estado de una publicación",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "example": "post_abc123"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Post",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Post"
                }
              }
            }
          },
          "404": {
            "description": "No existe (post_not_found)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/connect": {
      "post": {
        "operationId": "connectAccount",
        "summary": "Link para conectar una cuenta real",
        "description": "Devuelve el link que el humano abre para conectar su cuenta. Después, la misma clave publica de verdad.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "platform"
                ],
                "properties": {
                  "platform": {
                    "type": "string",
                    "enum": [
                      "instagram",
                      "facebook",
                      "tiktok",
                      "linkedin",
                      "twitter",
                      "threads",
                      "youtube",
                      "pinterest"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Link",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Connect"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "Clave que empieza con wyro_sk_"
      }
    },
    "schemas": {
      "Platform": {
        "type": "string",
        "enum": [
          "instagram",
          "facebook",
          "tiktok",
          "linkedin",
          "twitter",
          "threads",
          "youtube",
          "pinterest"
        ]
      },
      "Account": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "acc_abc123"
          },
          "platform": {
            "$ref": "#/components/schemas/Platform"
          },
          "mode": {
            "type": "string",
            "enum": [
              "simulated",
              "real"
            ]
          },
          "username": {
            "type": "string"
          },
          "display_name": {
            "type": "string"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "Sandbox": {
        "type": "object",
        "properties": {
          "api_key": {
            "type": "string",
            "description": "Guárdala: no se puede volver a ver."
          },
          "mode": {
            "type": "string",
            "enum": [
              "sandbox"
            ]
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "workspace_id": {
            "type": "string"
          },
          "accounts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Account"
            }
          },
          "mcp": {
            "type": "object",
            "properties": {
              "url": {
                "type": "string"
              },
              "claude_code": {
                "type": "string"
              }
            }
          },
          "next_step": {
            "type": "string",
            "description": "Qué hacer después, en lenguaje natural."
          }
        }
      },
      "Me": {
        "type": "object",
        "properties": {
          "workspace_id": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "sandbox",
              "trial",
              "paid",
              "expired"
            ]
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "key_hint": {
            "type": "string"
          },
          "connect_url": {
            "type": "string"
          },
          "next_step": {
            "type": "string"
          }
        }
      },
      "CreatePost": {
        "type": "object",
        "required": [
          "text"
        ],
        "description": "Envía platforms o account_ids.",
        "properties": {
          "text": {
            "type": "string",
            "example": "Hola desde mi agente"
          },
          "platforms": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Platform"
            },
            "example": [
              "instagram",
              "linkedin"
            ]
          },
          "account_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "media": {
            "type": "array",
            "maxItems": 10,
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "format": "uri"
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "image",
                    "video"
                  ]
                }
              }
            }
          },
          "scheduled_at": {
            "type": "string",
            "format": "date-time",
            "description": "Sin esto se publica ya."
          }
        }
      },
      "Post": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "scheduled",
              "published",
              "failed"
            ]
          },
          "simulated": {
            "type": "boolean"
          },
          "text": {
            "type": "string"
          },
          "media": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "scheduled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "published_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "preview_url": {
            "type": "string",
            "description": "Muéstraselo al usuario."
          },
          "targets": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "account_id": {
                  "type": "string"
                },
                "platform": {
                  "$ref": "#/components/schemas/Platform"
                },
                "simulated": {
                  "type": "boolean"
                },
                "preview_url": {
                  "type": "string"
                }
              }
            }
          },
          "next_step": {
            "type": "string"
          }
        }
      },
      "Connect": {
        "type": "object",
        "properties": {
          "platform": {
            "$ref": "#/components/schemas/Platform"
          },
          "connect_url": {
            "type": "string"
          },
          "next_step": {
            "type": "string"
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "missing_api_key",
                  "invalid_api_key",
                  "sandbox_expired",
                  "key_expired",
                  "workspace_suspended",
                  "rate_limited",
                  "sandbox_limit",
                  "validation_error",
                  "platform_not_supported",
                  "no_account_for_platform",
                  "media_required",
                  "text_too_long",
                  "account_not_found",
                  "post_not_found",
                  "account_disconnected",
                  "provider_error",
                  "not_found",
                  "internal_error"
                ]
              },
              "message": {
                "type": "object",
                "properties": {
                  "es": {
                    "type": "string"
                  },
                  "en": {
                    "type": "string"
                  }
                }
              },
              "fix": {
                "type": "object",
                "properties": {
                  "es": {
                    "type": "string"
                  },
                  "en": {
                    "type": "string"
                  }
                }
              },
              "docs_url": {
                "type": "string"
              },
              "details": {
                "type": "object"
              }
            }
          }
        }
      }
    }
  }
}