> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gostudio.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Record a generation result

> Finalizes an existing generation log — stores the output URLs and marks the job completed, or marks it failed and refunds the credits that were reserved for it at submit time. Credits are deducted when the generation is submitted, not here; `credits_deducted` echoes the amount already charged. A job can only be finalized once; a second call returns `400 invalid_job_status`. If the log carries a `webhook_url` in its metadata, or you pass one here, the result is delivered to it.

Allowed callers: `user`. An internal service token passes the auth gate but carries no user context, so the job lookup returns `404`.




## OpenAPI

````yaml /openapi.yaml post /api/v2/apps/watermark-remover/record
openapi: 3.0.3
info:
  title: GoStudio Watermark Remover API
  version: 2.0.0
  description: >
    The Watermark Remover endpoints of the GoStudio v2 REST API. Every response
    uses a standard envelope: successes return `{ status, data }`; errors return
    `{ status, error: { type, code, dev, message } }`.


    Every endpoint here takes a **Supabase user JWT** as a Bearer token. An
    `internal` service token is accepted by the auth layer but carries no user
    identity, so it cannot be used to generate or look up a job. The one
    exception is the provider callback, which is authenticated by signature
    rather than by a caller token.
servers:
  - url: https://www.gostudio.ai
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Watermark Remover
    description: AI watermark removal — orchestration, model metadata, and job polling.
  - name: Webhooks
    description: Endpoints called by external services, not by your application.
paths:
  /api/v2/apps/watermark-remover/record:
    post:
      tags:
        - Watermark Remover
      summary: Record a generation result
      description: >
        Finalizes an existing generation log — stores the output URLs and marks
        the job completed, or marks it failed and refunds the credits that were
        reserved for it at submit time. Credits are deducted when the generation
        is submitted, not here; `credits_deducted` echoes the amount already
        charged. A job can only be finalized once; a second call returns `400
        invalid_job_status`. If the log carries a `webhook_url` in its metadata,
        or you pass one here, the result is delivered to it.


        Allowed callers: `user`. An internal service token passes the auth gate
        but carries no user context, so the job lookup returns `404`.
      operationId: recordWatermarkResult
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - generation_log_id
                - status
              properties:
                generation_log_id:
                  type: integer
                  description: The log to finalize. Must belong to the caller.
                  example: 12345
                status:
                  type: string
                  enum:
                    - completed
                    - failed
                output_urls:
                  type: array
                  description: Required when `status` is `completed`; must be non-empty.
                  items:
                    type: string
                    format: uri
                error:
                  type: string
                  description: Failure reason, used when `status` is `failed`.
                webhook_url:
                  type: string
                  format: uri
                  description: >-
                    HTTPS URL to deliver the result to. Overrides the log's
                    stored webhook.
            examples:
              completed:
                summary: Mark completed
                value:
                  generation_log_id: 12345
                  status: completed
                  output_urls:
                    - https://r2.gostudio.ai/g/k7p2qm9x/i/p4w7t1.jpg
              failed:
                summary: Mark failed
                value:
                  generation_log_id: 12345
                  status: failed
                  error: Provider returned no output.
      responses:
        '200':
          description: Result recorded successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: integer
                    example: 200
                  data:
                    $ref: '#/components/schemas/WatermarkRecordResult'
        '400':
          description: >
            Invalid body, unknown status, missing `output_urls` for a completed
            job, or the job was already finalized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                status: 400
                error:
                  type: validation_error
                  code: invalid_job_status
                  dev: 40037
                  message: This job has already been finalized.
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          description: Generation log not found, or not owned by the authenticated user.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                status: 404
                error:
                  type: not_found_error
                  code: generation_log_not_found
                  dev: 40405
                  message: Generation log not found.
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/ServerError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
components:
  schemas:
    WatermarkRecordResult:
      type: object
      properties:
        generation_log_id:
          type: integer
        status:
          type: string
          enum:
            - completed
            - failed
        credits_deducted:
          type: number
          description: >
            The credits already charged for this job when it was submitted, not
            a charge made by this call. Always `0` when `status` is `failed`.
        credit_balance:
          type: number
          description: >
            Always `0` on this endpoint — it does not read your account balance.
            Call `GET /api/v2/me/credit-balance` for the real figure.
          example: 0
        output_urls:
          type: array
          description: Stored CDN URLs. Present on success.
          items:
            type: string
            format: uri
    ErrorResponse:
      type: object
      properties:
        status:
          type: integer
          example: 400
        error:
          type: object
          properties:
            type:
              type: string
              example: validation_error
            code:
              type: string
              example: invalid_input
            dev:
              type: integer
              example: 40001
            message:
              type: string
              example: Some information is invalid.
  responses:
    Unauthorized:
      description: Missing or invalid Authorization Bearer token.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: 401
            error:
              type: authentication_error
              code: unauthorized
              dev: 40100
              message: Missing or invalid Authorization Bearer token.
    Forbidden:
      description: Caller type not allowed for this endpoint.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: 403
            error:
              type: permission_error
              code: forbidden
              dev: 40300
              message: You don't have permission for this action.
    RateLimited:
      description: Too many requests.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: 429
            error:
              type: rate_limit_error
              code: rate_limited
              dev: 42900
              message: You're doing that too often. Please wait a moment.
    ServerError:
      description: Unexpected server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: 500
            error:
              type: system_error
              code: internal_error
              dev: 50000
              message: Something went wrong on our end.
    ServiceUnavailable:
      description: >
        A dependency is temporarily unavailable. Auth-dependent endpoints return
        `service_unavailable` (dev 50300) when the auth provider is down;
        generation endpoints return `model_unavailable` (dev 50301) when the
        model provider is. Both are safe to retry with backoff.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            status: 503
            error:
              type: system_error
              code: service_unavailable
              dev: 50300
              message: Auth service is temporarily unavailable.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >
        Supabase user JWT (or an internal service token). Send as
        `Authorization: Bearer <token>`.

````