Contracts that fit the shoot, not the other way around

Built from 15 years on set shooting music, editorial, documentary, weddings, and commercial work — answer a few questions, get a tailored draft in under a minute.

Wedding to documentary, one tool

Whether you're shooting a wedding, a family or senior portrait session, commercial work, editorial assignments, a documentary project, or a live music session — pick your shoot type and the questions change to match what that job actually needs.

WHY THIS EXISTS

Built from real jobs, including the ones that went wrong

I've spent the last 15 years shooting music, editorial, and documentary work, the kind of jobs where the contract question isn't "do I need one?" it's "which version do I need this time?" I learned that the hard way: more than once, a client used images well beyond what we'd actually agreed to, because the contract I'd used didn't spell out the limits clearly enough. Sorting that out after the fact meant lawyers, lost time, and money that should never have left my pocket in the first place.

HOW IT WORKS

Three steps, not twenty fields

Pick your shoot type — wedding, family, senior, commercial, editorial, documentary, or music — and the questions change to match. Set your terms: payment, cancellation, delivery timeline, and where it matters, licensing. Get a complete draft in under a minute, ready to review with your own attorney before you send it.

TRY IT FREE

Try it for your next shoot

Pick a shoot type and watch the questions change. Nothing is saved until you choose to send it to yourself. Built for wedding, family, senior, commercial, editorial, documentary, and music shoots — the questions adjust to fit whichever one you pick.

