How it works
Deploy with AI without duplicate projects
Before creating, read GET /projects and GET /subscription. Identify the requested project by projectId or exact slug and preserve that ID throughout the task. Send a stable slug when creating it. A 409 with error.details.reason=PROJECT_ALREADY_EXISTS returns this organization’s projectId and slug: confirm it is the intended project and reuse it. Do not invent another name or suffix to bypass a conflict or quota.
For POST /projects and POST /projects/<id>/deployments, send Idempotency-Key: an identifier of 8–128 characters [A-Za-z0-9._:-]. Preserve one key for project creation and another per code revision. Retry the SAME key and SAME body after a lost response; successful results replay for 24 hours without another mutation. A changed body returns 409 IDEMPOTENCY_KEY_REUSED. IDEMPOTENCY_PENDING or IDEMPOTENCY_PREVIOUS_FAILURE requires inspecting projects and deployment history before acting; never blindly use a new key. A genuine code fix uses a new ZIP, sourceObjectKey and deployment key while retaining projectId.
Distinguish the overall project state from the current release: read GET /deployments/<id>. Follow the same deployment during QUEUED, BUILDING or HEALTHCHECK; on deadline report the pending stage. On FAILED read /diagnostico (text), /logs?from=tail and runtime-logs; fix build, port, command or dependencies and deploy to the SAME project. Never create another project to fix HTTP 500/502, timeouts or queues. READY still requires HTTPS and checking the requested flow, such as login, before claiming functional success.
Before provisioning, read GET /databases and GET /projects/<id>/storage and reuse the project resources. Database and S3 bindings are not new projects. Use the returned connectionEnvKey, DATABASE_URL/REDIS_URL and S3 envKeys; never derive a password or host from a country. The default storage binding is reused; additional=true requests another binding and should only be used when requested. Keep database and S3 credentials out of browsers.
Use data.effectiveLimits, data.usage, data.executionAllowed and data.subscription from GET /subscription, not just the Hobby/Pro/Enterprise name. A 402 PLAN_LIMIT_EXCEEDED does not authorize deleting resources to free quota or purchasing extras. Desired replicas do not prove healthy instances: check /replicas and /metrics. Autoscaling and paid copies must fit the limits and customer authorization; a region alone does not prove database, Redis or file failover.