# Create job

Advanced compatibility route that creates a sponsorship job and returns one or more slot IDs.

Use this when you intentionally need job-plus-decision orchestration. New Server API integrations should start with POST /v1/placements. Browser-activation requests use a separate public-contract branch with contract_version and job.job_type.

| Method | Path | Authentication | Stability |
| --- | --- | --- | --- |
| POST | /v1/jobs | Secret key, or activation token for browser flows | advanced |

## Request fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| client_id | string | Yes | Project ID (client_id, WAVEBIRD_CLIENT_ID), formatted like wbproj_.... |
| session_id | string | No | Optional stable publisher session identifier. |
| job_type | string: chat, code, image, voice, agent | No | Optional workload category: chat, code, image, voice, agent. Missing values normalize to chat. |
| slots_requested | integer | No | Number of ad slots to request. Defaults to one. |
| prompt | object \| string | No | Optional context. Prefer { topic, text }; raw text is processed only when prompt_shared is true and is never sent to SSPs or advertisers. |
| consent | object | No | Request-level consent flags: semantic_targeting, prompt_shared, gdpr_applies, and consent_source. |

## Response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| job_id | string | Yes | Created job identifier. |
| slot_ids | string[] | Yes | Slots to render or poll for decisions. |
| poll_path_template | string | Yes | Canonical decision polling path. |
| request_id | string | Yes | Support identifier. |

## Errors

| Status | Code | Description |
| --- | --- | --- |
| 401 | unauthorized | Missing key or activation token. |
| 403 | forbidden | Wrong key type for the request. |
| 429 | rate_limited | Key exceeded its rate limit; retry after the Retry-After header. |
| 415 | unsupported_media_type | Non-empty request bodies must use Content-Type: application/json. |
| 400 | validation_error | The request body failed validation. |

## Response example

```json
{
  "job_id": "job_demo_123",
  "slot_ids": ["slot_demo_123"],
  "poll_path_template": "/v1/decisions/{slot_id}",
  "request_id": "req_JVd28x"
}
```

## cURL

```bash
curl -X POST https://api.wavebird.ai/v1/jobs \
  -H "Authorization: Bearer sk_test_wavebird_demo_secret" \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "wbproj_demo_8jK42",
    "session_id": "sess_demo_123",
    "job_type": "chat",
    "slots_requested": 1,
    "consent": {
      "semantic_targeting": false,
      "prompt_shared": false,
      "gdpr_applies": false,
      "consent_source": "wavebird_consent"
    }
  }'
```

## Node

```javascript
const response = await fetch("https://api.wavebird.ai/v1/jobs", {
  method: "POST",
  headers: {
    Authorization: "Bearer sk_test_wavebird_demo_secret",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
  client_id: "wbproj_demo_8jK42",
  session_id: "sess_demo_123",
  job_type: "chat",
  slots_requested: 1,
  consent: {
    semantic_targeting: false,
    prompt_shared: false,
    gdpr_applies: false,
    consent_source: "wavebird_consent"
  }
})
});

const data = await response.json();
console.log(data);
```

## Python

```python
import json
import urllib.request

request = urllib.request.Request(
    "https://api.wavebird.ai/v1/jobs",
    data=json.dumps({"client_id": "wbproj_demo_8jK42", "session_id": "sess_demo_123", "job_type": "chat", "slots_requested": 1}).encode("utf-8"),
    headers={
        "Authorization": "Bearer sk_test_wavebird_demo_secret",
        "Content-Type": "application/json",
    },
    method="POST",
)

with urllib.request.urlopen(request) as response:
    print(response.read().decode("utf-8"))
```
