---
title: "Create a project"
method: POST
path: "/v1/projects"
tags: ["Projects"]
---

# Create a project

`POST /v1/projects`

This endpoint creates a project. Authenticate with a personal API key or JWT and pass the organisation id as the orgID query parameter. The response includes the project and a one-time project API key.

## Query parameters

- `orgID` string, required

## Request body

- ModelsCreateProject
  - `config` ModelsProjectConfig
    - `add_event_id_trace_headers` boolean — Controls of the Event ID and Event Delivery ID Headers are added to the request when events are dispatched to endpoints
    - `allow_unmatched_dynamic_urls` boolean — AllowUnmatchedDynamicURLs lets a dynamic event URL that matches none of the project's endpoint URL templates auto-create an endpoint instead of failing. When false (the default), a project with templates configured rejects unmatched URLs.
    - `circuit_breaker` DatastoreCircuitBreakerConfiguration
      - `consecutive_failure_threshold` integer
      - `error_timeout` integer
      - `failure_threshold` integer
      - `minimum_request_count` integer
      - `observability_window` integer
      - `sample_rate` integer
      - `success_threshold` integer
    - `disable_endpoint` boolean — Controls if the project will disable and endpoint after the retry threshold for an event is reached
    - `max_payload_read_size` integer — Specifies how many bytes and incoming project should read from the ingest request, and how many bytes an outgoing project should from the response of your endpoints Defaults to 50KB.
    - `meta_event` ModelsMetaEventConfiguration
      - `event_type` string[]
      - `is_enabled` boolean
      - `secret` string
      - `type` string
      - `url` string
    - `multiple_endpoint_subscriptions` boolean — MultipleEndpointSubscriptions is used to configure if multiple subscriptions can be created for the endpoint in a project
    - `ratelimit` ModelsRateLimitConfiguration
      - `count` integer
      - `duration` integer
    - `replay_attacks_prevention_enabled` boolean — Controls if your project will add a timestamp to it's webhook signature header to prevent a replay attack, See this blog post[https://getconvoy.io/blog/generating-stripe-like-webhook-signatures] for more]
    - `request_id_header` 'X-Convoy-Idempotency-Key' | ''
    - `search_policy` string — Specify the interval in hours for which the event tokenizer runs
    - `signature` ModelsSignatureConfiguration
      - `header` 'X-Convoy-Signature' | ''
      - `versions` ModelsSignatureVersion[]
        - `created_at` string
        - `encoding` string
        - `hash` string
        - `uid` string
    - `ssl` ModelsSSLConfiguration
      - `enforce_secure_endpoints` boolean
    - `strategy` ModelsStrategyConfiguration
      - `duration` integer
      - `retry_count` integer
      - `type` string
    - `verify_dynamic_events` boolean — VerifyDynamicEvents waits for dynamic endpoint/subscription resolve before acknowledging POST /events/dynamic. When false, the handler returns 201 after enqueue.
  - `logo_url` string
  - `name` string — Project Name
  - `type` string — Project Type, supported values are `outgoing`, `incoming`

## Response `201`

Created

- object
  - `message` string
  - `status` boolean
  - `data` ModelsCreateProjectResponse
    - `api_key` DatastoreAPIKeyResponse
      - `created_at` string
      - `expires_at` string, nullable
      - `key` string
      - `key_type` string
      - `name` string
      - `role` DatastoreRole
        - `app` string
        - `project` string
        - `type` 'instance_admin' | 'organisation_admin' | 'billing_admin' | 'project_admin' | 'project_viewer' | 'api' | ''
      - `uid` string
      - `user_id` string
    - `project` ModelsProjectResponse
      - `config` DatastoreProjectConfig
        - `add_event_id_trace_headers` boolean
        - `allow_unmatched_dynamic_urls` boolean — AllowUnmatchedDynamicURLs lets a dynamic event URL that matches none of the project's endpoint URL templates auto-create an endpoint. Default false rejects unmatched URLs.
        - `circuit_breaker` DatastoreCircuitBreakerConfiguration
          - `consecutive_failure_threshold` integer
          - `error_timeout` integer
          - `failure_threshold` integer
          - `minimum_request_count` integer
          - `observability_window` integer
          - `sample_rate` integer
          - `success_threshold` integer
        - `disable_endpoint` boolean
        - `max_payload_read_size` integer
        - `meta_event` DatastoreMetaEventConfiguration
          - `event_type` string[]
          - `is_enabled` boolean
          - `pub_sub` DatastorePubSubConfig
            - `amqp` DatastoreAmqpPubSubConfig
              - …
            - `google` DatastoreGooglePubSubConfig
              - …
            - `kafka` DatastoreKafkaPubSubConfig
              - …
            - `sqs` DatastoreSQSPubSubConfig
              - …
            - `type` 'sqs' | 'google' | 'kafka' | 'amqp' | ''
            - `workers` integer
          - `secret` string
          - `type` 'http' | 'pub_sub' | ''
          - `url` string
        - `multiple_endpoint_subscriptions` boolean
        - `ratelimit` DatastoreRateLimitConfiguration
          - `count` integer
          - `duration` integer
        - `replay_attacks_prevention_enabled` boolean
        - `request_id_header` 'X-Convoy-Idempotency-Key' | ''
        - `search_policy` string
        - `signature` DatastoreSignatureConfiguration
          - `header` 'X-Convoy-Signature' | ''
          - `versions` DatastoreSignatureVersion[]
            - `created_at` string
            - `encoding` 'base64' | 'hex' | ''
            - `hash` string
            - `uid` string
        - `ssl` DatastoreSSLConfiguration
          - `enforce_secure_endpoints` boolean
        - `strategy` DatastoreStrategyConfiguration
          - `duration` integer
          - `retry_count` integer
          - `type` 'linear' | 'exponential' | ''
        - `verify_dynamic_events` boolean — VerifyDynamicEvents waits for endpoint/subscription resolve before returning 2xx from POST /events/dynamic. Default false keeps 201-on-queue.
      - `created_at` string
      - `deleted_at` string, nullable
      - `logo_url` string
      - `name` string
      - `organisation_id` string
      - `retained_events` integer
      - `statistics` DatastoreProjectStatistics
        - `endpoints_exist` boolean
        - `events_exist` boolean
        - `sources_exist` boolean
        - `subscriptions_exist` boolean
      - `type` 'outgoing' | 'incoming' | ''
      - `uid` string
      - `updated_at` string

## Other responses

- `400` — Bad Request
- `401` — Unauthorized
- `402` — Payment Required
- `403` — Forbidden
- `404` — Not Found

---

[API](https://skmtc.net/frain-dev/apis/convoy-api-reference.md) · [All operations](https://skmtc.net/frain-dev/apis/convoy-api-reference/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/frain-dev/convoy-api-reference/versions/dbd5b4f9cf13/schema)
