{"revision":"0ed62d2c742f8e20","language":"en","entry":{"id":"create-organisation","kind":"endpoint","group":"manage","title":"Create an organisation","method":"POST","path":"/v1/organizations","paths":[],"summary":"Publish an organisation’s first record, signed by its founder’s active person key.","response":"201 with n, id, url, token, version, commitment, logIndex, publishedAt and checkpoint. The response follows witnessed publication.","parameters":[],"sample":"/v1/organizations","access":"signed","base":"directory","notes":["On a log in format 2 the body is {label, body, signature, pictureData?}, with clientSalt and saltTicket required for version 1; a record is refused with wrong_format."],"errors":["400 invalid_alias","400 invalid_json","400 invalid_name","400 invalid_nonce","400 invalid_parameter","400 invalid_signature_alg","400 invalid_timestamp","400 wrong_format","401 invalid_signature","401 missing_signature","401 stale_timestamp","403 identity_banned","403 key_banned","403 key_mismatch","404 not_found","409 account_locked","409 alias_quarantined","409 alias_reserved","409 alias_taken","409 already_member","409 grant_used","409 identity_exists","409 invitation_withdrawn","409 key_already_used","409 replayed_nonce","409 salt_ticket_invalid","409 takeover_already_open","409 version_conflict","410 erased","413 payload_too_large","422 grant_expired","422 invalid_grant","422 invalid_logo","422 invalid_op","422 invalid_record","422 invalid_record_signature","422 label_mismatch","422 last_owner","422 links_need_verification","422 membership_needs_grant","422 not_an_organization","429 rate_limited","500 internal_error","502 log_mismatch","503 busy","503 log_unavailable"],"related":["signed-requests"],"sections":[{"kind":"code","language":"shell","code":"curl -fsS -X POST \\\n  -H \"X-Public-Key: $PUBLIC_KEY\" \\\n  -H \"X-Signature: $REQUEST_SIGNATURE\" --json @request.json \\\n  \"https://veil.rip/v1/organizations\""}],"bodyFields":[{"name":"record","description":"The complete canonical identity or organisation record, including its history fields.","in":"body","required":true},{"name":"signature","description":"The record signature, separate from the request signature header.","in":"body","required":true},{"name":"logoData","description":"The image that record.logo names by hash, in standard padded base64 on one line. Required when the version brings a new image. With an unchanged image it can be left out, and if sent it must match.","in":"body","required":false},{"name":"nonce","description":"A fresh 16 to 128 character nonce using letters, digits, underscore or hyphen.","in":"body","required":true},{"name":"timestamp","description":"Unix milliseconds within two minutes of the server clock.","in":"body","required":true},{"name":"clientSalt, saltTicket","description":"Optional pair for the first version. Request the ticket before drawing the client salt.","in":"body","required":false},{"name":"label","description":"Format 2: the label as a JSON object; the server encodes it canonically and checks the signature on those bytes.","in":"body","required":false},{"name":"body","description":"Format 2: the body as a JSON object, its hash in label.body.","in":"body","required":false},{"name":"pictureData","description":"Format 2: the bytes of a new picture the body names by hash, in standard padded base64.","in":"body","required":false}],"live":false,"responses":[{"status":201,"contentType":"application/json","description":"201 with n, id, url, token, version, commitment, logIndex, publishedAt and checkpoint. The response follows witnessed publication.","fields":[{"name":"n","type":"integer","description":"Permanent card number."},{"name":"id","type":"string","description":"Version-one commitment in hex."},{"name":"url","type":"string","description":"Permanent card URL."},{"name":"token","type":"string","description":"Stable log pseudonym in base64url."},{"name":"version","type":"integer","description":"Published version number."},{"name":"commitment","type":"string","description":"This version’s commitment in hex."},{"name":"logIndex","type":"integer","description":"Zero-based log index."},{"name":"publishedAt","type":"string","description":"Earliest cosignature time at publication."},{"name":"checkpoint","type":"Checkpoint","description":"First checkpoint covering the version."}]}],"responseObjects":[{"id":"checkpoint","title":"Checkpoint","fields":[{"name":"size","type":"integer","description":"Number of leaves in the signed tree."},{"name":"root","type":"string","description":"Root hash in base64."},{"name":"note","type":"string","description":"Full signed note, including log and witness signatures."}],"typeName":"Checkpoint"}],"errorFormat":"json","errorDetails":[{"status":400,"code":"invalid_alias","description":"The alias does not meet the ASCII name rules.","action":"Use 3 to 32 lowercase ASCII letters, digits, hyphens or underscores; start with a letter and end with a letter or digit.","scope":"endpoint"},{"status":400,"code":"invalid_json","description":"The body is not a JSON object, contains duplicate keys or has trailing data.","action":"Send one valid JSON object with `Content-Type` application/json.","scope":"endpoint"},{"status":400,"code":"invalid_name","description":"A name contains invisible, direction-control or unsupported format characters.","action":"Use a visible name in the accepted Unicode form and sign the corrected request.","scope":"endpoint"},{"status":400,"code":"invalid_nonce","description":"The signed-request nonce has an invalid format.","action":"Generate a fresh 16 to 128-character nonce using letters, digits, _ or -.","scope":"common"},{"status":400,"code":"invalid_parameter","description":"A path, query or body field is missing, malformed or outside its accepted range.","action":"Correct the field named in `error.message` before sending again.","scope":"endpoint"},{"status":400,"code":"invalid_signature_alg","description":"`X-Signature-Alg` is unsupported.","action":"Use a supported signing algorithm and matching key/signature encoding.","scope":"common"},{"status":400,"code":"invalid_timestamp","description":"The signed-request timestamp is not Unix milliseconds.","action":"Use an integer Unix timestamp in milliseconds and sign the corrected request.","scope":"common"},{"status":400,"code":"wrong_format","description":"The request or the read belongs to the other log format than this server’s: a v1 record on a format 2 log, or a format 2 read on a format 1 log.","action":"Read `format` in GET /v1/log (absent means 1) and send the shape of that format.","scope":"endpoint"},{"status":401,"code":"invalid_signature","description":"The HTTP request signature does not verify.","action":"Sign the exact method, path and body bytes, without changing them afterwards.","scope":"common"},{"status":401,"code":"missing_signature","description":"The request requires a device signature and its headers are missing or unreadable.","action":"Send `X-Public-Key`, `X-Signature` and the signed-request metadata. An API key does not replace a device signature.","scope":"common"},{"status":401,"code":"stale_timestamp","description":"The signed timestamp is outside the accepted clock window.","action":"Compare the server Date header with your clock, then generate a fresh nonce, timestamp and signature.","scope":"common"},{"status":403,"code":"identity_banned","description":"The acting identity is suspended by Veil staff.","action":"Wait for the restriction to end or ask staff to review it.","scope":"endpoint"},{"status":403,"code":"key_banned","description":"The device signing key is suspended by Veil staff.","action":"Use an authorised active key or ask staff to review the restriction.","scope":"common"},{"status":403,"code":"key_mismatch","description":"The signing key does not have authority over this card or operation.","action":"Use an active device key with the required owner or member role.","scope":"endpoint"},{"status":404,"code":"not_found","description":"The requested card, key, alias, code or resource was not found.","action":"Check the identifier. Temporary codes and previews may already have expired or been used.","scope":"endpoint"},{"status":409,"code":"account_locked","description":"Moderation prevents this account from being claimed.","action":"Check the current card’s public moderation state.","scope":"endpoint"},{"status":409,"code":"alias_quarantined","description":"The alias is in its 30-day release quarantine.","action":"Inspect `reusableAt` and the previous holder through the alias endpoint.","scope":"endpoint"},{"status":409,"code":"alias_reserved","description":"The chosen alias is reserved for the service.","action":"Choose another alias.","scope":"endpoint"},{"status":409,"code":"alias_taken","description":"The alias is claimed or a publication has reserved it.","action":"Choose another alias or check availability again after the publication finishes.","scope":"endpoint"},{"status":409,"code":"already_member","description":"This membership already exists.","action":"Read current memberships before publishing another invitation.","scope":"endpoint"},{"status":409,"code":"grant_used","description":"A verification or membership grant has already been consumed.","action":"Check the resulting card version, then obtain a fresh grant if still needed.","scope":"endpoint"},{"status":409,"code":"identity_exists","description":"An identity already uses this token.","action":"Check the existing publication. Generate a new identity only when a different card is intended.","scope":"endpoint"},{"status":409,"code":"invitation_withdrawn","description":"The organisation no longer offers the invitation.","action":"Ask for a new invitation.","scope":"endpoint"},{"status":409,"code":"key_already_used","description":"A device key already belongs to an identity and cannot be reused by another.","action":"Use the existing card or generate a fresh device key.","scope":"endpoint"},{"status":409,"code":"replayed_nonce","description":"The signing key already used this nonce.","action":"Check whether the previous request succeeded before making a fresh signed request.","scope":"common"},{"status":409,"code":"salt_ticket_invalid","description":"The salt ticket is unknown, expired or already consumed.","action":"Request a fresh ticket and rebuild and sign version one with it.","scope":"endpoint"},{"status":409,"code":"takeover_already_open","description":"A takeover for this linked account is already open.","action":"Read the pending takeover instead of opening another.","scope":"endpoint"},{"status":409,"code":"version_conflict","description":"The version cannot be published against the card’s current state.","action":"Read the latest card, reconcile the intended change and sign a new version.","scope":"endpoint"},{"status":410,"code":"erased","description":"The card existed and was erased or removed. The response also carries its public erasure receipt.","action":"Stop using this card as current authority. Retain only the public receipt if needed.","scope":"endpoint"},{"status":413,"code":"payload_too_large","description":"The request body exceeds this endpoint’s byte limit.","action":"Reduce the encoded body. API-key management accepts at most 8 KiB.","scope":"endpoint"},{"status":422,"code":"grant_expired","description":"The verification or membership grant expired.","action":"Obtain a fresh grant before publishing the version.","scope":"endpoint"},{"status":422,"code":"invalid_grant","description":"The verification or membership grant is invalid or belongs to another operation.","action":"Use the grant issued for this exact card, account or membership.","scope":"endpoint"},{"status":422,"code":"invalid_logo","description":"The image fails type, size, dimensions or content validation.","action":"Correct the image according to `error.message` before uploading again.","scope":"endpoint"},{"status":422,"code":"invalid_op","description":"An operation is unknown, malformed, not one of this card’s type or version, or changes nothing.","action":"Correct the operation named in `error.message`.","scope":"endpoint"},{"status":422,"code":"invalid_record","description":"The identity version violates the signed-record rules.","action":"Correct the validation issue, canonicalise the record and sign it again.","scope":"endpoint"},{"status":422,"code":"invalid_record_signature","description":"The identity-version signature does not verify.","action":"Sign the exact canonical record with its identity-version prefix and declared key.","scope":"endpoint"},{"status":422,"code":"label_mismatch","description":"The label’s prev, body, auth or state is not what the chain, the body and the operations give.","action":"Read the card again, plan the operations on its current state and sign the new label.","scope":"endpoint"},{"status":422,"code":"last_owner","description":"The change would leave an organisation without an accepted owner.","action":"Add or accept another owner before removing the last one.","scope":"endpoint"},{"status":422,"code":"links_need_verification","description":"A new account link has no acceptable verification grant.","action":"Complete the account proof before publishing its link.","scope":"endpoint"},{"status":422,"code":"membership_needs_grant","description":"An organisation membership lacks its acceptance grant.","action":"Accept the invitation and include its grant in the next signed version.","scope":"endpoint"},{"status":422,"code":"not_an_organization","description":"The card is a person where an organisation is required.","action":"Use the person endpoint or an organisation card.","scope":"endpoint"},{"status":429,"code":"rate_limited","description":"An anonymous, signed-request or API-key allowance was exceeded.","action":"Wait at least `Retry-After` seconds. Share a queue and retry budget across your workers.","scope":"common"},{"status":500,"code":"internal_error","description":"An unexpected server error occurred. Internal details are not returned.","action":"Retry reads with bounded backoff. Check write results before sending a new signed operation.","scope":"common"},{"status":502,"code":"log_mismatch","description":"The log response did not match the expected signed entry or proof.","action":"Do not accept the publication as verified. Check the card and log before retrying.","scope":"endpoint"},{"status":503,"code":"busy","description":"The application has reached a temporary concurrency or database limit.","action":"Wait `Retry-After` seconds and retry with bounded backoff.","scope":"common"},{"status":503,"code":"log_unavailable","description":"The public log cannot currently be read, verified or used for publication.","action":"For reads, keep the result unverified and try later. Before retrying a write, read the card to check whether publication completed.","scope":"endpoint"}],"responseHeaders":[{"name":"Content-Type","value":"application/json","description":"Use the declared media type before choosing a parser."},{"name":"Date","value":"HTTP date","description":"Server time. Compare it with your clock when signing requests."},{"name":"Location","value":"relative URL","description":"Published card/proof address, or permanent widget redirect target."},{"name":"Retry-After","value":"integer seconds, on rate_limited or busy","description":"Wait at least this long before retrying. Other 429/503 codes do not necessarily include it."}],"documentationUrl":"https://veil.rip/docs/create-organisation","supportsBrowserFetch":false,"browserMode":"local-or-server"}}