---
openapi: 3.0.1
info:
  title: Worders API V1
  version: v1
  description: Worders API endpoints (freelance invoice verification, webhooks, ...).
paths:
  "/V1/customers":
    get:
      summary: Search customers by name
      tags:
      - Customers
      description: List or search customers. Used by the budget export scenario to
        resolve a customer name to a Plunet identifier before calling /V1/orders.
      security:
      - cookie_session: []
      - bearer_auth: []
      parameters:
      - name: q
        in: query
        required: false
        schema:
          type: string
        description: Partial name match (case-insensitive). Empty returns all customers.
      responses:
        '200':
          description: matching customers
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/Customer"
        '401':
          description: unauthenticated
  "/V1/freelancers":
    get:
      summary: Search freelancers by name
      tags:
      - Freelancers
      description: Search freelancers by full or partial name. Used by the freelance
        invoice verification scenario to locate the user behind an invoice.
      security:
      - cookie_session: []
      - bearer_auth: []
      parameters:
      - name: q
        in: query
        required: true
        schema:
          type: string
        description: Full or partial name (matches full_name, first_name, last_name).
          Restricted to users with user_type = author.
      responses:
        '200':
          description: matching freelancers
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/Freelancer"
        '401':
          description: unauthenticated
  "/V1/invoices":
    get:
      summary: List invoices
      tags:
      - Invoices
      description: Returns invoices mirroring the invoice PDF. Items are flattened
        with grouping fields (requester, order_reference, project_name) so the consumer
        can group freely.
      security:
      - cookie_session: []
      - bearer_auth: []
      parameters:
      - name: customer_plunet_id
        in: query
        required: false
        schema:
          type: integer
      - name: status
        in: query
        required: false
        schema:
          type: string
      - name: updated_since
        in: query
        required: false
        schema:
          type: string
          format: date-time
      - name: page
        in: query
        required: false
        schema:
          type: integer
          default: 1
      - name: per_page
        in: query
        required: false
        schema:
          type: integer
          default: 50
      responses:
        '200':
          description: matching invoices
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/Invoice"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
        '401':
          description: unauthenticated
  "/V1/invoices/{id}":
    parameters:
    - name: id
      in: path
      required: true
      schema:
        type: string
      description: Plunet invoice id (e.g. "2847") or invoice_number (e.g. "I-2847").
    get:
      summary: Show a single invoice
      tags:
      - Invoices
      security:
      - cookie_session: []
      - bearer_auth: []
      responses:
        '200':
          description: lookup by decorated invoice_number
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Invoice"
        '404':
          description: unknown invoice
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/V1/orders":
    get:
      summary: List orders eligible for the weekly client budget export
      tags:
      - Orders
      description: Returns orders with their items. Supports filtering by customer
        (Plunet id), completion state (all items approved), and incremental polling
        via updated_since.
      security:
      - cookie_session: []
      - bearer_auth: []
      parameters:
      - name: customer_plunet_id
        in: query
        required: false
        schema:
          type: integer
        description: Filter to a single customer (matches Order.customer_id, which
          stores the customer Plunet id).
      - name: all_items_approved
        in: query
        required: false
        schema:
          type: boolean
        description: When true, keep only orders that have at least one item AND whose
          every item is in 'approved' status.
      - name: updated_since
        in: query
        required: false
        schema:
          type: string
          format: date-time
        description: ISO 8601 timestamp. Restricts to orders updated since this date.
      - name: page
        in: query
        required: false
        schema:
          type: integer
          default: 1
      - name: per_page
        in: query
        required: false
        schema:
          type: integer
          default: 50
      responses:
        '200':
          description: matching orders
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/Order"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
        '401':
          description: unauthenticated
    post:
      summary: Create a Plunet order with items
      tags:
      - Orders
      description: 'Create an Order + OrderItems in Plunet from Airtable-mapped data.
        Idempotent on `external_id`: the second POST returns 200 with the existing
        order.'
      security:
      - bearer_auth: []
      parameters: []
      responses:
        '201':
          description: order created in Plunet
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/OrderCreateResponse"
        '200':
          description: returns the existing order when external_id matches
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/OrderCreateResponse"
        '404':
          description: unknown customer
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
        '400':
          description: missing order key
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/OrderCreateRequest"
        required: true
  "/V1/orders/{id}":
    parameters:
    - name: id
      in: path
      required: true
      schema:
        type: string
      description: Plunet order id (e.g. "O-100") or order_reference (e.g. "ORD-2025-789").
    get:
      summary: Show a single order
      tags:
      - Orders
      security:
      - cookie_session: []
      - bearer_auth: []
      responses:
        '200':
          description: lookup by plunet_id
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Order"
        '404':
          description: quote id should not resolve
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/V1/freelancers/{freelancer_id}/purchase_orders":
    parameters:
    - name: freelancer_id
      in: path
      required: true
      schema:
        type: string
        format: uuid
    get:
      summary: List purchase orders for a freelancer
      tags:
      - PurchaseOrders
      description: List purchase orders attached to a freelancer over a period. By
        default `deleted` and `deprecated` POs are excluded.
      security:
      - cookie_session: []
      - bearer_auth: []
      parameters:
      - name: period_start
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: period_end
        in: query
        required: false
        schema:
          type: string
          format: date
      - name: status
        in: query
        required: false
        style: form
        explode: true
        schema:
          type: array
          items:
            type: string
        description: Optional status filter, e.g. status[]=generated&status[]=paid
      - name: page
        in: query
        required: false
        schema:
          type: integer
          default: 1
      - name: per_page
        in: query
        required: false
        schema:
          type: integer
          default: 50
      responses:
        '200':
          description: 'pagination: second page returns correct slice'
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/PurchaseOrderSummary"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
        '404':
          description: freelancer not found
  "/V1/purchase_orders/{po_number}":
    parameters:
    - name: po_number
      in: path
      required: true
      schema:
        type: string
      description: PO number, e.g. PO-2025-001234
    get:
      summary: PO detail with all its jobs
      tags:
      - PurchaseOrders
      description: Returns the PO with its freelancer and all attached jobs (price,
        currency, language pair, order reference, delivery date). Used when an invoice
        cites a PO number.
      security:
      - cookie_session: []
      - bearer_auth: []
      responses:
        '200':
          description: PO found
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/PurchaseOrderDetail"
        '404':
          description: PO not found
        '401':
          description: unauthenticated
  "/V1/quotes":
    get:
      summary: List quotes
      tags:
      - Quotes
      description: Returns quotes mirroring the quote PDF. Supports filtering by customer,
        status, and incremental polling via updated_since.
      security:
      - cookie_session: []
      - bearer_auth: []
      parameters:
      - name: customer_plunet_id
        in: query
        required: false
        schema:
          type: integer
      - name: status
        in: query
        required: false
        schema:
          type: string
      - name: updated_since
        in: query
        required: false
        schema:
          type: string
          format: date-time
      - name: page
        in: query
        required: false
        schema:
          type: integer
          default: 1
      - name: per_page
        in: query
        required: false
        schema:
          type: integer
          default: 50
      responses:
        '200':
          description: matching quotes
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/Quote"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
        '401':
          description: unauthenticated
    post:
      summary: Create a Plunet quote with items
      tags:
      - Quotes
      description: 'Create a Quote + OrderItems in Plunet from Airtable-mapped data.
        Idempotent on `external_id`: the second POST returns 200 with the existing
        quote.'
      security:
      - bearer_auth: []
      parameters: []
      responses:
        '201':
          description: quote created in Plunet
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/QuoteCreateResponse"
        '200':
          description: returns the existing quote when external_id matches
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/QuoteCreateResponse"
        '404':
          description: unknown customer
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
        '400':
          description: missing quote key
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/QuoteCreateRequest"
        required: true
  "/V1/quotes/{id}":
    parameters:
    - name: id
      in: path
      required: true
      schema:
        type: string
      description: Plunet quote id (e.g. "Q-1000") or order_reference (e.g. "Q-1446-01").
    get:
      summary: Show a single quote
      tags:
      - Quotes
      security:
      - cookie_session: []
      - bearer_auth: []
      responses:
        '200':
          description: lookup by plunet_id
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/Quote"
        '404':
          description: unknown quote
          content:
            application/json:
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/V1/customers/{customer_id}/templates":
    parameters:
    - name: customer_id
      in: path
      required: true
      schema:
        type: integer
      description: Customer's Plunet id (matches the `id` field in /V1/customers responses).
    get:
      summary: List Plunet order templates available for a customer
      tags:
      - Templates
      description: Returns Plunet `getTemplateList` results filtered by the customer's
        Plunet id. Used by the Adobe order-creation scenario to offer a template before
        POST /V1/orders.
      security:
      - cookie_session: []
      - bearer_auth: []
      responses:
        '200':
          description: templates list (scoped to customer)
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/PlunetTemplate"
components:
  securitySchemes:
    cookie_session:
      type: apiKey
      in: cookie
      name: _worders_session
      description: Authenticated Devise session cookie (api.worders.net).
    bearer_auth:
      type: http
      scheme: bearer
      description: 'Service API key issued from the admin UI. Sent as `Authorization:
        Bearer wrd_live_…`.'
  schemas:
    Freelancer:
      type: object
      properties:
        id:
          type: string
          format: uuid
        internal_id:
          type: string
          format: uuid
          nullable: true
          description: Same as id
        full_name:
          type: string
        first_name:
          type: string
        last_name:
          type: string
        email:
          type: string
          format: email
        user_type:
          type: string
          example: author
      required:
      - id
      - full_name
      - email
      - user_type
    PurchaseOrderSummary:
      type: object
      properties:
        id:
          type: string
          format: uuid
        internal_id:
          type: string
          format: uuid
          nullable: true
          description: Same as id
        po_number:
          type: string
          example: PO-2025-001234
        currency:
          type: string
          example: EUR
        status:
          type: string
          example: generated
        created_at:
          type: string
          format: date-time
        total_amount:
          type: number
          format: float
          example: 1250.0
        jobs_count:
          type: integer
          example: 5
        freelancer:
          type: object
          properties:
            id:
              type: string
              format: uuid
            full_name:
              type: string
    Job:
      type: object
      properties:
        id:
          type: string
          format: uuid
        internal_id:
          type: string
          format: uuid
          nullable: true
          description: Same as id
        plunet_id:
          type: string
          nullable: true
        job_no:
          type: string
          nullable: true
        short_job_type:
          type: string
          nullable: true
          example: TRA
        status:
          type: string
          example: approved
        price:
          type: number
          format: float
          nullable: true
        currency:
          type: string
          nullable: true
        language_pair:
          type: string
          nullable: true
          example: en > fr
        order_reference:
          type: string
          nullable: true
        delivered_on:
          type: string
          format: date-time
          nullable: true
    PurchaseOrderDetail:
      type: object
      properties:
        id:
          type: string
          format: uuid
        internal_id:
          type: string
          format: uuid
          nullable: true
          description: Same as id
        po_number:
          type: string
        currency:
          type: string
        status:
          type: string
        created_at:
          type: string
          format: date-time
        total_amount:
          type: number
          format: float
        freelancer:
          type: object
          nullable: true
          properties:
            id:
              type: string
              format: uuid
            full_name:
              type: string
        jobs:
          type: array
          items:
            "$ref": "#/components/schemas/Job"
    Customer:
      type: object
      properties:
        id:
          type: integer
          nullable: true
          example: 12345
          description: Plunet customer id
        name:
          type: string
          example: AcmeCorp
      required:
      - name
    OrderItem:
      type: object
      properties:
        id:
          type: string
          nullable: true
          example: I-44556
          description: Plunet item id
        plunet_id:
          type: string
          nullable: true
          description: Same as id
        language_source:
          type: string
          nullable: true
          example: en-US
        language_target:
          type: string
          nullable: true
          example: fr-FR
        quantity:
          type: number
          format: float
          nullable: true
          example: 1200
        price:
          type: number
          format: float
          nullable: true
          example: 1372.64
          description: Item price in internal currency (EUR).
        currency:
          type: string
          nullable: true
          example: EUR
          description: Internal currency (always EUR).
        client_price:
          type: number
          format: float
          nullable: true
          example: 1500.0
          description: Item price in the customer-facing currency (matches the PDF).
        client_currency:
          type: string
          nullable: true
          example: USD
          description: Customer-facing currency on the item.
        status:
          type: string
          example: approved
    Order:
      type: object
      properties:
        id:
          type: string
          nullable: true
          example: O-78901
          description: Plunet order id
        plunet_id:
          type: string
          nullable: true
          description: Same as id
        order_reference:
          type: string
          example: ORD-2025-789
        quote_number:
          type: string
          nullable: true
          example: Q-1446-01
          description: Source quote's order_reference, if the order originated from
            a quote.
        project_name:
          type: string
          nullable: true
        project_manager_memo:
          type: string
          nullable: true
        properties:
          type: object
          nullable: true
          additionalProperties: true
          description: Internal metadata (TMS jobs, CAT info, job dates).
        status:
          type: string
          nullable: true
          example: completed
        all_items_approved:
          type: boolean
          example: true
        client:
          "$ref": "#/components/schemas/Customer"
          nullable: true
        contact_person:
          type: object
          nullable: true
          properties:
            id:
              type: string
              format: uuid
            full_name:
              type: string
            email:
              type: string
              format: email
        currency:
          type: string
          nullable: true
          example: EUR
          description: Internal currency (always EUR).
        total_price:
          type: number
          format: float
          nullable: true
          example: 4117.92
          description: Order total in internal currency (EUR).
        client_ccy:
          type: string
          nullable: true
          example: USD
          description: Customer-facing currency (matches the PDF invoice/quote).
        total_price_in_client_ccy:
          type: number
          format: float
          nullable: true
          example: 4500.0
          description: Order total in the customer-facing currency.
        due_date:
          type: string
          format: date-time
          nullable: true
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
        items:
          type: array
          items:
            "$ref": "#/components/schemas/OrderItem"
    PaginationMeta:
      type: object
      properties:
        total:
          type: integer
          example: 42
        page:
          type: integer
          example: 1
        per_page:
          type: integer
          example: 50
    PriceLineEntry:
      type: object
      properties:
        price_unit_id:
          type: integer
          nullable: true
          example: 12
        service:
          type: string
          nullable: true
          example: Culturalization
        unit:
          type: string
          nullable: true
          example: Hour
        amount:
          type: number
          format: float
          example: 0.55
        unit_price:
          type: number
          format: float
          example: 90.0
        total:
          type: number
          format: float
          example: 49.5
    QuoteItem:
      type: object
      properties:
        id:
          type: string
          nullable: true
          example: I-44556
          description: Plunet item id
        plunet_id:
          type: string
          nullable: true
          description: Same as id
        language_source:
          type: string
          nullable: true
          example: en-US
        language_target:
          type: string
          nullable: true
          example: fr-FR
        client_price:
          type: number
          format: float
          nullable: true
          example: 49.5
          description: Item price in the customer-facing currency.
        status:
          type: string
          nullable: true
          example: invoiced
        price_line:
          type: array
          items:
            "$ref": "#/components/schemas/PriceLineEntry"
    QuoteCustomer:
      type: object
      nullable: true
      properties:
        plunet_id:
          type: integer
          nullable: true
          example: 12345
        name:
          type: string
          example: EBSCO
        address:
          type: string
          nullable: true
          example: |-
            EBSCO
            10 Estes Street
            01938 Ipswich
            United States
    Quote:
      type: object
      properties:
        id:
          type: string
          example: Q-1446-01
          description: Quote order_reference
        plunet_id:
          type: string
          nullable: true
          description: Plunet quote id
        order_reference:
          type: string
          nullable: true
          description: Same as id; canonical reference like "Q-1446-01"
        created_at:
          type: string
          format: date-time
        valid_until:
          type: string
          format: date
          nullable: true
          description: Quote validity end date (created_at + 1 month).
        status:
          type: string
          nullable: true
          example: pending
        project_name:
          type: string
          nullable: true
        client_ccy:
          type: string
          nullable: true
          example: USD
        price_in_client_ccy:
          type: number
          format: float
          nullable: true
          example: 5778.0
        customer:
          "$ref": "#/components/schemas/QuoteCustomer"
        contact_person:
          type: object
          nullable: true
          properties:
            full_name:
              type: string
              example: Amber Russell
            email:
              type: string
              format: email
              example: amberrussell@ebsco.com
        project_manager:
          type: object
          nullable: true
          properties:
            full_name:
              type: string
              example: Jane Doe
        items:
          type: array
          items:
            "$ref": "#/components/schemas/QuoteItem"
    InvoiceLine:
      type: object
      description: A single billable line on the invoice, flattened with grouping
        fields (requester, order_reference, project_name) so the consumer can group
        freely.
      properties:
        requester:
          type: string
          nullable: true
          example: Amber Russell
          description: Order contact person full name.
        order_reference:
          type: string
          nullable: true
          example: O-9703
          description: Falls back to the originating quote order_reference.
        project_name:
          type: string
          nullable: true
          example: Weekly Researcher task - May 5
        description:
          type: string
          nullable: true
        total_price:
          type: number
          format: float
          nullable: true
          example: 9.0
          description: Line total in the customer-facing currency.
        order_item:
          "$ref": "#/components/schemas/QuoteItem"
          nullable: true
    Invoice:
      type: object
      properties:
        invoice_number:
          type: string
          nullable: true
          example: Worders-Invoice2847
        created_at:
          type: string
          format: date-time
        payment_due_date:
          type: string
          format: date
          nullable: true
        payment_date:
          type: string
          format: date
          nullable: true
        description:
          type: string
          nullable: true
          example: Collective invoice - May 2026
        po_number:
          type: string
          nullable: true
        client_ccy:
          type: string
          nullable: true
          example: USD
        status:
          type: string
          nullable: true
          example: outstanding
        totals:
          type: object
          properties:
            net:
              type: number
              format: float
              nullable: true
              example: 5778.0
            outgoing:
              type: number
              format: float
              nullable: true
              example: 5778.0
            paid:
              type: number
              format: float
              nullable: true
              example: 0
        customer:
          "$ref": "#/components/schemas/QuoteCustomer"
        payment_request_id:
          type: string
          format: uuid
          nullable: true
        items:
          type: array
          items:
            "$ref": "#/components/schemas/InvoiceLine"
    PlunetTemplate:
      type: object
      properties:
        id:
          type: integer
          example: 42
        name:
          type: string
          example: Adobe — Standard Translation
        description:
          type: string
          nullable: true
          example: Default template for Adobe orders
    OrderCreateRequest:
      type: object
      required:
      - order
      properties:
        order:
          type: object
          required:
          - customer
          - project_manager
          - items
          properties:
            external_id:
              type: string
              example: rec_AIRTABLE_RECORD_ID
              description: Airtable record id, used for idempotence
            customer:
              type: object
              description: Identify the customer by plunet_id, id (uuid) or name (one
                of)
              properties:
                plunet_id:
                  type: integer
                  example: 12345
                id:
                  type: string
                  format: uuid
                name:
                  type: string
            project_manager:
              type: object
              description: Identify the PM by email or id (uuid)
              properties:
                email:
                  type: string
                  format: email
                  example: pm@worders.net
                id:
                  type: string
                  format: uuid
            contact_person:
              type: object
              description: Optional. Identify by plunet_id (Plunet customer_contact_id)
                or email
              properties:
                plunet_id:
                  type: integer
                  example: 67890
                email:
                  type: string
                  format: email
            project_name:
              type: string
              example: Adobe — Acrobat Q2 update
            subject:
              type: string
              example: Translation of help articles
            currency:
              type: string
              example: EUR
            order_date:
              type: string
              format: date
              nullable: true
            delivery_deadline:
              type: string
              format: date-time
              nullable: true
            rate:
              type: number
              format: float
              nullable: true
              example: 0.1
            project_manager_memo:
              type: string
              nullable: true
            template_id:
              type: integer
              nullable: true
              example: 42
            items:
              type: array
              items:
                type: object
                properties:
                  language_source:
                    type: string
                    example: en-US
                  language_target:
                    type: string
                    example: fr-FR
                  quantity:
                    type: number
                    format: float
                    example: 1200
                  description:
                    type: string
                    nullable: true
                  delivery_date:
                    type: string
                    format: date
                    nullable: true
    OrderCreateResponse:
      type: object
      properties:
        id:
          type: string
          nullable: true
          example: O-78901
          description: Plunet order id
        plunet_id:
          type: string
          nullable: true
          description: Same as id
        created:
          type: boolean
          description: true when newly created, false when idempotent hit on existing
            external_id
        order_reference:
          type: string
          nullable: true
        status:
          type: string
          nullable: true
          example: in_preparation
        external_id:
          type: string
          nullable: true
        items:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                nullable: true
                description: Plunet item id
              language_source:
                type: string
                nullable: true
              language_target:
                type: string
                nullable: true
        urls:
          type: object
          properties:
            worders_admin:
              type: string
              format: uri
            plunet:
              type: string
              format: uri
              nullable: true
    QuoteCreateRequest:
      type: object
      required:
      - quote
      properties:
        quote:
          type: object
          required:
          - customer
          - project_manager
          - items
          properties:
            external_id:
              type: string
              example: rec_AIRTABLE_RECORD_ID
              description: Airtable record id, used for idempotence
            customer:
              type: object
              description: Identify the customer by plunet_id, id (uuid) or name (one
                of)
              properties:
                plunet_id:
                  type: integer
                  example: 12345
                id:
                  type: string
                  format: uuid
                name:
                  type: string
            project_manager:
              type: object
              description: Identify the PM by email or id (uuid)
              properties:
                email:
                  type: string
                  format: email
                  example: pm@worders.net
                id:
                  type: string
                  format: uuid
            contact_person:
              type: object
              description: Optional. Identify by plunet_id (Plunet customer_contact_id)
                or email
              properties:
                plunet_id:
                  type: integer
                  example: 67890
                email:
                  type: string
                  format: email
            project_name:
              type: string
              example: Adobe — Acrobat Q2 update
            subject:
              type: string
              example: Translation of help articles
            currency:
              type: string
              example: EUR
            order_date:
              type: string
              format: date
              nullable: true
            delivery_deadline:
              type: string
              format: date-time
              nullable: true
            rate:
              type: number
              format: float
              nullable: true
              example: 0.1
            project_manager_memo:
              type: string
              nullable: true
            template_id:
              type: integer
              nullable: true
              example: 42
            items:
              type: array
              items:
                type: object
                properties:
                  language_source:
                    type: string
                    example: en-US
                  language_target:
                    type: string
                    example: fr-FR
                  quantity:
                    type: number
                    format: float
                    example: 1200
                  description:
                    type: string
                    nullable: true
                  delivery_date:
                    type: string
                    format: date
                    nullable: true
    QuoteCreateResponse:
      type: object
      properties:
        id:
          type: string
          nullable: true
          example: Q-12345
          description: Plunet quote id
        plunet_id:
          type: string
          nullable: true
          description: Same as id
        created:
          type: boolean
          description: true when newly created, false when idempotent hit on existing
            external_id
        order_reference:
          type: string
          nullable: true
          example: Q-1446-01
        status:
          type: string
          nullable: true
          example: in_preparation
        external_id:
          type: string
          nullable: true
        items:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
                nullable: true
                description: Plunet item id
              language_source:
                type: string
                nullable: true
              language_target:
                type: string
                nullable: true
        urls:
          type: object
          properties:
            worders_admin:
              type: string
              format: uri
            plunet:
              type: string
              format: uri
              nullable: true
    ErrorResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
            details:
              type: object
              nullable: true
          required:
          - code
          - message
      required:
      - error
servers:
- url: https://api.worders.net