(function(){ const typeConfig = { wedding: { label:'Wedding', fields:[ {id:'secondShooter', label:'Second shooter included', type:'select', options:['No','Yes']}, {id:'engagement', label:'Engagement session included', type:'select', options:['No','Yes']}, {id:'album', label:'Album / prints included', type:'select', options:['No','Yes']}, {id:'imageRights', label:'Image rights', type:'select', options:['Personal-use license (recommended)','Full copyright transfer (buyout)']}, {id:'commercialUse', label:'Client may use images commercially', type:'select', options:['No','Yes']} ]}, family: { label:'Family / portrait', fields:[ {id:'minors', label:'Minors will be photographed', type:'select', options:['No','Yes']}, {id:'imageRights', label:'Image rights', type:'select', options:['Personal-use license (recommended)','Full copyright transfer (buyout)']}, {id:'commercialUse', label:'Client may use images commercially', type:'select', options:['No','Yes']} ]}, senior: { label:'Senior portrait', fields:[ {id:'minors', label:'Subject is a minor', type:'select', options:['Yes','No']}, {id:'imageRights', label:'Image rights', type:'select', options:['Personal-use license (recommended)','Full copyright transfer (buyout)']}, {id:'commercialUse', label:'Client may use images commercially', type:'select', options:['No','Yes']} ]}, commercial: { label:'Creative / commercial', fields:[ {id:'usageScope', label:'Usage scope', type:'select', options:['Print only','Digital & social','Broadcast & advertising','Full buyout']}, {id:'licenseType', label:'License type', type:'select', options:['Limited term (recommended)','Perpetual — use with caution']}, {id:'licenseTermMonths', label:'License term in months (if limited)', type:'number', value:12}, {id:'pricePerImage', label:'Price per image license (USD)', type:'number', value:350}, {id:'bundleOption', label:'Offer bundle pricing', type:'select', options:['No','Yes']}, {id:'bundleDetails', label:'Bundle terms (e.g. 10 images for $2,800)', type:'text'}, {id:'exclusivity', label:'Exclusive to this client', type:'select', options:['No','Yes']} ]}, editorial: { label:'Editorial', fields:[ {id:'publication', label:'Publication / outlet name', type:'text'}, {id:'useType', label:'Use type', type:'select', options:['One-time use','First refusal','Syndication rights']}, {id:'creditRequired', label:'Photographer credit required', type:'select', options:['Yes','No']}, {id:'licenseType', label:'License type', type:'select', options:['Limited term (recommended)','Perpetual — use with caution']}, {id:'pricePerImage', label:'Price per image license (USD)', type:'number', value:150}, {id:'bundleOption', label:'Offer bundle pricing', type:'select', options:['No','Yes']}, {id:'bundleDetails', label:'Bundle terms (e.g. full gallery for $1,200)', type:'text'} ]}, documentary: { label:'Documentary', fields:[ {id:'consentType', label:'Subject consent type', type:'select', options:['Standard release','Limited - subject may withdraw','Anonymized / identity protected']}, {id:'archivalYears', label:'Archival rights (years, 0 = perpetual)', type:'number', value:10} ]}, music: { label:'Music', fields:[ {id:'eventType', label:'Session type', type:'select', options:['Live concert','Studio session','Album artwork / press']}, {id:'labelExclusivity', label:'Exclusive to label/artist', type:'select', options:['No','Yes']}, {id:'promoUse', label:'Promotional use allowed without extra fee', type:'select', options:['Yes','No']} ]} }; function renderTypeFields(){ const type = document.getElementById('fac_shootType').value; const cfg = typeConfig[type]; const wrap = document.getElementById('fac_typeFields'); wrap.innerHTML = '

' + cfg.label + ' details

'; const grid = document.createElement('div'); grid.style.display = 'grid'; grid.style.gridTemplateColumns = 'repeat(auto-fit, minmax(180px, 1fr))'; grid.style.gap = '12px'; cfg.fields.forEach(f => { const col = document.createElement('div'); const lab = document.createElement('label'); lab.textContent = f.label; lab.style.fontSize = '13px'; lab.style.color = '#555'; lab.style.display = 'block'; lab.style.marginBottom = '4px'; col.appendChild(lab); let input; if(f.type === 'select'){ input = document.createElement('select'); f.options.forEach(o => { const opt = document.createElement('option'); opt.value = o; opt.textContent = o; input.appendChild(opt); }); } else { input = document.createElement('input'); input.type = f.type; if(f.value !== undefined) input.value = f.value; } input.id = 'fac_tf_' + f.id; input.style.width = '100%'; input.style.padding = '10px'; input.style.borderRadius = '8px'; input.style.border = '1px solid #ccc'; col.appendChild(input); grid.appendChild(col); }); wrap.appendChild(grid); } function val(id){ const el = document.getElementById(id); return el ? el.value : ''; } function imageRightsClause(){ const lines = []; if(val('fac_tf_imageRights').includes('buyout')){ lines.push('IMAGE RIGHTS: Full copyright in the delivered images transfers to client effective upon receipt of final payment. Photographer relinquishes copyright claims to these images and will not use them for portfolio, marketing, or editorial purposes without client permission.'); } else { lines.push('IMAGE RIGHTS: Client receives a perpetual, personal-use license to print, share, and display delivered images. Photographer retains copyright at all times and may use images for portfolio, marketing, and editorial purposes unless otherwise restricted. This is a license to use, not a transfer of ownership.'); lines.push('COMMERCIAL USE: ' + (val('fac_tf_commercialUse')==='Yes' ? 'Client may use delivered images for their own commercial purposes (e.g. business marketing) without additional licensing fees.' : 'Client may not use delivered images for commercial purposes (e.g. resale, advertising, business marketing) without a separate written license from photographer.')); } return lines.join('\n'); } function licensingClause(){ const lt = val('fac_tf_licenseType'); const isPerpetual = lt.includes('Perpetual'); const term = val('fac_tf_licenseTermMonths'); const price = val('fac_tf_pricePerImage'); const bundleOn = val('fac_tf_bundleOption') === 'Yes'; const bundleDetails = val('fac_tf_bundleDetails'); let lines = []; if(isPerpetual){ lines.push('LICENSE TYPE: This license is granted in perpetuity; client may use licensed images indefinitely under the scope above. Photographer acknowledges this grant cannot be revoked once executed.'); lines.push('NOTE TO PHOTOGRAPHER: consider whether a long renewable term (e.g. 5\u201310 years) better serves your interests, since it preserves renegotiation leverage that a perpetual grant gives up permanently.'); } else { lines.push('LICENSE TYPE: This license is limited to a term of ' + (term || '[term]') + ' months from the delivery date, after which usage must be renewed or renegotiated.'); } lines.push('PRICING: Each individually licensed image is priced at $' + (price || '[price]') + ' per image, in addition to the session/creation fee above.'); if(bundleOn){ lines.push('BUNDLE PRICING: Client may instead select bundle pricing: ' + (bundleDetails || '[bundle terms]') + '. Bundle pricing supersedes individual per-image pricing for images included in the bundle.'); } else { lines.push('BUNDLE PRICING: No bundle pricing is offered; all licensed images are billed individually at the per-image rate above.'); } return lines.join('\n'); } function buildClause(type){ const lines = []; if(type === 'wedding'){ lines.push('SECOND SHOOTER: ' + (val('fac_tf_secondShooter')==='Yes' ? 'A second photographer is included in this package.' : 'No second photographer is included unless added by written amendment.')); lines.push('ENGAGEMENT SESSION: ' + (val('fac_tf_engagement')==='Yes' ? 'One engagement session is included prior to the wedding date.' : 'No engagement session is included in this package.')); lines.push('ALBUM / PRINTS: ' + (val('fac_tf_album')==='Yes' ? 'A printed album and/or prints are included as specified in the package details.' : 'Digital delivery only; albums and prints may be purchased separately.')); lines.push(imageRightsClause()); lines.push('WEATHER / VENUE CONTINGENCY: Photographer is not liable for conditions outside their control (weather, venue restrictions, vendor delays) that affect coverage.'); } else if(type === 'family' || type === 'senior'){ lines.push('MINORS: ' + (val('fac_tf_minors')==='Yes' ? 'A parent or legal guardian must sign this agreement and any required minor release on behalf of the minor subject.' : 'All subjects are adults capable of signing on their own behalf.')); lines.push(imageRightsClause()); } else if(type === 'commercial'){ lines.push('USAGE SCOPE: Client is licensed to use delivered images for ' + val('fac_tf_usageScope').toLowerCase() + ' purposes only, unless expanded by written amendment.'); lines.push('EXCLUSIVITY: ' + (val('fac_tf_exclusivity')==='Yes' ? 'This usage license is exclusive to client; photographer will not license these images to competing parties during the term above.' : 'This license is non-exclusive; photographer retains the right to license these images to other parties.')); lines.push(licensingClause()); } else if(type === 'editorial'){ lines.push('PUBLICATION: Images are licensed for use by ' + (val('fac_tf_publication') || '[publication name]') + '.'); lines.push('USE TYPE: ' + val('fac_tf_useType') + '. Any use beyond this scope, including reuse by third parties, requires a separate licensing agreement.'); lines.push('CREDIT: ' + (val('fac_tf_creditRequired')==='Yes' ? 'Photographer must be credited by name adjacent to each published image.' : 'Credit is requested but not contractually required.')); lines.push('COPYRIGHT: Photographer retains copyright at all times; this is a license to use, not a transfer of ownership.'); lines.push(licensingClause()); } else if(type === 'documentary'){ lines.push('SUBJECT CONSENT: ' + val('fac_tf_consentType') + '.'); lines.push('RIGHT TO WITHDRAW: ' + (val('fac_tf_consentType').includes('Limited') ? 'Subject may withdraw consent for further use of their likeness at any time by written notice; this does not retroactively affect already-published or already-licensed material.' : 'Standard consent terms apply as signed; withdrawal terms are as negotiated separately.')); const arc = val('fac_tf_archivalYears'); lines.push('ARCHIVAL RIGHTS: ' + (Number(arc)===0 ? 'Photographer retains perpetual rights to archive and exhibit this work, including for editorial, gallery, and portfolio use.' : 'Photographer retains rights to archive and exhibit this work for ' + arc + ' years from the date of capture.')); } else if(type === 'music'){ lines.push('SESSION TYPE: ' + val('fac_tf_eventType') + '.'); lines.push('EXCLUSIVITY: ' + (val('fac_tf_labelExclusivity')==='Yes' ? 'Images from this session are exclusive to the artist/label and may not be licensed elsewhere without written consent.' : 'Photographer retains the right to license these images to other outlets unless otherwise restricted.')); lines.push('PROMOTIONAL USE: ' + (val('fac_tf_promoUse')==='Yes' ? 'Artist/label may use delivered images for promotional purposes (social, press, websites) at no additional fee.' : 'Promotional use beyond personal/portfolio reference requires an additional licensing fee.')); } return lines.join('\n'); } function generate(){ const type = document.getElementById('fac_shootType').value; const cfg = typeConfig[type]; const client = val('fac_clientName') || '[Client Name]'; const date = val('fac_shootDate') || '[Shoot Date]'; const fee = val('fac_totalFee') || '[Total Fee]'; const depositPct = val('fac_depositPct') || '0'; const fee_num = Number(val('fac_totalFee')) || 0; const deposit_num = Math.round(fee_num * (Number(depositPct)/100)); const cancelMap = { flexible: 'Client may ca

Get your contract

Drop your email and we'll send what you just built, plus occasional notes on the business side of photography. No spam, unsubscribe anytime.