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

# Submit a verification questionnaire

> Submit the customer's answers to one questionnaire, named by `type`.

| `type` | Answers | Applies to |
|---|---|---|
| `occupation` | `jobTitle`, `industry` | Every customer |
| `agreement` | `acceptTerms`, `signatureName`, `signatureDate` | Customers who accepted under your terms |

Documents are uploaded through [`POST /organization/{organizationId}/verification/documents`](/v2/api-reference/kyc/upload-verification-documents), including a region's tax document.

**`agreement` is a legal declaration, affirmed by `acceptTerms: true`.** By default the customer accepts the agreement themselves in `/idv`. Send `agreement` only if your own terms incorporate ours and you already collected their acceptance. [The customer agreement](/v2/guides/kyc-api#the-customer-agreement) sets out what you are declaring.

**Submit the customer's personal data first**, or this answers `409`. As with document upload, the stage that asks these questions doesn't exist on the customer until then.

**Send `agreement` only once `customerAgreement` is in the requirements list.** It belongs to the last stage, after the identity stage and any proof of address, so do not send it together with `occupation`. An early `agreement` answers `202`, then is refused in the background, and a `kycUpdated` webhook arrives with `needsWork: true`. See [Requirements unlock in stages](/v2/guides/onboarding#requirements-unlock-in-stages).

**Answers `202`, not `200`.** `industry` is resolved against the live category list in the background, so an unrecognized value doesn't fail the request: it leaves the occupation requirement outstanding.



## OpenAPI

````yaml openapi-v2.json POST /organization/{organizationId}/verification/questionnaire
openapi: 3.1.0
info:
  title: Etherfuse FX API
  description: >-
    Partner-facing ramp API, version 2: payment accounts, quotes, orders and
    webhooks.
  license:
    name: Proprietary
  version: 2.0.0
servers:
  - url: https://api.sand.etherfuse.com
    description: Sandbox
security:
  - ApiKeyAuth: []
tags:
  - name: Payment Accounts
    description: >-
      Register the bank accounts and wallets that money moves from and to, and
      read their readiness per rail.
  - name: Quotes
    description: Price a transfer between two registered payment accounts.
  - name: Orders
    description: Create orders from quotes and track them.
  - name: Webhook Subscriptions
    description: Subscribe to webhook events.
  - name: Webhook Events
    description: Payloads Etherfuse sends to your webhook subscriptions.
  - name: Sandbox
    description: Endpoints that work only in sandbox, for testing.
  - name: Assets
    description: The markets and tokens a quote can use, and the balances of a wallet.
  - name: Authentication
    description: >-
      Partner JWT authentication: exchange a JWT for an access token, or launch
      a user into the app.
  - name: KYC
    description: >-
      Submit a customer's verification data, documents and questionnaire
      answers, import a verification they already passed elsewhere, and check
      where their KYC stands.
  - name: KYB
    description: Check where a business organization's KYB stands.
  - name: Lookup
    description: >-
      Public reference data: exchange rates, stablebonds, bond costs, country
      codes.
  - name: Organizations
    description: >-
      Your organization, your default partner fee, and the customer
      organizations you create.
  - name: Members
    description: >-
      The people who belong to a customer business organization and complete its
      KYB.
  - name: Statements
    description: >-
      Monthly revenue share statements for closed months, as a list or as a CSV
      or PDF download.
paths:
  /organization/{organizationId}/verification/questionnaire:
    post:
      tags:
        - KYC
      summary: Submit a verification questionnaire
      description: >-
        Submit the customer's answers to one questionnaire, named by `type`.


        | `type` | Answers | Applies to |

        |---|---|---|

        | `occupation` | `jobTitle`, `industry` | Every customer |

        | `agreement` | `acceptTerms`, `signatureName`, `signatureDate` |
        Customers who accepted under your terms |


        Documents are uploaded through [`POST
        /organization/{organizationId}/verification/documents`](/v2/api-reference/kyc/upload-verification-documents),
        including a region's tax document.


        **`agreement` is a legal declaration, affirmed by `acceptTerms: true`.**
        By default the customer accepts the agreement themselves in `/idv`. Send
        `agreement` only if your own terms incorporate ours and you already
        collected their acceptance. [The customer
        agreement](/v2/guides/kyc-api#the-customer-agreement) sets out what you
        are declaring.


        **Submit the customer's personal data first**, or this answers `409`. As
        with document upload, the stage that asks these questions doesn't exist
        on the customer until then.


        **Send `agreement` only once `customerAgreement` is in the requirements
        list.** It belongs to the last stage, after the identity stage and any
        proof of address, so do not send it together with `occupation`. An early
        `agreement` answers `202`, then is refused in the background, and a
        `kycUpdated` webhook arrives with `needsWork: true`. See [Requirements
        unlock in stages](/v2/guides/onboarding#requirements-unlock-in-stages).


        **Answers `202`, not `200`.** `industry` is resolved against the live
        category list in the background, so an unrecognized value doesn't fail
        the request: it leaves the occupation requirement outstanding.
      operationId: v2SubmitVerificationQuestionnaire
      parameters:
        - $ref: '#/components/parameters/OrganizationId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - title: occupation
                  type: object
                  additionalProperties: false
                  required:
                    - type
                    - jobTitle
                    - industry
                  properties:
                    type:
                      type: string
                      description: >-
                        Which questionnaire these answers are for. New values
                        may be added. If this names a questionnaire that does
                        not exist, the request is rejected and the error tells
                        you which names are valid.
                      enum:
                        - occupation
                      example: occupation
                    jobTitle:
                      type: string
                      description: >-
                        The customer's occupation, free text. Up to 255
                        characters.
                      example: Software Engineer
                    industry:
                      type: string
                      description: >-
                        Occupation category: a `code` from [GET
                        /verification/occupations](/v2/api-reference/kyc/list-occupation-categories).
                        The `label` is not accepted; it is display copy and can
                        be reworded.
                      example: '4430200'
                - title: agreement
                  type: object
                  additionalProperties: false
                  required:
                    - type
                    - acceptTerms
                    - signatureName
                    - signatureDate
                  properties:
                    type:
                      type: string
                      description: >-
                        Which questionnaire these answers are for. New values
                        may be added. If this names a questionnaire that does
                        not exist, the request is rejected and the error tells
                        you which names are valid.
                      enum:
                        - agreement
                      example: agreement
                    acceptTerms:
                      type: boolean
                      enum:
                        - true
                      description: >-
                        Your affirmation of [the
                        declaration](/v2/guides/kyc-api#the-customer-agreement).
                        Must be `true`.
                      example: true
                    signatureName:
                      type: string
                      maxLength: 255
                      description: >-
                        The name the customer typed to sign, in their own words.
                        Printed on their agreement in a cursive face, so it
                        appears as the signature on the executed document.
                      example: Ana Ejemplo
                    signatureDate:
                      type: string
                      format: date
                      description: >-
                        When the customer accepted, `YYYY-MM-DD`. Printed on
                        their agreement as the date of signature. Should be
                        within one day of today's date.
                      example: '2026-08-24'
      responses:
        '202':
          description: >-
            Accepted and being applied. The customer's current verification
            status is returned.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VerificationStatusResponse'
        '400':
          description: >-
            `invalid-request`: validation failed. A missing or unrecognized
            `type`; a blank `jobTitle` or `industry`; an `acceptTerms` that is
            not `true`; a `signatureName` that is blank or over 255 characters;
            or a `signatureDate` that is not `YYYY-MM-DD` or is not within a day
            of today. Also returned for a business organization.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/OrganizationNotFound'
        '409':
          description: >-
            `conflict`, in one of three cases. Nothing has been submitted for
            this customer yet, so submit their personal data first. Or their
            personal data landed but they have not been routed to their
            country's requirements yet; `kycUpdated` fires when routing
            completes, and a retry after it succeeds. Or their verification is
            already approved or denied and cannot be modified.
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Problem'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  parameters:
    OrganizationId:
      name: organizationId
      in: path
      required: true
      description: >-
        The organization this call acts for: your API key's organization or one
        of its customer organizations. Any other id returns `404` `not-found`.
      schema:
        type: string
        format: uuid
  schemas:
    VerificationStatusResponse:
      type: object
      description: >-
        Where the customer's verification stands after a write. `status` is the
        same value `GET /organization/{organizationId}/kyc` reports.
      required:
        - organizationId
        - status
      properties:
        organizationId:
          type: string
          format: uuid
        status:
          $ref: '#/components/schemas/VerificationStatus'
      example:
        organizationId: a1b2c3d4-e5f6-7890-abcd-ef1234567890
        status: inProgress
    Problem:
      type: object
      description: >-
        RFC 9457 problem details. Every v2 error uses this body with content
        type `application/problem+json`. `errors` is present only on
        `validation-error`. `required` and `missing` are present only on
        `registration-info-required`.
      required:
        - type
        - title
        - status
        - detail
        - instance
      properties:
        type:
          type: string
          format: uri
          description: >-
            `https://docs.etherfuse.com/ramp/v2/errors/` followed by the problem
            slug, for example
            `https://docs.etherfuse.com/ramp/v2/errors/quote-expired`. Switch on
            this value.
          example: https://docs.etherfuse.com/ramp/v2/errors/quote-expired
        title:
          type: string
          description: Short summary of the problem type.
          example: Quote expired
        status:
          type: integer
          description: The HTTP status code.
          example: 400
        detail:
          type: string
          description: Human-readable explanation of this occurrence. Do not parse it.
          example: >-
            quote 5e6f7a8b-9c0d-4e1f-8a2b-3c4d5e6f7a8b has expired or does not
            exist
        instance:
          type: string
          description: Unique identifier for this occurrence. Quote it to support.
          example: >-
            tag:etherfuse.com,2026-08-28:R2-10120/0b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d
        errors:
          type: array
          description: Present on `validation-error`. One entry per invalid field.
          items:
            $ref: '#/components/schemas/FieldViolation'
        required:
          type: array
          description: >-
            Present on `registration-info-required`. Every registration field
            the route requires, as JSON Pointers into the request, for example
            `#/registrationInfo/taxId`.
          items:
            type: string
        missing:
          type: array
          description: >-
            Present on `registration-info-required`. The required fields you
            must still send, as JSON Pointers into the request.
          items:
            type: string
    VerificationStatus:
      type: string
      enum:
        - notStarted
        - inProgress
        - submitted
        - approved
        - denied
      description: |-
        - `notStarted`: verification has not started.
        - `inProgress`: the customer started but has not submitted everything.
        - `submitted`: submitted and waiting for review.
        - `approved`: cleared.
        - `denied`: rejected, or a previous approval was revoked.
    FieldViolation:
      type: object
      required:
        - pointer
        - detail
      properties:
        pointer:
          type: string
          description: >-
            JSON Pointer to the field in the request, for example
            `#/accountDetails/clabe`.
          example: '#/accountDetails/clabe'
        detail:
          type: string
          description: What is wrong with the field.
          example: This field is required.
  responses:
    Unauthorized:
      description: >-
        `unauthorized`: the `Authorization` header is missing, not ASCII, or
        does not hold a valid API key.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    OrganizationNotFound:
      description: '`not-found`: your API key cannot act for this organization.'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
    InternalError:
      description: >-
        `internal-error`: an unexpected error on our side. Retry with backoff,
        and quote `instance` to support if it persists.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problem'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: API key sent in the Authorization header, with no `Bearer` prefix.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.