---
title: "Upsert My Profile"
method: PUT
path: "/api/profile"
tags: ["profiles"]
---

# Upsert My Profile

`PUT /api/profile`

## Request

- Base URL: `https://api.parlel.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.parlel.com/api/profile`
- Auth: none declared

Create or replace the signed-in user's profile.

200 on both create and update, deliberately — not 201 on create. The client
treats this as one "save" action and branching its success handler on a status
code would gain it nothing that ``exists`` in the body does not already say.

Idempotent in the sense that matters: the row is keyed by ``user_id``, so
saving twice updates one row and can never produce two profiles for one
person. That is a primary key doing the work rather than a code path
remembering to.

## Headers

- `authorization` string, nullable

## Request body

- ProfileUpsert: The whole profile. ``PUT`` semantics: absent means cleared, not unchanged. A PUT and not a PATCH because this is a form. The editor holds every field on screen and submits all of them, so "the body is the new state" is both the honest description and the one that lets a user delete their headline — something a PATCH cannot express without a null-versus-absent convention that every client then has to get right. The consequence is worth stating plainly for whoever writes that client: **omitting ``is_public`` sets it to false.** A partial body does not preserve the old visibility, it unpublishes.
  - `handle` string, required
  - `display_name` string, nullable
  - `headline` string, nullable
  - `bio` string, nullable
  - `location` string, nullable
  - `company` string, nullable
  - `role` string, nullable
  - `open_to` string, nullable
  - `languages` string, nullable
  - `website_url` string, nullable
  - `linkedin_url` string, nullable
  - `x_url` string, nullable
  - `github_url` string, nullable
  - `work_email` string, nullable
  - `phone` string, nullable
  - `calendar_url` string, nullable
  - `skills` string[]
  - `positions` PositionIn[]
    - `title` string, required
    - `company` string, required
    - `location` string, nullable
    - `start_year` integer, nullable
    - `start_month` integer, nullable
    - `end_year` integer, nullable
    - `end_month` integer, nullable
    - `description` string, nullable
  - `education` EducationIn[]
    - `school` string, required
    - `degree` string, nullable
    - `field_of_study` string, nullable
    - `start_year` integer, nullable
    - `end_year` integer, nullable
    - `description` string, nullable
  - `contact_visibility` 'open' | 'paid' | 'private'
  - `unlock_price_cents` integer, nullable
  - `call_price_cents` integer, nullable
  - `accepts_hiring_messages` boolean
  - `is_public` boolean
  - `residence_country` string, nullable
  - `needs_sponsorship` string, nullable
  - `gender` string, nullable
  - `ethnicity` string, nullable
  - `veteran_status` string, nullable
  - `disability_status` string, nullable
  - `sexual_orientation` string, nullable

## Response `200`

Successful Response

- object

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/parlel/apis/parlel-api.md) · [All operations](https://skmtc.dev/parlel/apis/parlel-api/llms.txt) · [OpenAPI document](https://skmtc.dev/parlel/apis/parlel-api/revisions/4d41a8f5cfc9?raw)
