{
  "openapi": "3.1.0",
  "info": {
    "title": "Transi-Store API",
    "version": "1.0.0",
    "description": "REST API for managing translations in [Transi-Store](https://transi-store.com).\n\n## Authentication\n\nAll endpoints require a **Bearer API key**. You can generate one from your organization's settings page (*Settings → API Keys*).\n\n```\nAuthorization: Bearer <your-api-key>\n```\n\n## CLI\n\nFor automated workflows (CI/CD, local development), use the [`@transi-store/cli`](https://www.npmjs.com/package/@transi-store/cli) command-line tool. It wraps these API endpoints and supports batch operations via a configuration file.\n\n```bash\nnpm install -g @transi-store/cli\n```\n\nRead the full documentation on [npm](https://www.npmjs.com/package/@transi-store/cli).\n\n## Formats\n\n| Format | Content-Type | Extension | Description |\n|--------|-------------|-----------|-------------|\n| `json` | `application/json` | `.json` | Flat key → value object |\n| `xliff` | `application/xml` | `.xliff` | XLIFF 2.0 XML document |\n| `csv` | `text/csv` | `.csv` | CSV with columns `key`, `translation` |\n\n| `yaml` | `application/x-yaml` | `.yaml` | Flat key → value object in YAML format |\n| `po` | `text/plain` | `.po` | Gettext PO file |\n| `ini` | `text/plain` | `.ini` | INI file with flat key → value pairs |\n| `php` | `text/plain` | `.php` | PHP file returning an array of key → value pairs |\n\n"
  },
  "servers": [
    {
      "url": "/",
      "description": "Current server"
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerApiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key generated from the organization settings page. Pass it as a Bearer token in the Authorization header."
      }
    },
    "schemas": {
      "ProjectDetail": {
        "type": "object",
        "properties": {
          "files": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "number",
                  "description": "Project file identifier."
                },
                "format": {
                  "type": "string",
                  "enum": [
                    "json",
                    "xliff",
                    "yaml",
                    "csv",
                    "po",
                    "ini",
                    "php"
                  ],
                  "description": "File format."
                },
                "filePath": {
                  "type": "string",
                  "description": "Relative path to the translation file, with a `<lang>` placeholder that is replaced by each locale when writing the file to disk."
                }
              },
              "required": [
                "id",
                "format",
                "filePath"
              ]
            }
          },
          "languages": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "locale": {
                  "type": "string",
                  "description": "BCP-47 language tag."
                },
                "isDefault": {
                  "type": "boolean",
                  "description": "Whether this language is the project's default locale."
                }
              },
              "required": [
                "locale",
                "isDefault"
              ]
            }
          }
        },
        "required": [
          "files",
          "languages"
        ]
      },
      "ProjectDetailError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message.",
            "example": "Project 'my-project' not found"
          }
        },
        "required": [
          "error"
        ]
      },
      "ExportError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message.",
            "example": "Invalid format. Use 'json', 'xliff', 'yaml', 'csv', 'po', 'ini', or 'php'"
          }
        },
        "required": [
          "error"
        ]
      },
      "ImportSuccess": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "stats": {
            "type": "object",
            "properties": {
              "total": {
                "type": "number",
                "description": "Total number of entries processed from the file.",
                "example": 42
              },
              "keysCreated": {
                "type": "number",
                "description": "Number of new translation keys created.",
                "example": 5
              },
              "translationsCreated": {
                "type": "number",
                "description": "Number of new translations added.",
                "example": 8
              },
              "translationsUpdated": {
                "type": "number",
                "description": "Number of existing translations updated (only with 'overwrite' strategy).",
                "example": 3
              },
              "translationsSkipped": {
                "type": "number",
                "description": "Number of existing translations left untouched (only with 'skip' strategy).",
                "example": 0
              }
            },
            "required": [
              "total",
              "keysCreated",
              "translationsCreated",
              "translationsUpdated",
              "translationsSkipped"
            ]
          }
        },
        "required": [
          "success",
          "stats"
        ]
      },
      "ImportError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Human-readable error message.",
            "example": "Missing 'locale' field"
          },
          "details": {
            "type": "string",
            "description": "Additional technical details about the error."
          }
        },
        "required": [
          "error"
        ]
      }
    },
    "parameters": {}
  },
  "paths": {
    "/api/orgs/{orgSlug}/projects/{projectSlug}": {
      "get": {
        "summary": "Get project metadata",
        "description": "Return the list of translation files and languages configured for a project. Used by the CLI to discover which files to download or upload.",
        "tags": [
          "Projects"
        ],
        "security": [
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Organization slug.",
              "example": "my-org"
            },
            "required": true,
            "description": "Organization slug.",
            "name": "orgSlug",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Project slug.",
              "example": "my-project"
            },
            "required": true,
            "description": "Project slug.",
            "name": "projectSlug",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Project metadata (files and languages).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectDetail"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectDetailError"
                }
              }
            }
          },
          "403": {
            "description": "The API key does not belong to this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectDetailError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectDetailError"
                }
              }
            }
          }
        }
      }
    },
    "/api/orgs/{orgSlug}/projects/{projectSlug}/files/{fileId}/translations": {
      "get": {
        "summary": "Export translations for a specific file",
        "description": "Download translations for a single locale, scoped to one project file. The file's stored format is used by default; pass `format` to override. The response is returned as a file attachment.",
        "tags": [
          "Translations"
        ],
        "security": [
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Organization slug.",
              "example": "my-org"
            },
            "required": true,
            "description": "Organization slug.",
            "name": "orgSlug",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Project slug.",
              "example": "my-project"
            },
            "required": true,
            "description": "Project slug.",
            "name": "projectSlug",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Project file identifier.",
              "example": "1"
            },
            "required": true,
            "description": "Project file identifier.",
            "name": "fileId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "xliff",
                "yaml",
                "csv",
                "po",
                "ini",
                "php"
              ],
              "description": "Output format. Supported formats: 'json', 'xliff', 'yaml', 'csv', 'po', 'ini', or 'php'.",
              "example": "json"
            },
            "required": false,
            "description": "Output format. Supported formats: 'json', 'xliff', 'yaml', 'csv', 'po', 'ini', or 'php'.",
            "name": "format",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Language code to export (must match one of the project's configured languages).",
              "example": "fr"
            },
            "required": true,
            "description": "Language code to export (must match one of the project's configured languages).",
            "name": "locale",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Branch slug. When set, translations from this branch are merged on top of main translations. Use \"@all\" to export all translations across every branch (no branch filtering). Omit to export the main branch only.",
              "example": "feature-xyz"
            },
            "required": false,
            "description": "Branch slug. When set, translations from this branch are merged on top of main translations. Use \"@all\" to export all translations across every branch (no branch filtering). Omit to export the main branch only.",
            "name": "branch",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Translation file for the given project file + locale.",
            "headers": {
              "Content-Disposition": {
                "schema": {
                  "type": "string",
                  "description": "Suggested filename for the downloaded file.",
                  "example": "attachment; filename=\"my-project-1-fr.json\""
                },
                "required": true,
                "description": "Suggested filename for the downloaded file."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "string"
                  },
                  "description": "Flat key → translation object.",
                  "example": {
                    "home.title": "Accueil"
                  }
                }
              },
              "application/xml": {
                "schema": {
                  "type": "string",
                  "description": "XLIFF 2.0 XML document."
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExportError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExportError"
                }
              }
            }
          },
          "403": {
            "description": "The API key does not belong to this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExportError"
                }
              }
            }
          },
          "404": {
            "description": "Project or file not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExportError"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Import translations into a specific file",
        "description": "Upload a translation file for a single locale, scoped to one project file. New keys are created under that file. Use the `strategy` field to control whether existing translations are updated or skipped.",
        "tags": [
          "Translations"
        ],
        "security": [
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Organization slug.",
              "example": "my-org"
            },
            "required": true,
            "description": "Organization slug.",
            "name": "orgSlug",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Project slug.",
              "example": "my-project"
            },
            "required": true,
            "description": "Project slug.",
            "name": "projectSlug",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Project file identifier.",
              "example": "1"
            },
            "required": true,
            "description": "Project file identifier.",
            "name": "fileId",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "locale": {
                    "type": "string",
                    "description": "Language code to import into (must match one of the project's configured languages).",
                    "example": "fr"
                  },
                  "strategy": {
                    "type": "string",
                    "enum": [
                      "overwrite",
                      "skip"
                    ],
                    "description": "Import strategy. 'overwrite' updates existing translations. 'skip' only creates missing translations and leaves existing ones untouched.",
                    "example": "overwrite"
                  },
                  "format": {
                    "type": "string",
                    "enum": [
                      "json",
                      "xliff",
                      "yaml",
                      "csv",
                      "po",
                      "ini",
                      "php"
                    ],
                    "description": "File format ('json', 'xliff', 'yaml', 'csv', 'po', 'ini', or 'php'). Auto-detected from file extension if omitted.",
                    "example": "json"
                  },
                  "branch": {
                    "type": "string",
                    "description": "Target branch slug. If the branch does not exist and has an open status, it will be created automatically. Omit to import into the main branch.",
                    "example": "feature-xyz"
                  },
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "Translation file to import (JSON or XLIFF 2.0). Maximum size: 5 MB."
                  }
                },
                "required": [
                  "locale",
                  "strategy",
                  "file"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Import completed successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportSuccess"
                }
              }
            }
          },
          "400": {
            "description": "Validation error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportError"
                }
              }
            }
          },
          "403": {
            "description": "The API key does not belong to this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportError"
                }
              }
            }
          },
          "404": {
            "description": "Project or file not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportError"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed (only POST is accepted).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportError"
                }
              }
            }
          }
        }
      }
    },
    "/api/orgs/{orgSlug}/projects/{projectSlug}/translations": {
      "get": {
        "summary": "Export translations (deprecated)",
        "description": "⚠️ **Deprecated.** Use the file-scoped endpoint `/api/orgs/{orgSlug}/projects/{projectSlug}/files/{fileId}/translations` instead. This route operates on the project's default file only and will be removed in a future version.\n\nDownload translations for a single locale in JSON or XLIFF 2.0 format. The response is returned as a file attachment.",
        "deprecated": true,
        "tags": [
          "Translations"
        ],
        "security": [
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Organization slug.",
              "example": "my-org"
            },
            "required": true,
            "description": "Organization slug.",
            "name": "orgSlug",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Project slug.",
              "example": "my-project"
            },
            "required": true,
            "description": "Project slug.",
            "name": "projectSlug",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "json",
                "xliff",
                "yaml",
                "csv",
                "po",
                "ini",
                "php"
              ],
              "description": "Output format. Supported formats: 'json', 'xliff', 'yaml', 'csv', 'po', 'ini', or 'php'.",
              "example": "json"
            },
            "required": true,
            "description": "Output format. Supported formats: 'json', 'xliff', 'yaml', 'csv', 'po', 'ini', or 'php'.",
            "name": "format",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Language code to export (must match one of the project's configured languages).",
              "example": "fr"
            },
            "required": true,
            "description": "Language code to export (must match one of the project's configured languages).",
            "name": "locale",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Branch slug. When set, translations from this branch are merged on top of main translations. Use \"@all\" to export all translations across every branch (no branch filtering). Omit to export the main branch only.",
              "example": "feature-xyz"
            },
            "required": false,
            "description": "Branch slug. When set, translations from this branch are merged on top of main translations. Use \"@all\" to export all translations across every branch (no branch filtering). Omit to export the main branch only.",
            "name": "branch",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Translation file. Content-Type depends on the requested format: `application/json` for JSON, `application/xml` for XLIFF.",
            "headers": {
              "Content-Disposition": {
                "schema": {
                  "type": "string",
                  "description": "Suggested filename for the downloaded file.",
                  "example": "attachment; filename=\"my-project-fr.json\""
                },
                "required": true,
                "description": "Suggested filename for the downloaded file."
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "string"
                  },
                  "description": "Flat key → translation object.",
                  "example": {
                    "home.title": "Accueil",
                    "home.subtitle": "Bienvenue"
                  }
                }
              },
              "application/xml": {
                "schema": {
                  "type": "string",
                  "description": "XLIFF 2.0 XML document."
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters (unknown format, missing locale, …).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExportError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExportError"
                }
              }
            }
          },
          "403": {
            "description": "The API key does not belong to this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExportError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExportError"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Import translations (deprecated)",
        "description": "⚠️ **Deprecated.** Use the file-scoped endpoint `/api/orgs/{orgSlug}/projects/{projectSlug}/files/{fileId}/translations` instead. This route operates on the project's default file only and will be removed in a future version.\n\nUpload a translation file (JSON or XLIFF 2.0) for a single locale. New keys are created automatically. Use the `strategy` field to control whether existing translations are updated or skipped.",
        "deprecated": true,
        "tags": [
          "Translations"
        ],
        "security": [
          {
            "BearerApiKey": []
          }
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Organization slug.",
              "example": "my-org"
            },
            "required": true,
            "description": "Organization slug.",
            "name": "orgSlug",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Project slug.",
              "example": "my-project"
            },
            "required": true,
            "description": "Project slug.",
            "name": "projectSlug",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "locale": {
                    "type": "string",
                    "description": "Language code to import into (must match one of the project's configured languages).",
                    "example": "fr"
                  },
                  "strategy": {
                    "type": "string",
                    "enum": [
                      "overwrite",
                      "skip"
                    ],
                    "description": "Import strategy. 'overwrite' updates existing translations. 'skip' only creates missing translations and leaves existing ones untouched.",
                    "example": "overwrite"
                  },
                  "format": {
                    "type": "string",
                    "enum": [
                      "json",
                      "xliff",
                      "yaml",
                      "csv",
                      "po",
                      "ini",
                      "php"
                    ],
                    "description": "File format ('json', 'xliff', 'yaml', 'csv', 'po', 'ini', or 'php'). Auto-detected from file extension if omitted.",
                    "example": "json"
                  },
                  "branch": {
                    "type": "string",
                    "description": "Target branch slug. If the branch does not exist and has an open status, it will be created automatically. Omit to import into the main branch.",
                    "example": "feature-xyz"
                  },
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "Translation file to import (JSON or XLIFF 2.0). Maximum size: 5 MB."
                  }
                },
                "required": [
                  "locale",
                  "strategy",
                  "file"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Import completed successfully.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportSuccess"
                }
              }
            }
          },
          "400": {
            "description": "Validation error (missing field, unsupported format, unknown locale, …).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportError"
                }
              }
            }
          },
          "403": {
            "description": "The API key does not belong to this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportError"
                }
              }
            }
          },
          "404": {
            "description": "Project not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportError"
                }
              }
            }
          },
          "405": {
            "description": "Method not allowed (only POST is accepted).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ImportError"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {}
}